π LinkedIn Engagement & Content Analytics
Pricing
$19.99/month + usage
π LinkedIn Engagement & Content Analytics
LinkedIn Post Scraper extracts posts from public LinkedIn profiles, pages, or companies. Capture text, media, timestamps, reactions, comments, and engagement metrics. Ideal for research, competitor tracking, content analysis, and workflows needing structured LinkedIn post data.
Pricing
$19.99/month + usage
Rating
0.0
(0)
Developer
API Empire
Maintained by CommunityActor stats
6
Bookmarked
81
Total users
0
Monthly active users
6 days ago
Last modified
Categories
Share
LinkedIn Engagement Scraper β Extract Posts, Analytics & Sentiment
LinkedIn Engagement Scraper pulls posts from any public LinkedIn company or person page and layers on engagement scoring, hashtag extraction, sentiment (lexicon or optional AI), and an aggregate analytics summary β reading only each post's public ld+json data, with no LinkedIn login required. Every response is typed, normalized JSON: no HTML, no CSS selectors, no parsing step before you can drop it into a script, a spreadsheet, or an LLM pipeline. Point it at one or many LinkedIn URLs and get back scored, sentiment-labeled posts plus one honest analytics row per run.
What is LinkedIn Engagement Scraper?
LinkedIn Engagement Scraper is an Apify Actor that scrapes public LinkedIn company and person post feeds and adds an analytics layer on top: hashtag extraction, a weighted engagement score, sentiment classification, top-post ranking, and an aggregate summary. It does not require a LinkedIn account, cookies, or login β every field comes from the public ld+json and HTML LinkedIn serves to a logged-out visitor. Its defining trust feature: any identifier or count that isn't genuinely present in that public data β a tracking ID, a comment timestamp, a like count β is returned as null, never a fabricated or hashed stand-in.
- π Scrape public posts from a LinkedIn company or person page, with author, media, mentions, comments, and reactions
- π₯ Compute a per-post
engagementScoreand rank top posts and top hashtags - π Classify sentiment with a free built-in lexicon, or opt into real AI classification (sentiment, topics, B2B lead quality) across seven model providers
- π Get one aggregate analytics row per run β totals, averages, posting cadence, content mix, sentiment distribution
- π¦ Export as JSON, CSV, or any format the Apify dataset supports β no proxy management required by default
What data does LinkedIn Engagement Scraper collect?
The Actor returns three kinds of rows in the same dataset: individual posts, an aggregate analytics summary, and β nested inside both β a hashtag and sentiment breakdown.
| Data Type | Key Fields | JSON Field Names |
|---|---|---|
| Posts | text, author, timestamps, like/comment/share counts, media, mentions | text, authorFullName, postedAtISO, numLikes, numComments, numShares, images, attributes |
| Engagement & content analytics (aggregate) | totals, per-post averages, posting cadence, content-type mix, coverage | totals, averages, postingByWeekday, postingByHourUTC, contentTypeBreakdown, engagementDataCoverage |
| Hashtag & sentiment breakdown | top hashtags, sentiment distribution, ranked top posts | topHashtags, sentimentDistribution, topPosts, sentimentLabel |
Need more LinkedIn data?
If you need employee lists, company competitors, or a broader company profile alongside posts, the API Empire account also publishes Linkedin-Company-Scraper-Scrape-Employees-Competitors-&-Posts. For phone/email-style contact discovery on LinkedIn profiles, see Linkedin-Phone-&-Lead-Scraper. Run them alongside this Actor to combine content analytics with company and contact data in one pipeline.
How does LinkedIn Engagement Scraper differ from the official LinkedIn API?
LinkedIn's own Marketing Developer Platform and Community Management APIs expose engagement data, but only for pages and profiles you administer, and only after your application is reviewed and approved. LinkedIn Engagement Scraper reads the same publicly rendered post data any logged-out visitor sees, for any public company or person page, with no application process.
| Feature | LinkedIn's official APIs | LinkedIn Engagement Scraper |
|---|---|---|
| Access approval | Requires a LinkedIn Developer Program application and partner review | None β starts immediately on Apify |
| Scope of accessible pages | Only pages/profiles you administer or have been granted access to | Any public company or person page URL |
| Authentication | OAuth 2.0 member or company access token | None required (optional Apify/custom proxy) |
| Analytics layer | Raw metrics only β engagement scoring and sentiment must be built by the developer | Built-in engagement score, hashtag ranking, lexicon sentiment, optional AI enrichment |
| Data returned | Metrics scoped to your own organization's page analytics | Public post text, engagement counts, hashtags, sentiment for any public page |
| Setup time | Application review plus an OAuth integration β typically days to weeks | Minutes β supply URLs and start the run |
The official APIs are the right choice when you already administer the LinkedIn page and need first-party, guaranteed-accurate metrics for your own content. LinkedIn Engagement Scraper is the right choice when you need engagement and content analytics on pages you don't administer β competitors, prospects, thought leaders β without waiting on a partner review.
Why do developers and teams scrape LinkedIn?
For AI engineers and agent builders
Post text, hashtags, sentiment, and engagementScore are all pre-computed, typed JSON fields β no need to write a scoring or classification layer before indexing into a vector store. A common workflow: run the Actor against a list of target company pages, push each post plus its sentiment and hashtags into a RAG index, and let an agent answer "what is this company posting about, and how is it landing" directly from the topPosts and topHashtags fields in the analytics row, without touching raw HTML.
For marketers and brand teams
Track what a competitor's company page or an executive's personal page is posting, and how it performs, without manually opening dozens of profiles. Set minEngagement to filter out noise, and the topHashtags and contentTypeBreakdown fields in the analytics row surface which topics and formats are actually landing this run β a faster read than scrolling a feed.
For researchers and analysts
Public post text, postedAtISO timestamps, and sentimentDistribution support studies of organizational communication, professional discourse, or trend cycles on LinkedIn, scoped strictly to what a public page shows a logged-out visitor. scrapeUntil narrows a run to a defined date window, useful for building a comparable dataset across multiple companies or people for the same period.
For developers building data products
engagementScore, hashtags, and the aggregate summary row are structured inputs for a sales-intelligence or content-monitoring product: schedule runs against a list of target company pages, and feed the topPosts and engagementDataCoverage fields straight into a dashboard or alerting pipeline without post-processing raw post objects yourself.
How to scrape LinkedIn (step by step)
- Open the LinkedIn Engagement & Content Analytics Actor (
linkedin-engagement-analytics) in the Apify Console or on the Apify Store. - Provide the required input:
urlsβ one or more LinkedIn company or person URLs. - Set the run's filters:
limit(posts per URL),scrapeUntil(date window),sentiment/aiEnhancement(classification mode),minEngagement(noise filter), andtopN(ranking size). TogglerawDataif you only want plain post objects, ormetricsOnlyif you only want the aggregate row. - Start the run from the Console, or trigger it programmatically via the Apify API/
apify_client. - Download results as JSON or CSV from the dataset, or open the default Posts & Engagement Analytics table view.
What to do when LinkedIn changes its structure
The Actor is maintained, and the output schema is designed to stay stable β field names and types on your end don't change when LinkedIn's page markup does. No specific turnaround time is published for structural fixes; treat the schema, not a fix timeline, as the stable contract.
β¬οΈ Input
| Parameter | Required | Type | Description | Example Value |
|---|---|---|---|---|
urls | Yes | array of string | LinkedIn company or person profile URLs to scrape β one or many. Bare slugs and IDs are accepted too. | ["https://www.linkedin.com/company/google/"] |
limit | No | integer (min 1, default 10) | Maximum number of posts to collect from each URL. limit=10 with 2 URLs β up to 20 posts total. | 10 |
scrapeUntil | No | string (nullable) | Only keep posts published on or after this date. Accepts an absolute date (2026-03-01) or a relative one (e.g. 30 days). Older posts are dropped. | "2026-01-01" |
deepScrape | No | boolean (default true) | Follow per-activity pages discovered on the profile to gather more posts and richer metadata. Recommended. | true |
rawData | No | boolean (default false) | Power-user mode: emit the plain scraped posts with no analytics fields and no summary row. | false |
topN | No | integer (min 1, default 10) | How many top posts and top hashtags to surface in the analytics summary. | 10 |
sentiment | No | boolean (default true) | Run lightweight lexicon sentiment on each post's text (positive/neutral/negative). Superseded by aiEnhancement when that is on. | true |
minEngagement | No | integer (min 0, default 0) | Drop posts whose computed engagementScore (likes + 2Γcomments + 3Γshares) is below this value. 0 keeps all posts. | 0 |
metricsOnly | No | boolean (default false) | Output only the aggregate analytics summary row and omit the individual post rows. | false |
aiEnhancement | No | boolean (default false) | Upgrade the built-in lexicon sentiment into real AI classification: sentiment, topics, and B2B lead-quality per post. Requires an API key. | false |
aiModel | No | string (enum, default "claude-haiku-4-5") | AI model to use when aiEnhancement is on. Provider is auto-detected from the name prefix. | "claude-haiku-4-5" |
aiApiKey | No | string (secret, nullable) | API key for the selected provider. If omitted, the matching environment variable is used. Only used when aiEnhancement is on. | null |
proxyConfiguration | No | object (nullable) | Optional Apify or custom proxy for better reliability and to avoid rate limits. | {"useApifyProxy": false} |
aiModel accepts one enum value per provider, auto-detected from its name prefix: claude-haiku-4-5, claude-sonnet-5, claude-opus-4-8, claude-fable-5 (Anthropic); gpt-4o-mini, gpt-4o, gpt-4.1-mini, gpt-4.1, o3-mini, o1 (OpenAI); gemini-2.0-flash-lite, gemini-2.0-flash, gemini-1.5-pro, gemini-2.5-flash, gemini-2.5-pro (Google); grok-2-latest, grok-3-mini, grok-3, grok-beta (xAI); deepseek-chat, deepseek-reasoner (DeepSeek); sonar, sonar-pro, sonar-reasoning (Perplexity); mistral-small-latest, mistral-large-latest (Mistral).
Example JSON input
{"urls": ["https://www.linkedin.com/company/google/", "https://www.linkedin.com/in/satyanadella"],"limit": 25,"scrapeUntil": "2026-01-01","deepScrape": true,"rawData": false,"topN": 10,"sentiment": true,"minEngagement": 0,"metricsOnly": false,"aiEnhancement": false,"aiModel": "claude-haiku-4-5","aiApiKey": null,"proxyConfiguration": { "useApifyProxy": false }}
Common pitfall: rawData: true returns the plain post objects only β no hashtags, engagementScore, sentiment, or analytics summary row are added in that mode, and topN, sentiment, minEngagement, and metricsOnly are all silently ignored. Leave rawData off (the default) to get the analytics layer.
β¬οΈ Output
Results are typed, normalized JSON written to the Actor's dataset, exportable as JSON, CSV, Excel, or any other format the Apify dataset supports. By default the dataset holds one row per scraped post plus one final aggregate type: "analytics" row; metricsOnly reduces this to just the summary row, and rawData reduces each post to its base scraped fields with no analytics added.
Scraped post (default mode)
{"urn": "urn:li:activity:7297410395815849984","text": "Thrilled to share our latest AI research milestone...","url": "https://www.linkedin.com/feed/update/urn:li:activity:7297410395815849984","postedAtTimestamp": 1742044320000,"postedAtISO": "2026-03-15T14:32:00.000000Z","timeSincePosted": "2d","isRepost": false,"authorType": "Company","authorProfileUrl": "https://www.linkedin.com/company/google/","authorProfileId": "google","authorHeadline": "Company","authorFullName": "Google","image": "https://media.licdn.com/dms/image/example.jpg","type": "image","images": ["https://media.licdn.com/dms/image/example.jpg"],"author": {"firstName": null,"lastName": null,"occupation": "Company","publicId": "google","id": null,"profileId": null,"trackingId": null,"picture": "https://media.licdn.com/dms/image/logo.jpg"},"authorName": "Google","authorTitle": "Company","attributes": [{ "start": 0, "length": 9, "type": "PROFILE_MENTION", "handle": "deepmind" }],"comments": [],"reactions": [],"numShares": 217,"numLikes": 14200,"numComments": 492,"commentsCount": 0,"reactionsCount": 0,"hashtags": ["ai", "research"],"textLength": 612,"wordCount": 98,"engagementScore": 16158,"hasEngagementData": true,"sentiment": { "score": 2, "label": "positive", "positiveHits": 2, "negativeHits": 0, "source": "lexicon" },"sentimentLabel": "positive","scrapedAt": "2026-07-26T09:14:02.123456Z"}
comments and reactions carry only genuinely scraped values β text/author for comments, type/publicId/name for reactions β and are typically empty ([]) on public, unauthenticated LinkedIn pages, since the comment and reactor DOM is rarely rendered without a login. That is honest output, not a bug: commentsCount and reactionsCount always match what's actually in those arrays. numLikes, numComments, and numShares come only from the post's ld+json interactionStatistic block and are null when not present β never a guessed number. When aiEnhancement succeeds, sentiment becomes {"label": ..., "source": "ai", "model": ...} and each post additionally carries topics (array of strings) and leadQuality ("high"/"medium"/"low").
Analytics summary (one row per run, unless metricsOnly reduces the dataset to only this row)
{"type": "analytics","totalPosts": 22,"engagementDataCoverage": { "postsWithCounts": 19, "postsTotal": 22, "fraction": 0.864 },"totals": { "likes": 48210, "comments": 3112, "engagementScore": 61073 },"averages": { "likesPerPost": 2191.36, "commentsPerPost": 141.45, "engagementPerPost": 2776.05 },"topHashtags": [["ai", 6], ["research", 4], ["cloud", 3]],"postingByWeekday": [["Tuesday", 8], ["Thursday", 6], ["Monday", 4]],"postingByHourUTC": [[9, 3], [14, 5], [17, 2]],"contentTypeBreakdown": [["image", 14], ["text", 8]],"sentimentDistribution": [["positive", 12], ["neutral", 8], ["negative", 2]],"topPosts": [{ "url": "https://www.linkedin.com/feed/update/urn:li:activity:7297410395815849984", "urn": "urn:li:activity:7297410395815849984", "engagementScore": 16158, "numLikes": 14200, "numComments": 492, "sentiment": "positive", "textPreview": "Thrilled to share our latest AI research milestone..." }]}
Raw post (rawData: true)
Same base fields as the default post object above, minus every analytics field (hashtags, textLength, wordCount, engagementScore, hasEngagementData, sentiment, sentimentLabel, scrapedAt), plus one extra field: rawHtml β the full HTML of the page the post was parsed from. No analytics summary row is pushed in this mode.
How does LinkedIn Engagement Scraper compare to other LinkedIn scrapers?
| Feature | LinkedIn Engagement Scraper | Generic alternative |
|---|---|---|
| Built-in analytics layer | Engagement scoring, hashtag ranking, sentiment, and optional AI topic/lead-quality β computed automatically every run | apimaestro's comment scraper and unseenuser's post scraper return raw post/comment lists with no scoring or sentiment layer (observed on the Apify Store on 2026-07-26) |
| Login requirement | None β reads public ld+json/HTML only | ahmed-khaled's LinkedIn Profile Engagement Scraper requires exporting and pasting LinkedIn session cookies before every run (observed on the Apify Store on 2026-07-26) |
| Fabricated-ID policy | Unavailable IDs and counts are emitted as null, never a random or hashed stand-in | Not documented by any of the three reviewed competitors (observed on the Apify Store on 2026-07-26) |
| Free-tier result cap | No hard cap in the Actor's own code | unseenuser's LinkedIn Profile Posts Scraper caps free-plan Apify accounts at 50 results per run (observed on the Apify Store on 2026-07-26) |
| Pricing model | Pay-per-event (row_result) | apimaestro and unseenuser also price pay-per-event; ahmed-khaled prices flat-rate per month (observed on the Apify Store on 2026-07-26) |
If you're building an AI agent or RAG pipeline, the built-in analytics layer row is the decision-maker β computing engagement scores and sentiment inside an agent loop from raw post lists is extra brittle logic, not a reliability improvement.
How many results can you scrape with LinkedIn Engagement Scraper?
There is no hard cap in the Actor itself: limit (minimum 1, default 10, no maximum) controls how many posts are collected per URL, so total volume scales as limit Γ number of URLs in urls. Pagination is implemented as a breadth-first crawl over urn:li:activity: IDs discovered on the profile page β when deepScrape is on, the Actor follows each discovered activity URN to its own feed page to collect additional posts and richer metadata, up to limit per source URL. Multiple source URLs are processed one after another, with a short delay between sources. No platform-imposed post-count limit is documented here, since one is not verifiable from the source code. Keep in mind that a large limit combined with deepScrape means more page fetches per URL, not a bigger single request.
Integrate LinkedIn Engagement Scraper and automate your workflow
LinkedIn Engagement Scraper works with any language or tool that can send an HTTP request.
REST API integration
from apify_client import ApifyClientclient = ApifyClient("<YOUR_APIFY_TOKEN>")run_input = {"urls": ["https://www.linkedin.com/company/google/"],"limit": 10,"sentiment": True,"topN": 10,}run = client.actor("linkedin-engagement-analytics").call(run_input=run_input)for item in client.dataset(run["defaultDatasetId"]).iterate_items():print(item.get("type", "post"), item.get("engagementScore"))
Works in Python, Node.js, Go, Ruby, cURL.
Automation platforms (n8n, Make, LangChain)
In n8n, the built-in Apify node can run any Actor by ID β set it to linkedin-engagement-analytics, pass your urls and other inputs, and route the returned dataset items into downstream nodes. In Make, the Apify module's "Run Actor" action takes the same Actor ID and input JSON, letting you wire a scheduled run into a Google Sheets, Notion, or Slack scenario. In LangChain, the ApifyWrapper/ApifyActorsTool integration calls an Actor by ID and loads its dataset directly into a document loader, so post text, sentiment, and hashtags can be indexed into a vector store without a separate parsing step.
Is it legal to scrape LinkedIn?
Yes β LinkedIn Engagement Scraper returns only publicly available data: post content, author names, and engagement counts that LinkedIn already shows to a logged-out visitor on a public company or person page. Because the output includes personal data β author names, headlines, and (when present) commenter and reactor names β data-protection regimes such as GDPR and CCPA apply to how you store, process, and use it, not to the act of reading a public page. Consult legal counsel for commercial use cases involving bulk personal data, especially before using scraped names or headlines for outbound contact or profiling.
Frequently asked questions
Does LinkedIn Engagement Scraper work without a LinkedIn account?
Yes. No LinkedIn login, cookies, or session is required at any point β the Actor requests the public page the same way a logged-out browser would and reads the ld+json and HTML LinkedIn serves in that response.
How often is the scraped data updated?
Every run fetches live. There is no caching layer in the Actor β each run issues fresh HTTP requests to LinkedIn for every URL in urls and parses whatever the page returns at that moment.
What happens if a URL returns no posts or fails to load?
If a source page can't be fetched, or its URL type isn't company, person, or feed (post, school, and group URLs are rejected outright), the Actor logs an error for that source and moves on to the next URL β it does not push an error row to the dataset, so a failed source produces zero rows and is never charged. If a public page loads but has no ld+json post data (a very quiet page, or deepScrape off with no posts in the initial render), you'll simply get fewer posts than limit for that source rather than an error.
Can I scrape private or restricted LinkedIn content?
No. Only content visible on a public LinkedIn company or person page without logging in is returned. A private profile, or a page whose posts require a session to render, will produce no posts for that URL rather than bypassing the restriction.
Does aiEnhancement require my own AI provider account?
Yes. aiEnhancement is opt-in and requires an API key for the model you select in aiModel, supplied via aiApiKey or the matching environment variable (ANTHROPIC_API_KEY, OPENAI_API_KEY, GEMINI_API_KEY, XAI_API_KEY, DEEPSEEK_API_KEY, PERPLEXITY_API_KEY, or MISTRAL_API_KEY). When aiEnhancement is off (the default), sentiment is computed with the built-in lexicon at no extra cost.
Does LinkedIn Engagement Scraper work for AI agent workflows and LLM pipelines?
Yes. It's callable as an HTTP endpoint by any agent framework through the Apify API β every response is typed JSON with stable field names, so there's no HTML or selector parsing step before passing post text, sentiment, and hashtags to an LLM.
How does LinkedIn Engagement Scraper handle LinkedIn's anti-bot defenses?
It retries failed requests (429/500/502/503/504) with exponential backoff and jitter, sends a standard browser User-Agent, and runs fetches through an async worker pool with a concurrency limit so requests aren't fired all at once. The retry count (3 attempts) and base rate-limit delay (1 second, jittered) are fixed in the Actor's code rather than exposed as input parameters. An optional Apify or custom proxy (proxyConfiguration) can be layered on top for additional reliability.
How does LinkedIn Engagement Scraper compare to other LinkedIn scrapers?
See the comparison table above. In short: apimaestro's and unseenuser's LinkedIn Actors return raw post or comment lists without an analytics layer, and ahmed-khaled's requires pasting LinkedIn session cookies before each run β all as observed on the Apify Store on 2026-07-26. LinkedIn Engagement Scraper needs no login and computes engagement scoring, hashtag ranking, and sentiment automatically.
Does LinkedIn Engagement Scraper return data in a format LLMs can use directly?
Yes. Every output is typed, normalized JSON with stable field names β no HTML, no selectors, no parsing step. Pass it directly into an LLM's context window, index it into a vector store, or route it through an agent tool call.
Can I use LinkedIn Engagement Scraper without managing proxies?
Yes. proxyConfiguration is optional and defaults to no proxy ({"useApifyProxy": false}); the Actor runs without any proxy configured. Add an Apify or custom proxy only if you need extra reliability or want to reduce the chance of rate limiting.
What happens when LinkedIn changes its structure or blocks the scraper?
The Actor is maintained, and the output schema stays stable β field names and types on your end don't change when LinkedIn's markup does. No numeric turnaround time is published for fixes after a structural change.
Your feedback
Found a bug or missing a field? We want to know. Open an issue on this Actor's Issues tab in Apify Console, or reach the API Empire team through this Actor's Apify Store page.