LinkedIn Posts Exporter
Chrome extension that exports saved LinkedIn posts to Google Docs with engagement analytics. Features scroll automation and OAuth integration.
TL;DR: TL;DR: I built a Chrome extension that exports your saved LinkedIn posts to Google Docs with full engagement analytics. Features automated scrolling to load all posts, reaction breakdowns, and structured formatting.
The Problem
LinkedIn's "Saved Posts" feature is broken for power users:
- No export option: Can't get your saved content out
- Limited search: Can't find specific saved posts
- No analytics: Saved a post because of engagement, but can't see the metrics
- Data loss risk: What if LinkedIn changes or removes the feature?
I save 10-20 posts weekly for research and wanted them in a searchable, permanent format.
My Approach
I built a Chrome extension (Manifest V3) with three components:
- Content script: Injects into LinkedIn, handles DOM scraping with scroll automation
- Background script: Manages OAuth with Google APIs, handles export
- Popup UI: Shows progress and triggers the export workflow
The key insight was using mutation observers to detect when new posts load during scrolling.
Architecture
LinkedIn Posts Exporter - Architecture Diagram
Key Features
- Auto-scroll Loading: Automatically scrolls to load all saved posts
- Engagement Analytics: View counts, reactions, comments captured
- Reaction Breakdown: Like, Love, Celebrate, Insightful, etc.
- Virality Metrics: Engagement velocity and reach estimates
- Structured Export: Organized by date with consistent formatting
- Privacy-first: Only accesses your own saved posts
- Retry Logic: Handles rate limits and network errors
Results & Metrics
| Metric | Value |
|---|---|
| Scroll Delay | 2 seconds between scrolls |
| Data Points per Post | 15+ |
| Reaction Types Captured | 7 |
| Export Format | Google Docs (formatted) |
| Auth Method | OAuth 2.0 |
| Chrome Storage | Tokens + preferences |
What I Learned
The hardest part was reliable DOM scraping on LinkedIn's dynamic page. The HTML structure changes frequently, and posts load asynchronously. I solved this with:
- Multiple selectors: Try several CSS selectors per data point
- Mutation observers: Detect when new posts appear
- Retry logic: Re-attempt extraction on failure
// Robust selector fallback
const extractViews = (postElement) => {
const selectors = [
'[data-test-id="social-counts__views"]',
'.social-details-social-counts__views',
'[aria-label*="views"]'
];
for (const selector of selectors) {
const el = postElement.querySelector(selector);
if (el) return parseNumber(el.textContent);
}
return null;
};
Rate limiting was critical. Scrolling too fast triggers LinkedIn's anti-bot detection. The 2-second delay between scrolls mimics human behavior.
The Google Docs API formatting was tricky—you work with a document model, not HTML. I built a translation layer that converts scraped data into Docs API requests.
Frequently Asked Questions
What problem does this extension solve?
It exports your saved LinkedIn posts to a permanent, searchable Google Doc with full engagement analytics. Great for content research, tracking viral posts, or just backing up bookmarks.
What technologies power this project?
Chrome Extension Manifest V3 with content scripts for DOM access, background service worker for OAuth and API calls, and Google Docs API for formatted export.
Is this against LinkedIn's terms of service?
The extension only accesses your own saved posts (not other users' data) and operates at human-like speeds. It's similar to manually copying posts to a document. However, always review LinkedIn's current ToS for automated access tools.
Frequently Asked Questions
More Projects
View allBuilt by Abhinav Sinha
AI-First Product Manager who builds production-grade tools. Passionate about turning complex problems into elegant solutions using AI, automation, and modern web technologies.