LinkedIn Post Comments Scraper By Keyword & Engagement Filter avatar

LinkedIn Post Comments Scraper By Keyword & Engagement Filter

Pricing

from $3.99 / 1,000 results

Go to Apify Store
LinkedIn Post Comments Scraper By Keyword & Engagement Filter

LinkedIn Post Comments Scraper By Keyword & Engagement Filter

๐Ÿ’ฌ Scrape LinkedIn post comments & replies in bulk. ๐Ÿ‘ Get likes, reactions, author names & profile links. ๐Ÿ“… Filter by date. ๐Ÿ”— Add multiple posts at once. No login required by default.

Pricing

from $3.99 / 1,000 results

Rating

0.0

(0)

Developer

Scrapio

Scrapio

Maintained by Community

Actor stats

0

Bookmarked

3

Total users

0

Monthly active users

a day ago

Last modified

Share

LinkedIn Comment Scraper โ€” Comments, Buying Signals & Contacts

A LinkedIn comment scraper that returns typed JSON, not a raw comment dump: point it at LinkedIn post URLs and it pulls every top-level comment, narrows the set with a filter stack (keyword, reactions, length, author, exact date range), then scores each survivor 0โ€“100 for buying intent against a fully auditable keyword lexicon โ€” no model, no black box. Every kept row also carries any email, phone number, mention or hashtag found inside the comment text. Unlike scraping frameworks that hand back raw HTML for you to parse, this Actor returns typed JSON โ€” ready for a CRM, a spreadsheet, or an LLM prompt with no cleanup step. Below: every input parameter, every output field read from the source code, and how sales, growth and research teams actually run it.

๐Ÿงญ What Does This LinkedIn Comment Scraper Do?

It scrapes comments from one or more LinkedIn posts, runs a deterministic keyword-and-reaction filter stack over them before anything is saved, then attaches a 0โ€“100 buying-signal score, a tier label, in-text contact extraction, mentions and hashtags to every row that survives. No LinkedIn account or login is required โ€” the default engine is the logged-out public post page. Supplying a LinkedIn li_at session cookie is optional and only changes what the Actor can reach (more comments per post, nested replies, commenter headline and picture), not whether it runs at all.

  • Scrapes top-level comments from public LinkedIn posts by URL, activity URN, or bare numeric activity ID
  • Filters comments by keyword match/exclude, minimum reactions, minimum length, post-author exclusion, and an exact date range before any row is written
  • Scores every surviving comment 0โ€“100 for buying intent with a named, weighted, auditable term match
  • Extracts in-text email addresses, phone numbers, URLs, @mentions and #hashtags from the comment body
  • Optionally escalates to LinkedIn's authenticated comment engine with a supplied li_at cookie to reach the full comment list and nested replies
  • Optionally adds AI-generated sentiment, an intent label and a short summary per comment, using your own API key for a provider of your choice

โšก Features & Capabilities

Core features

  • Dual engine, one output shape. The default logged-out engine (sourceEngine: "public_page") parses the same LinkedIn post page an anonymous visitor sees โ€” comment text, exact absolute UTC timestamp, per-comment reaction count, author name, author profile URL and avatar, all read from two independent, cross-checked surfaces on that one response (the page's application/ld+json block and the server-rendered comment DOM). Supplying liAtCookie escalates to the authenticated Voyager GraphQL engine (sourceEngine: "voyager"), which reaches the full paginated comment list and nested replies.
  • Filter before you pay. filterKeywords, excludeKeywords, minReactions, minCommentLength, excludeAuthorComments, postedFrom/postedTo/postedLimit and minBuyingSignalScore are all applied before a row is written to the dataset โ€” the filtered-out comments never appear in the output and are not billed.
  • Deterministic buying-signal scoring, no API key. buyingSignalScore, buyingSignalTier, buyingSignalMatches and buyingSignalReasons are computed by a fixed keyword lexicon (signals.py) โ€” every point on the score traces back to a literal phrase, its category and its weight.
  • In-text contact extraction. contactInTextEmail, contactInTextPhone, contactInTextUrl (plus the full contactEmailsInText / contactPhonesInText / contactUrlsInText arrays) are pulled from the comment body with regexes hardened against known false positives โ€” an @handle is never read as an email, and a bare licence or ID number is never read as a phone number.
  • Honest coverage reporting. Every row carries commentsAvailable (comments actually scanned), commentsTotal (the post's real comment count, read from LinkedIn's own page metadata) and commentsCoveragePct โ€” so a partial slice is always visible, never silently hidden.

How this LinkedIn comment scraper compares to other options

FeatureThis Actorapimaestro (no-cookies)benjarapi
Output formatTyped JSON, stable schemaTyped JSONTyped JSON
Keyword/reaction/length pre-filteringโœ… Built in, applied before saveโŒ Not documentedโŒ Not documented
Deterministic buying-intent scoreโœ… 0โ€“100, auditable term listโŒ Not documentedโŒ Not documented
In-text email/phone/URL extractionโœ… Built inโŒ Not documentedโŒ Not documented
Exact date-range filterโœ… postedFrom/postedToโŒ Not documentedโŒ Not documented
Logged-out (no cookie) by defaultโœ…โœ…Not documented (implies login-based access)
Nested reply extractionโœ… With li_at cookieโœ…โœ…
Optional AI sentiment/intent/summaryโœ… Bring your own key, off by defaultโŒ Not documentedโŒ Not documented

Comparison built from each competitor's own Apify Store listing, checked 2026-07-26. If your use case is feeding structured comment data to an LLM or a CRM enrichment step, the pre-filtering and scoring rows are the decision-maker โ€” piping thousands of unscored raw comments into an agent loop and asking it to find the three that matter is a reliability failure mode, not a feature.

When another tool might suit you better

If you need every comment and reply on a viral post with tens of thousands of comments and no interest in filtering or scoring โ€” just a full export โ€” a batch-oriented scraper built around raw volume, such as apimaestro's no-cookies comment scraper (4,336 users, 663,413 runs as observed on its Apify Store listing, checked 2026-07-26), is a reasonable fit. This Actor is built around narrowing the set down to the comments that matter for outreach, not around maximizing raw comment count per run, and its default logged-out engine caps out around 9โ€“10 top-level comments per post before a li_at cookie is supplied.

LinkedIn Comment Scraper within the Scrapio data stack

This Actor covers post comments and their buying-intent scoring. For monitoring LinkedIn posts themselves for new brand or keyword mentions over time, use LinkedIn Post Keyword Monitor. For scoring the credibility of a commenter's or prospect's profile rather than their comment, use LinkedIn Profile Credibility Scraper. Both are Scrapio Actors and share this Actor's logged-out-first approach to LinkedIn.

Why do developers and data teams scrape LinkedIn comments?

Comment sections under company and founder posts are one of the few places B2B buying intent shows up unprompted, in public, in the prospect's own words โ€” before a demo request ever reaches a CRM.

๐Ÿข Sales development and demand generation

An SDR team points the Actor at a competitor's or an industry influencer's recent posts, sets filterKeywords to commercial terms ("pricing", "demo", "how much"), and reads back rows where buyingSignalScore is 50 or higher. authorProfileSlug and author.profile_url go straight into a CRM lookup or a Sales Navigator search; contactInTextEmail sometimes shortcuts that step entirely when a commenter drops their address in the thread.

๐Ÿ“Š AI training data and RAG indexing

text, buyingSignalReasons and (when AI enrichment is on) summary are the high-information fields for both use cases: RAG enrichment, where text plus the scored buyingSignalMatches give a retrieval system pre-labeled intent signal rather than raw prose to re-classify at query time; and training-data construction, where buyingSignalTier, isQuestion and sentiment are already-typed labels with a consistent enum across every row, needing no normalization pass before they hit a training set.

๐Ÿ“ฑ Competitive and market intelligence

Run the Actor against a competitor's product-launch or pricing-announcement posts and track buyingSignalScore distribution and mentions/hashtags volume over time โ€” a spike in pricing-tier comments (buyingSignalMatches category pricing) under a competitor's post is a leading indicator worth watching before it shows up in a win/loss report.

๐Ÿ”ฌ Research and academic use

Social and market researchers studying public discourse patterns, engagement dynamics or B2B communication norms on professional networks can build a dataset from text, stats.total_reactions, commentCreatedAt and isQuestion across a set of posts. Scope is public-comment data only โ€” no private groups, no messages, no content behind LinkedIn's login wall.

๐ŸŽฅ Product and SaaS development

Lead-scoring tools, social-listening dashboards and CRM-enrichment plugins can be built directly on this Actor's output: buyingSignalScore and buyingSignalTier slot into a lead-priority field, contactInTextEmail/contactInTextPhone populate an enrichment record, and sourceEngine plus commentsCoveragePct let a downstream product be honest with its own users about data completeness.

๐Ÿš Input Parameters

All fields are optional โ€” the Actor runs with an empty input and does nothing until postUrls is supplied. Parameter names, types, defaults and constraints below are copied exactly from .actor/actor.json.

ParameterRequiredTypeConstraintsDescription
postUrlsNoarray (string list)default []One or more LinkedIn post URLs, activity URNs or bare activity IDs. Each post is scanned separately.
commentsPerPostNointegermin 1, max 500, default 10Top-level comments to pull per post before filtering. Logged-out, the public page serves roughly 9โ€“10 regardless of this value; a li_at cookie raises the ceiling.
filterKeywordsNoarray (string list)default []Case-insensitive. A comment is kept only if its text contains at least one of these. Empty = keep everything.
excludeKeywordsNoarray (string list)default []Case-insensitive. Drops comments containing any of these โ€” useful for stripping congratulation noise.
minReactionsNointegermin 0, default 0Keep only comments with at least this many reactions.
minCommentLengthNointegermin 0, default 0Minimum comment length in characters โ€” the cheapest way to drop one-word replies and emoji-only comments.
excludeAuthorCommentsNobooleandefault falseDrops comments written by the post's own author.
postedFromNostring (datepicker)absolute or relativeComments posted on or after this date. Accepts 2025-01-27, an ISO timestamp, or a relative value like "7 days".
postedToNostring (datepicker)absolute or relativeComments posted on or before this date. Same accepted formats as postedFrom.
postedLimitNostring (select)enum: any, 24h, week, month, 3months, 6months, year; default anyA coarse age bucket applied on top of the exact date range โ€” it can only tighten the lower bound, never widen it.
minBuyingSignalScoreNointegermin 0, max 100, default 0Keep only comments scoring at least this much. 25+ means one real intent term fired; 50+ means several.
buyingSignalKeywordsNoarray (string list)default []Your own intent terms, added to the built-in lexicon. Each is worth 20 points and reported by name in the score breakdown.
aiEnrichmentNobooleandefault falseAdds AI sentiment, an intent label and a short summary per comment. Off by default; requires your own provider API key.
aiModelNostring (select)enum: claude-haiku-4-5, claude-sonnet-5, claude-opus-4-8, gpt-4o-mini, gpt-4o, gpt-4.1-mini, o3-mini, gemini-2.0-flash-lite, gemini-2.0-flash, gemini-2.5-flash, grok-3-mini, deepseek-chat, sonar, mistral-small-latest; default claude-haiku-4-5Provider is auto-detected from the model name prefix.
aiApiKeyNostring (text field, secret)โ€”Your own key for the provider chosen above. Falls back to a matching environment variable. Leave empty to keep AI off. This field is flagged isSecret in the Actor's schema โ€” the Apify Console masks it in the UI and in logs.
includeRepliesNobooleandefault falseIncludes nested replies. Only reachable through the authenticated engine โ€” requires a li_at cookie.
authorDetailLevelNostring (select)enum: short, full; default shortfull adds commenter headline and profile picture, but only on the authenticated engine. Logged-out, LinkedIn does not expose headline data at all, so it stays null regardless of this setting.
liAtCookieNostring (text field, secret)โ€”Optional. Without it the Actor runs fully logged-out. With it, the authenticated engine reaches the full comment list and nested replies. This field is flagged isSecret in the Actor's schema โ€” treat it like a password, never commit it to a repo or share it in a support ticket screenshot.
proxyConfigurationNoobject (proxy editor)prefill {"useApifyProxy": false}Optional. No proxy is used by default; the Actor escalates direct โ†’ datacenter โ†’ residential on its own when LinkedIn returns its HTTP 999 throttle response.

aiApiKey and liAtCookie are the only two credential-shaped fields in this schema, and both carry isSecret: true โ€” meaning the Apify platform stores and displays them as masked values, not plaintext. Neither is required to run the Actor.

Example input (JSON)

{
"postUrls": [
"https://www.linkedin.com/feed/update/urn:li:activity:7289521182721093633/"
],
"commentsPerPost": 50,
"filterKeywords": ["pricing", "demo", "how much"],
"excludeKeywords": ["congrats", "great post"],
"minReactions": 2,
"minCommentLength": 40,
"excludeAuthorComments": true,
"postedFrom": "30 days",
"minBuyingSignalScore": 25,
"buyingSignalKeywords": ["switch from", "migrate off", "renewal"],
"aiEnrichment": false,
"proxyConfiguration": { "useApifyProxy": true }
}

Supported URL types and input formats

postUrls accepts three shapes, matched by the same parser used across the array:

  • A full activity URL: https://www.linkedin.com/feed/update/urn:li:activity:7289521182721093633/
  • A bare numeric activity ID: 7289521182721093633
  • A structured {"url": "..."} object, for compatibility with the base actor's original startUrls input shape

The base actor's original field names โ€” startUrls, resultLimitPerPost, scrapeReplies, profileScraperMode, liAt โ€” are still accepted as aliases alongside the renamed fields in the table above, in case you are migrating an existing input JSON.

๐Ÿ“ฆ Output Format

Every run pushes one JSON row per surviving comment to the default dataset โ€” typed, normalized, and stable across runs. Rows export to JSON, CSV, Excel, HTML table, or any other format the Apify platform's dataset export supports; there is no separate export mechanism specific to this Actor.

Output for a comment (the primary row)

This is the complete row shape written by the row-assembly function in main.py, with realistic example values. All 45 keys below are present on every successful row (an unsuccessful post produces a smaller accounting row instead โ€” see below).

{
"comment_id": "7289521199876543210",
"text": "This looks great โ€” what's the pricing for a team of 20? Would love to book a demo this week.",
"posted_at": {
"timestamp": 1737936000000,
"date": "2025-01-27 00:00:00",
"relative": "5mo"
},
"is_edited": null,
"is_pinned": null,
"comment_url": "https://www.linkedin.com/feed/update/urn:li:activity:7289521182721093633/?commentUrn=urn%3Ali%3Acomment%3A%28urn%3Ali%3Aactivity%3A7289521182721093633%2C7289521199876543210%29",
"author": {
"name": "Dana Rivera",
"headline": null,
"profile_url": "https://www.linkedin.com/in/danarivera/",
"profile_picture": "https://media.licdn.com/dms/image/D4E03AQ.../profile-displayphoto-shrink_100_100/"
},
"stats": {
"total_reactions": 14,
"reactions": { "like": null, "appreciation": null, "empathy": null, "interest": null, "praise": null },
"comments": null
},
"replies": [],
"post_input": "7289521182721093633",
"totalComments": 62,
"postUrl": "https://www.linkedin.com/feed/update/urn:li:activity:7289521182721093633/",
"sourceEngine": "public_page",
"commentCreatedAt": "2025-01-27T00:00:00Z",
"commentRelativeAge": "5mo",
"authorProfileSlug": "danarivera",
"commentsAvailable": 9,
"commentsTotal": 62,
"commentsCoveragePct": 14.52,
"commentsKeptAfterFilters": 3,
"postAuthorName": "Acme SaaS",
"postAuthorProfileUrl": "https://www.linkedin.com/company/acme-saas/",
"postPublishedAt": "2025-01-20T14:00:00.000Z",
"isPostAuthorComment": false,
"isQuestion": true,
"buyingSignalScore": 60,
"buyingSignalTier": "high",
"buyingSignalMatches": [
{ "term": "pricing", "category": "pricing", "weight": 25 },
{ "term": "book a call", "category": "demo_or_call", "weight": 25 }
],
"buyingSignalReasons": [
"is_question:+10",
"pricing:'pricing':+25",
"demo_or_call:'book a call':+25"
],
"contactInTextEmail": null,
"contactInTextPhone": null,
"contactInTextUrl": null,
"contactEmailsInText": [],
"contactPhonesInText": [],
"contactUrlsInText": [],
"mentions": [],
"hashtags": [],
"commentLength": 95,
"sentiment": null,
"intentLabel": null,
"summary": null,
"aiEnriched": false,
"errorReason": null,
"scrapedAt": "2026-07-26T09:00:00Z",
"runId": "a1B2c3D4e5F6g7H8"
}

is_edited, is_pinned and the per-type stats.reactions breakdown are null on the logged-out engine โ€” the guest page carries no edited/pinned markers and no reaction-type split, so the Actor reports null rather than fabricating false or 0. On the authenticated (voyager) engine these fields are populated with real booleans and per-type counts.

When AI enrichment is on and a usable key is supplied, the three AI columns populate instead of staying null:

{
"sentiment": "positive",
"intentLabel": "buying_intent",
"summary": "Asks for team pricing and wants to book a demo this week.",
"aiEnriched": true
}

Output for a nested reply (only with li_at + includeReplies)

Replies live inside a comment's replies array and are only populated on the authenticated engine. A reply carries the same base identity, timing and stats fields as a top-level comment, but not the buying-signal, contact-extraction or AI layer โ€” only top-level comments are filtered and scored.

{
"comment_id": "7289521199876543299",
"text": "Following up โ€” sent you a DM with our deck.",
"posted_at": { "timestamp": 1737939600000, "date": "2025-01-27 01:00:00", "relative": "5mo" },
"is_edited": false,
"is_pinned": false,
"comment_url": "https://www.linkedin.com/feed/update/urn:li:ugcPost:7289521182721093633?commentUrn=urn%3Ali%3Acomment%3A...",
"author": {
"name": "Sam Patel",
"headline": null,
"profile_url": "https://www.linkedin.com/in/sampatel",
"profile_picture": null
},
"stats": {
"total_reactions": 2,
"reactions": { "like": 2, "appreciation": 0, "empathy": 0, "interest": 0, "praise": 0 },
"comments": 0
},
"replies": [],
"post_input": "7289521182721093633",
"totalComments": 62
}

headline and profile_picture stay null here because authorDetailLevel defaults to short; set it to full to populate them for replies reached through the authenticated engine.

Accounting rows (no comments collected)

When a post URL can't be parsed, or LinkedIn's guest page blocks the request, or no comments survive collection, the Actor still writes one row so the run's log is complete โ€” with an errorReason (invalid_input, http_999, http_429, login_required, blocked_no_container, network_error, fetch_failed, or no_comments) and an errorMessage string, and every other field null, 0 or empty:

{
"comment_id": null,
"text": null,
"postUrl": "https://www.linkedin.com/feed/update/urn:li:activity:7289521182721093633/",
"sourceEngine": "public_page",
"commentsAvailable": 0,
"commentsKeptAfterFilters": 0,
"buyingSignalScore": null,
"errorReason": "blocked_no_container",
"errorMessage": "No comments were collected for this post (blocked_no_container).",
"scrapedAt": "2026-07-26T09:03:11Z"
}

These accounting rows are pushed without the row_result charged event โ€” only rows with errorReason: null (i.e. an actual scraped, filtered, scored comment) are billed under the row_result pay-per-event. To exclude accounting rows from a downstream count or export, filter on errorReason == null.

Schema stability and export options

Field names in the table above are stable across runs and are not renamed when LinkedIn changes its front-end markup โ€” the guest engine's HTML parsing (guest.py) and the authenticated GraphQL parsing (extractor.py) are isolated from the output row shape in main.py, so a LinkedIn markup change is absorbed inside the parser, not surfaced as a schema break. Results export from the Apify platform's dataset view as JSON, CSV, Excel/XLSX, or an HTML table, and are reachable via the Apify API or the apify-client SDKs in any language.

๐Ÿ’ก LinkedIn Comment Scraper Strategy Guide

๐ŸŽฏ Strategy 1: Real-time lead-signal enrichment

Trigger the Actor whenever a tracked account or founder publishes a new post โ€” a scheduled hourly run against a small watch-list of postUrls is the simplest version. For each run, filter the output on buyingSignalScore >= 50 and errorReason == null, then write author.name, author.profile_url, contactInTextEmail, buyingSignalReasons and text back to a CRM or a Slack alert. Because filtering happens before the row is saved, the enrichment step reads a short list, not a raw comment dump.

๐ŸŽฏ Strategy 2: Scheduled monitoring and alerting

Use an Apify Schedule to re-run the Actor daily or weekly against the same set of postUrls with postedLimit set to "24h" or "week" so only new comments are pulled each run. Diff the new dataset against the previous run's comment_id values, and alert on any new row where buyingSignalTier is "high" or "very_high" โ€” a spike in high-tier comments under a competitor's post is worth a same-day look, not a weekly digest.

๐ŸŽฏ Strategy 3: Bulk dataset build for outreach or research

Feed a list of post URLs (one per line in postUrls) covering a target account's or an industry hashtag's recent activity, run once with generous filters (minCommentLength low, minBuyingSignalScore at 0) to keep everything scored but nothing dropped, then aggregate the resulting dataset to CSV for a research corpus or an outreach list sorted by buyingSignalScore descending. No concurrency limit is documented for this Actor beyond the per-post commentsPerPost cap and the sequential 1โ€“2 second delay the Actor applies between posts in a single run.

Strategy comparison at a glance

StrategyBest forRun patternOutput format
Real-time enrichmentSDR/sales teams working a small watch-listTriggered or hourly run, tight filtersFiltered rows to CRM/Slack
Scheduled monitoringCompetitive intelligence, brand trackingDaily/weekly Apify Schedule, postedLimit narrowDiffed dataset, alert on high tier
Bulk dataset buildResearch corpora, outreach listsOne-off run, loose filters, wide postUrls listFull dataset exported to CSV
ScraperWhat it extracts
LinkedIn Post Keyword MonitorMonitors public LinkedIn posts for brand, product and keyword mentions, flagging what's new since the last scheduled run
LinkedIn Profile Credibility ScraperScores a public LinkedIn profile 0โ€“100 for credibility and extracts its recommendations
Instagram Comment Sentiment ScraperCross-platform equivalent: scores Instagram post/reel comments for sentiment, emotion and topic
Instagram Phone Lead ValidatorComplementary contact-validation step for phone numbers surfaced during lead-qualification workflows

How to integrate this LinkedIn comment scraper with your stack

This Actor works with any language or tool that can make an HTTP request โ€” it runs on the Apify platform and is reachable through the Apify API or an official apify-client SDK.

Python

from apify_client import ApifyClient
client = ApifyClient("<YOUR_APIFY_TOKEN>")
run_input = {
"postUrls": [
"https://www.linkedin.com/feed/update/urn:li:activity:7289521182721093633/",
],
"filterKeywords": ["pricing", "demo"],
"minBuyingSignalScore": 25,
}
run = client.actor("<YOUR_USERNAME>/linkedin-post-comments-scraper-buying-signal-detection").call(
run_input=run_input
)
rows = []
for item in client.dataset(run["defaultDatasetId"]).iterate_items():
if item.get("errorReason") is None:
rows.append(item)
import csv
with open("linkedin_comments.csv", "w", newline="", encoding="utf-8") as f:
writer = csv.DictWriter(f, fieldnames=[
"text", "author", "buyingSignalScore", "buyingSignalTier", "contactInTextEmail",
])
writer.writeheader()
for row in rows:
writer.writerow({
"text": row.get("text"),
"author": (row.get("author") or {}).get("name"),
"buyingSignalScore": row.get("buyingSignalScore"),
"buyingSignalTier": row.get("buyingSignalTier"),
"contactInTextEmail": row.get("contactInTextEmail"),
})
print(f"Saved {len(rows)} scored comments to linkedin_comments.csv")

Node.js

import { ApifyClient } from 'apify-client';
const client = new ApifyClient({ token: '<YOUR_APIFY_TOKEN>' });
const run = await client.actor('<YOUR_USERNAME>/linkedin-post-comments-scraper-buying-signal-detection').call({
postUrls: ['https://www.linkedin.com/feed/update/urn:li:activity:7289521182721093633/'],
minBuyingSignalScore: 25,
});
const { items } = await client.dataset(run.defaultDatasetId).listItems();
const highIntent = items.filter((row) => row.errorReason === null && row.buyingSignalScore >= 50);
console.log(`${highIntent.length} high-intent comments out of ${items.length} rows`);

Async and scheduled pipelines

Every run is an Apify Actor run: start it asynchronously through apify_client/apify-client and poll run.status or wait on client.run(runId).wait_for_finish(), or attach an Apify webhook to the run for a fire-and-forget notification when it finishes. For recurring monitoring, an Apify Schedule re-runs the Actor on a cron expression without any polling code at all.

๐ŸŽฏ Who Needs This LinkedIn Comment Scraper? (Use Cases & Industries)

๐Ÿข Sales development and B2B growth teams

An SDR targeting a named-account list runs the Actor against that account's recent posts with filterKeywords set to buying-language terms, then works the output sorted by buyingSignalScore โ€” author.profile_url for the Sales Navigator lookup, contactInTextEmail when a commenter left one, buyingSignalReasons as the exact talking point to reference in outreach.

๐Ÿ“Š RevOps and marketing analysts

Analysts track buyingSignalTier distribution across a set of monitored posts week over week to quantify how much public buying signal a content or ad campaign is actually generating, independent of vanity metrics like raw comment count.

๐Ÿ“ฑ Competitive intelligence teams

Running the Actor against a competitor's launch or pricing posts and reading buyingSignalMatches for the pricing and purchase_intent categories surfaces market reaction โ€” objection language, comparison shopping, timeline pressure โ€” before it reaches a win/loss report.

๐Ÿ”ฌ Researchers

Academic and market researchers studying professional-network discourse can build a public-data-only corpus from text, commentCreatedAt, stats.total_reactions and isQuestion across a defined set of posts, with no login and no access to private groups or messages.

๐ŸŽฅ Product and lead-gen tool builders

Teams building a lead-scoring dashboard or a social-selling browser extension can wire this Actor's buyingSignalScore, buyingSignalTier and contact fields directly into a product's data layer rather than building and maintaining their own LinkedIn parser and keyword lexicon.

Scraping publicly accessible data is generally lawful in the United States: in hiQ Labs, Inc. v. LinkedIn Corp., 938 F.3d 985 (9th Cir. 2019), the Ninth Circuit held that scraping data LinkedIn had made publicly viewable likely does not violate the Computer Fraud and Abuse Act. That case concerned public LinkedIn profile data specifically, and legal standards vary by jurisdiction and by what is scraped, so it should not be read as blanket clearance.

Separately, scraping may still breach LinkedIn's own Terms of Service, which is a contract and civil-risk question, not a criminal one โ€” this Actor's default logged-out mode reduces but does not eliminate that exposure, and using a personal li_at cookie escalates it further by tying the request to an authenticated account.

Because this Actor returns commenter names, profile URLs and avatars, its output is personal data under GDPR and CCPA-style frameworks, even though the source is public. This Actor returns only publicly accessible data. What you do with that data is your responsibility โ€” consult legal counsel for commercial applications involving personal data.

โ“ Frequently asked questions

Does this LinkedIn comment scraper work without a LinkedIn account?

Yes. The default engine is the logged-out public post page and needs no account, cookie or browser. Supplying liAtCookie is an optional escalation that unlocks the full comment list, nested replies, and commenter headline/picture on authorDetailLevel: "full" โ€” it is never required to get a result.

How does it handle LinkedIn's anti-scraping measures?

The Actor treats an HTTP 200 response as unreliable on its own โ€” a LinkedIn guest wall answers 200 with a normal-looking page โ€” so it only accepts a guest page when the actual comment container or the post's structured-data node is present, and rejects any response whose final URL resolved to a login or signup wall. On LinkedIn's HTTP 999 throttle signal (or a 429), it retries with escalating proxy tiers โ€” none โ†’ datacenter โ†’ residential, up to two residential attempts โ€” rather than failing the post outright.

Can I run this at scale without getting blocked?

The Actor applies a randomized 1โ€“2 second delay between posts within a single run and escalates proxy tiers automatically on a block; no uptime or success-rate figure is published for running many posts in a single job, and none should be assumed. Supplying your own residential proxy via proxyConfiguration gives the retry ladder a stronger starting point.

How fresh is the data this Actor returns?

Every run performs a live fetch of the post page (or the authenticated GraphQL endpoint) at run time โ€” nothing is cached or served from a prior run's snapshot.

Which fields work best for AI training and RAG indexing?

For RAG: text combined with buyingSignalReasons gives a retrieval system pre-labeled intent context instead of raw prose to re-classify. For training data: buyingSignalTier, isQuestion and (with AI enrichment on) sentiment/intentLabel are consistent enum values across every row. All fields return as typed primitives โ€” strings, integers, booleans, arrays โ€” requiring no normalization before use.

What happens to personal data returned in the results?

The commenter names, profile URLs and avatars in the output are publicly visible on LinkedIn at scrape time. This Actor does not infer, guess or enrich beyond what LinkedIn's page itself displays; lawful basis for storing and using that data in your own systems sits with you as the operator, not with the Actor.

Does this Actor work with Claude, ChatGPT and other AI agent tools?

It is not documented as reachable through a dedicated MCP server. Any agent framework that can call the Apify API or the apify_client/apify-client SDK can run it and read back typed JSON directly โ€” no HTML parsing step is needed before passing a row into an LLM's context window.

What happens when a post has no comments left after filtering?

The post still produces one dataset row rather than nothing: errorReason is set to "no_comments" (or a more specific block reason), commentsKeptAfterFilters is 0, and every content field is null. This accounting row is pushed without the row_result charged event, so a fully-filtered-out post costs nothing.

How does this Actor compare to other LinkedIn comment scrapers?

apimaestro's no-cookies comment scraper and benjarapi's comment scraper both document broader raw comment volume and nested-reply extraction (observed on their Apify Store listings, checked 2026-07-26) without documenting any pre-filtering, scoring or contact-extraction layer. This Actor trades some of that raw-volume framing for a filter-then-score pipeline: fewer rows, but every row carries a keyword-auditable buying-intent score and any contact details LinkedIn itself never surfaces as a structured field.

โ„น๏ธ Disclaimer

This Actor extracts only publicly available data from LinkedIn. It is intended for lawful use cases only. Users are responsible for complying with LinkedIn's Terms of Service and applicable data protection laws in their jurisdiction, including any obligations that attach to the personal data (names, profile URLs, avatars) present in the comments it returns.