LinkedIn Profile Reactions Scraper
Pricing
from $0.96 / 1,000 reaction extracteds
LinkedIn Profile Reactions Scraper
Find which LinkedIn posts a person recently reacted to. Give profile URLs, get each public reaction with post URL, text, author, publish time, engagement counts and media. Batch profiles, dedupe keys, since cutoff. No login or cookies.
Pricing
from $0.96 / 1,000 reaction extracteds
Rating
0.0
(0)
Developer
Automation Lab
Maintained by CommunityActor stats
0
Bookmarked
2
Total users
1
Monthly active users
9 minutes ago
Last modified
Categories
Share
Find out which LinkedIn posts a person recently reacted to. Paste one or more LinkedIn profile URLs and get each public reaction as a structured row: the reaction (like, celebrate, love…), the reacted post URL and text, the post author, when the post was published, its reaction and comment counts, and attached media.
No LinkedIn login, cookies or account are needed. The Actor reads the public Activity → Reactions tab that LinkedIn shows to logged-out visitors.
What does LinkedIn Profile Reactions Scraper do?
For every profile you supply, the Actor:
- opens the public LinkedIn profile page as a logged-out visitor;
- reads the server-rendered Reactions tab of the profile's Activity section;
- saves one row per reaction, newest first, with full post context;
- adds one free outcome row when a profile has no public reactions, is not visible to logged-out visitors, or could not be loaded.
It answers "what is this person engaging with?", not "who reacted to this post?" and not "what did this person comment?".
Who is it for?
- Account-based sales teams checking every week which topics, companies and people their target buyers are engaging with, to time outreach and find conversation openers.
- Founders and creators monitoring which posts influential people in their niche react to.
- Recruiters learning what candidates care about before reaching out.
- Competitive and market researchers seeing which vendor or competitor posts executives at key accounts like.
- RevOps and data teams feeding engagement signals into a CRM, warehouse or alerting workflow.
Why use this LinkedIn reactions scraper?
- Profile-first: start from the people you care about, not from posts.
- Batch many profiles in one run: up to 1,000 unique profiles; duplicates are processed once.
- Stable dedupe key:
activityId=<profile ID>:<post ID>stays identical across runs, so weekly runs can be upserted and diffed. - Incremental cutoff:
sincekeeps only reactions on posts published after a date or "7 days" ago. - Explicit outcomes: every supplied profile ends as reactions or a free
no_public_reactions,profile_unavailable,access_failedornot_processedrow. A blocked page is never reported as "no reactions", and a profile the run could not reach is never silently dropped. - Exact post timestamps: decoded from LinkedIn post IDs, not just "3d ago".
- No account risk: nothing logs in, so no LinkedIn account can be restricted.
What LinkedIn reaction data is extracted?
| Field | Meaning |
|---|---|
status | reaction for a reaction row; no_public_reactions, profile_unavailable, access_failed or not_processed for a per-profile outcome row (these outcome rows cost nothing) |
reactingProfileUrl, reactingProfileSlug, reactingProfileName | The supplied person who reacted |
activityId | Stable profile-plus-post key, e.g. satyanadella:7520880308594917376 |
reactionType | LIKE, PRAISE (celebrate), EMPATHY (love), APPRECIATION (support), INTEREST (insightful), ENTERTAINMENT (funny) or generic REACTION |
actionText | LinkedIn's activity line, e.g. "Satya Nadella liked this" |
reactedPostId, reactedPostUrn, reactedPostUrl | The post the person reacted to |
postText | Text of the reacted post |
postAuthor | Post author name, URL and type (person, company, showcase, school) |
postPublishedAt, postAge | Exact post publication time and LinkedIn's relative age |
reactionCount, commentCount | Engagement on the reacted post |
topReactionTypes | Most common reaction types on the post |
mediaUrls | Image and video-cover URLs of the post |
position | Order on the profile's Reactions tab (1 = most recent) |
message | Explanation on free outcome rows |
scrapedAt | When the row was produced |
How much does it cost to scrape LinkedIn profile reactions?
The Actor uses pay-per-event pricing. You pay only for reactions saved, plus a tiny start fee per run. Empty, unavailable and failed profile rows are free.
| Event | Free plan | Bronze | Silver | Gold+ |
|---|---|---|---|---|
| Run start (once per run) | $0.001 | $0.001 | $0.001 | $0.001 |
| Reaction saved | $0.00184 | $0.0016 | $0.001248 | $0.00096 |
Examples at the Bronze price:
- 1 profile, 5 reactions: $0.001 + 5 × $0.0016 = $0.009
- 25 prospects weekly, about 5 reactions each: $0.001 + 125 × $0.0016 = about $0.20 per week
- 200 accounts, about 5 reactions each: $0.001 + 1,000 × $0.0016 = about $1.60
The number of reactions per profile depends on how active the person is; observed profiles showed 1 to 8 public reactions. To cap spend, lower the per-profile limit or set a maximum cost per run in the run options.
How to scrape the posts a LinkedIn user reacted to
- Open the Actor in Apify Console and click Try for free.
- Paste LinkedIn profile URLs (for example
https://www.linkedin.com/in/satyanadella/) or bare profile IDs into LinkedIn profile URLs. - Optionally set Maximum reactions per profile and Only posts published since (for example
7 days). - Click Start. A run with a few profiles usually finishes in under a minute.
- Open the Reactions view of the dataset, or export JSON, CSV or Excel.
- To monitor weekly, save the input as a Task and add a Schedule.
Input parameters
| Field | Type | Default | Description |
|---|---|---|---|
profileUrls | array of strings | required | Personal profile URLs (linkedin.com/in/...) or public profile IDs. Company, school and post URLs are rejected. Up to 1,000 unique profiles. |
maxItemsPerProfile | integer 1–100 | 20 | Per-profile cap on saved reactions, newest first. |
since | string | empty | Keep only reactions on posts published on/after this date: 2026-10-01, an ISO timestamp, or 7 days / 2 weeks. |
Example input:
{"profileUrls": ["https://www.linkedin.com/in/satyanadella/","https://www.linkedin.com/in/jeffweiner08/"],"maxItemsPerProfile": 20,"since": "30 days"}
Output example
A reaction row from a real run:
{"status": "reaction","reactingProfileUrl": "https://www.linkedin.com/in/satyanadella","reactingProfileSlug": "satyanadella","reactingProfileName": "Satya Nadella","activityId": "satyanadella:7520880308594917376","reactionType": "LIKE","actionText": "Satya Nadella liked this","reactedPostId": "7520880308594917376","reactedPostUrn": "urn:li:activity:7520880308594917376","reactedPostUrl": "https://www.linkedin.com/posts/judsonalthoff_every-quarter-gives-us-an-opportunity-to-activity-7520880308594917376-q9Zz","postText": "Every quarter gives us an opportunity to step back and look at the progress we are making with our customers and partners around the world. ...","postAuthor": {"name": "Judson Althoff","url": "https://www.linkedin.com/in/judsonalthoff","type": "person","headline": null},"postPublishedAt": "2026-10-27T16:13:16.768Z","postAge": "3d","reactionCount": 1389,"commentCount": 94,"topReactionTypes": ["LIKE", "PRAISE", "EMPATHY"],"mediaUrls": ["https://media.licdn.com/dms/image/v2/D4E05AQGWHaILeegb1w/videocover-high/..."],"position": 1,"message": null,"scrapedAt": "2026-10-31T07:20:48.070Z"}
A free outcome row for a profile without public reactions:
{"status": "no_public_reactions","reactingProfileUrl": "https://www.linkedin.com/in/garyvaynerchuk","reactingProfileSlug": "garyvaynerchuk","reactingProfileName": "Gary Vaynerchuk","activityId": null,"reactionType": null,"message": "LinkedIn shows no public reaction activity for this profile to logged-out visitors.","scrapedAt": "2026-10-31T07:20:52.376Z"}
The key-value store also contains RUN_SUMMARY with counts of requested and processed profiles, reactions, outcomes and requests, plus stopReason and notProcessedProfiles when a run stopped early.
Limits and how failures are reported
- Recent reactions only. LinkedIn shows logged-out visitors only a person's most recent public reactions on the profile's Reactions tab, usually 1 to 10. The Actor does not log in, so it cannot page through older reaction history. Run it on a schedule (for example weekly) to build a history over time;
activityIdmakes deduplication easy. - Reaction time is not public.
postPublishedAtis when the post was published. Thesincefilter uses that time. - Generic reactions. When LinkedIn only says "reacted on this",
reactionTypeisREACTION. - Hidden or missing profiles return
profile_unavailable. LinkedIn answers missing profiles the same way it answers blocked visitors, so the Actor confirms with two healthy connections that load other public profiles before it reports a profile as unavailable. - Temporary blocks return
access_failedafter up to five fresh datacenter connections. These rows are free; retry later. - Run timeout. The default timeout is 1 hour, enough for about 1,000 profiles. If the run reaches its timeout first, every profile that did not finish gets a free
not_processedrow,RUN_SUMMARY.notProcessedProfileslists them, and the run ends as failed so schedules notice. Saved reactions stay in the dataset; rerun only the listed profiles. - Your maximum charge limit. If the run reaches the maximum cost you set, it stops, lists the remaining profiles as
not_processedrows and ends as succeeded with a status message, because you chose that limit. A profile that was cut off midway keeps its saved (charged) reactions; itsnot_processedrow says how many were saved and that the rest were not charged.RUN_SUMMARY.partiallyProcessedProfileslists those profiles. - Storage or billing errors. If a charged row cannot be saved after three attempts, the run stops instead of fetching the profile again, so no reaction is charged or saved twice. The profile being saved and all remaining profiles get
not_processedrows (the rows themselves are not charged), and the run fails. If a reaction was charged but its row could not be saved, that profile's row andRUN_SUMMARY.chargedWithoutRowsay so. If even the outcome rows cannot be written, the run still fails andRUN_SUMMARYlists the profiles. - If every profile in a run fails to load, the run ends as failed so schedules and integrations notice.
Integrations and workflows
- Weekly ABM signal feed: schedule a Task with your target buyers and
since: "7 days"; send new rows to Google Sheets, HubSpot or Salesforce through Make, Zapier or n8n. - Slack alerts: trigger a webhook on run success and post reactions on competitor or partner posts to a channel.
- Warehouse sync: load the dataset to BigQuery or Snowflake and upsert on
activityId. - Combine with other data: enrich
postAuthor.urlwith profile data, or pull the full post with a post scraper.
Use the API
cURL:
curl -X POST "https://api.apify.com/v2/acts/automation-lab~linkedin-profile-reaction-activity/run-sync-get-dataset-items?token=$APIFY_TOKEN" \-H "Content-Type: application/json" \-d '{"profileUrls":["https://www.linkedin.com/in/satyanadella/"],"since":"14 days"}'
JavaScript:
import { ApifyClient } from 'apify-client';const client = new ApifyClient({ token: process.env.APIFY_TOKEN });const run = await client.actor('automation-lab/linkedin-profile-reaction-activity').call({profileUrls: ['https://www.linkedin.com/in/satyanadella/', 'jeffweiner08'],maxItemsPerProfile: 20,});const { items } = await client.dataset(run.defaultDatasetId).listItems();console.log(items.filter((row) => row.status === 'reaction'));
Python:
from apify_client import ApifyClientclient = ApifyClient("YOUR_APIFY_TOKEN")run = client.actor("automation-lab/linkedin-profile-reaction-activity").call(run_input={"profileUrls": ["https://www.linkedin.com/in/satyanadella/"], "since": "7 days"})for row in client.dataset(run["defaultDatasetId"]).iterate_items():if row["status"] == "reaction":print(row["reactionType"], row["reactedPostUrl"])
Use with AI agents via MCP
Connect this Actor to Claude Code, Claude Desktop, Cursor or another MCP client through the Apify MCP server.
Claude Code
claude mcp add --transport http apify \"https://mcp.apify.com?tools=automation-lab/linkedin-profile-reaction-activity"
Claude Desktop
Add this server object to the Claude Desktop MCP configuration:
{"mcpServers": {"apify": {"url": "https://mcp.apify.com?tools=automation-lab/linkedin-profile-reaction-activity"}}}
Cursor
Add the same apify server under Settings → MCP in Cursor.
VS Code
Add the same Actor-specific URL to your VS Code MCP server configuration. Your client opens the Apify OAuth flow the first time it connects.
This Actor-specific URL also exposes the helper tools get-actor-run, get-dataset-items, get-key-value-store-record and abort-actor-run, so the server offers more than one tool. List the tools first and use only the ones you need. A reliable agent workflow:
- Start one run and keep its IDs. Keep the returned run ID, status and dataset ID (
defaultDatasetId). These are run details, not results.call-actorwaits at most 45 seconds (waitSecs0–45, default 30), so the run may still be going. - Follow the same run. If the run is not finished, call
get-actor-runfor that same run ID with short backoff (2, 4, 8, then 10 seconds) up to a deadline you choose, such as 120 seconds. Set the client request timeout longer than the server wait. After a client timeout, check the known run again instead of starting a new one. If you never got a run ID, report that rather than rerunning blindly. At the deadline, report the run as still running with its ID and stop polling. - Report failures honestly. If the run fails, times out or is aborted, any rows already in the dataset are a partial result, not a complete answer. Check
statusfornot_processedrows andRUN_SUMMARY(get-key-value-store-record) forstopReason,notProcessedProfilesandpartiallyProcessedProfiles. - Read bounded pages. When the run succeeds, call
get-dataset-itemswith the dataset ID, an explicitlimitandoffset, and only thefieldsyou need (for examplereactingProfileSlug,reactionType,postAuthor,reactedPostUrl,postPublishedAt). Use pages of about 20 rows from offset 0 and stop at a budget such as 100 rows or 64 KiB of result text in the model's context, whichever comes first. Track the source offset, not how many rows you kept after filtering. - Handle large rows.
postTextcan be long. If a page is larger than your byte budget, have the client trim or summarize it before it reaches the model and say so. If your client cannot inspect responses before the model sees them, request fewer rows and fields; it cannot guarantee a hard byte limit. - Say when results are partial. When you stop at a budget, report how many rows you read, the next offset and that the result is truncated. For a full export, download the dataset through the API or an integration outside the model's context.
These page sizes and deadlines are example choices, not Apify defaults. They limit what enters the model's context only; the Actor still collects and stores every row.
Example prompts:
- "Which posts did satyanadella and jeffweiner08 react to in the last 14 days? Group them by post author."
- "For these 20 prospect profiles, list any reactions to posts from our competitors."
Is it legal to scrape LinkedIn reactions?
The Actor reads only information that LinkedIn shows to any logged-out visitor of a public profile. It does not log in, bypass privacy settings or access private data. Reaction data is still personal data: you are responsible for having a lawful basis (for example GDPR legitimate interest), respecting LinkedIn's terms, and not using the data for spam. If in doubt, ask your legal counsel. This Actor is not affiliated with or endorsed by LinkedIn.
Data handling and error diagnostics
Requests pass through Apify Proxy to LinkedIn. Page bodies and guest session cookies are processed in memory only; results stay in your Apify run storage under your account's retention settings, and you can delete the dataset and key-value store at any time. The Actor keeps no external history or cache.
Failed operations send sanitized diagnostic input, exceptions and Actor/build/run IDs to our private GlitchTip service so we can fix problems. Secret fields and URL queries are removed, raw page bodies and cookies are never sent, and reports are retained for 30 days. Expected empty profiles and ordinary retries are not error reports.
FAQ
Why do I get only a few reactions per profile? LinkedIn shows logged-out visitors only the most recent public reactions on the profile (usually 1 to 10). Schedule the Actor to collect new reactions over time.
Why did a profile return no_public_reactions?
The profile loaded, but LinkedIn shows no public reactions for it. Some people hide their activity or rarely react.
Why did a profile return access_failed?
LinkedIn refused several fresh connections. The row is free; rerun later.
Can I scrape company page reactions?
No. Only personal profiles (linkedin.com/in/...) have a reactions activity tab.
Does since filter by when the person reacted?
No. LinkedIn does not publish reaction times, so since uses the reacted post's publication time.
Related LinkedIn scrapers
- LinkedIn Profile Posts Scraper: posts written by a profile.
- LinkedIn Profile Activity Time Scraper: when a profile was last publicly active.
- LinkedIn Profile Scraper: profile details for enrichment.
- LinkedIn Post Scraper: full details of a post URL.