# LinkedIn Post Comment & Reply Thread Extractor (`nimbryxo-studio/linkedin-post-comment-and-reply-thread-extractor`) Actor

Pull top-level comments from LinkedIn posts, with optional nested reply threads, author identity, reaction counts, and linked profiles found in the comment text.

- **URL**: https://apify.com/nimbryxo-studio/linkedin-post-comment-and-reply-thread-extractor.md
- **Developed by:** [Nimbryxo-studio](https://apify.com/nimbryxo-studio) (community)
- **Categories:** Social media, Lead generation, Automation
- **Stats:** 1 total users, 0 monthly users, 0.0% runs succeeded, 0 bookmarks
- **User rating**: No ratings yet

## Pricing

from $0.49 / 1,000 results

This Actor is paid per event and usage. You are charged both the fixed price for specific events and for Apify platform usage.
Since this Actor supports Apify Store discounts, the price gets lower the higher subscription plan you have.

Learn more: https://docs.apify.com/actors/running/actors-in-store.md#pay-per-event

## What's an Apify Actor?

An Actor is a serverless cloud program that runs on the Apify platform. It has two run modes.
In Batch mode, an Actor accepts a well-defined JSON input, performs an action which can take anything from a few seconds to a few hours,
and optionally produces a well-defined JSON output, datasets with results, or files in key-value store.
In Standby mode, an Actor provides a web server which can be used as a website, API, or an MCP server.

Apify vocabulary and the platform model are defined once, in the agent quickstart at https://apify.com/agents.md.

## How to integrate an Actor?

If asked about integration, you help developers integrate Actors into their projects.
You adapt to their stack and deliver integrations that are safe, well-documented, and production-ready.

Do not guess an integration path. Every one of them is in the agent quickstart at https://apify.com/agents.md: the Apify MCP server, Agent Skills with the Apify CLI, the JavaScript and Python clients, the REST API, and the account-free path for an agent with no human to sign in. It also carries the rule on stating cost before the first paid run.

For examples already wired to this Actor's own input schema, see the [API](#api) section below.

Each client library has reference documentation the quickstart does not restate: [JavaScript/TypeScript](https://docs.apify.com/api/client/js/docs.md) (`npm install apify-client`) and [Python](https://docs.apify.com/api/client/python/docs.md) (`pip install apify-client`).

# README

## LinkedIn Post Comment & Reply Thread Extractor

Feed this actor one or more LinkedIn post links and a session cookie, and it returns the top-level comments on each post (up to your per-post limit) — optionally with nested reply threads — as structured rows with author identity, engagement counts, and linked profiles.

### What this actor does

- Scrapes top-level comments from one or more LinkedIn post URLs, with a relevance or recency sort preference.
- Optionally follows reply threads up to 3 levels deep, emitting each reply as its own row linked to its parent via `parentCommentId`.
- Classifies each commenter as a person or company page, and pulls any LinkedIn profile or company links out of the comment text.
- Filters out comments below a minimum reaction count, and can exclude comments from person or company authors entirely.
- Omits text and URL fields it couldn't populate for a given comment; the counts (`reactionsCount`, `repliesCount`, `authorFollowersCount`), `isReply` and `authorType` are always present.

### Output per comment

| Field | Description |
|---|---|
| `commentId` | Unique numeric ID for the comment. |
| `postUrl` | Canonical URL of the source post. |
| `postId` | Numeric activity ID of the source post. |
| `authorName` | Commenter's full name. |
| `authorProfileUrl` | URL to the commenter's LinkedIn profile or company page. |
| `authorHeadline` | Commenter's headline/title. |
| `authorAvatar` | CDN URL of the commenter's profile photo. |
| `authorType` | `PERSON`, `COMPANY`, or `UNKNOWN` when it can't be determined. |
| `authorFollowersCount` | Commenter's follower count, when LinkedIn exposes one (0 otherwise). |
| `commentText` | Full text of the comment. |
| `commentedAt` | ISO 8601 UTC timestamp of when the comment was posted. |
| `commentEditedAt` | ISO 8601 UTC timestamp of the last edit, when the comment was edited. |
| `reactionsCount` | Total reactions on the comment (`0` when none or unknown). |
| `reactionBreakdown` | Reaction counts by type (e.g. `like`, `praise`), when more than one type is present. |
| `repliesCount` | Number of replies to this comment (`0` when none or unknown). |
| `isReply` | `true` if this row is a reply, `false` if top-level. |
| `parentCommentId` | ID of the parent comment (replies only). |
| `mentionedUsers` | LinkedIn profile URLs (`linkedin.com/in/...`) that appear in the comment text, when any are present. |
| `mentionedCompanies` | Company slugs from `linkedin.com/company/...` links in the comment text, when any are present. |
| `attachmentImageUrl` | URL of an attached image, when the comment includes one. |
| `attachmentVideoUrl` | URL of an attached video, when the comment includes one. |
| `scrapedAt` | ISO 8601 UTC timestamp of when the row was scraped. |

If no cookie is supplied, or the supplied cookie is or becomes invalid, the run writes a record with `_status: "no_data"`, `_reason`, `_message`, `_help` and `scrapedAt` fields explaining what to fix, and stops. Comments already saved before the cookie stopped working stay in the dataset.

### Input

| Field | Type | Default | Description |
|---|---|---|---|
| `postUrls` | List of strings | – | LinkedIn post URLs to scrape comments from. Accepts `/feed/update/urn:li:activity:ID/` or `/posts/username_slug-ID/` formats. Required. |
| `cookie` | String | – | A LinkedIn session cookie: either the `li_at` value, or the full cookies JSON array exported from a browser extension. Required. |
| `maxCommentsPerPost` | Integer | `50` | Maximum top-level comments to scrape per post (1–500). Replies don't count toward it. |
| `includeReplies` | Boolean | `false` | Also fetch replies to top-level comments, each output as its own row. |
| `replyDepth` | Integer | `1` | How many reply levels to recurse when `includeReplies` is on: `1` = direct replies, up to `3`. Up to 10 replies are read per comment. |
| `sortBy` | String (select) | `RELEVANCE` | `RELEVANCE` (LinkedIn's "Most relevant") or `RECENT` (newest first). A preference only: depending on how LinkedIn serves a post's comments, they may come back in LinkedIn's default order. |
| `minReactions` | Integer | `0` | Skip comments and replies with fewer than this many reactions. `0` disables the filter. |
| `language` | String (select) | `en` | Preferred LinkedIn UI language; influences which translation of comment text is returned. |
| `excludeAuthorTypes` | List of strings | `[]` | Drop comments and replies from the selected author types: `PERSON`, `COMPANY`. Comments whose author type is `UNKNOWN` are always kept. |
| `proxyConfiguration` | Object | – | Optional Apify proxy settings. |

#### Example: default run

```json
{
  "postUrls": ["https://www.linkedin.com/feed/update/urn:li:activity:7329761432933134337/"],
  "cookie": "YOUR_LI_AT_VALUE",
  "maxCommentsPerPost": 50
}
```

#### Example: with nested replies, newest first

```json
{
  "postUrls": ["https://www.linkedin.com/posts/williamhgates_climate-7329761432933134337/"],
  "cookie": "YOUR_LI_AT_VALUE",
  "includeReplies": true,
  "replyDepth": 2,
  "sortBy": "RECENT"
}
```

#### Example: high-engagement comments from people only

```json
{
  "postUrls": ["https://www.linkedin.com/feed/update/urn:li:activity:7329761432933134337/"],
  "cookie": "YOUR_LI_AT_VALUE",
  "minReactions": 10,
  "excludeAuthorTypes": ["COMPANY"]
}
```

### Use cases

- **Audience sentiment** — read how people are reacting to a company announcement or thought-leadership post.
- **Lead discovery** — surface engaged commenters as warm prospects, filtered to real people by `excludeAuthorTypes`.
- **Influencer research** — see who's actively replying to a creator's posts and how deep the conversation threads go.
- **Brand monitoring** — track mentions of your company or product inside comment threads on relevant posts.
- **Community moderation review** — pull full reply chains to review how a sensitive post's discussion unfolded.

### FAQ

**Does this need a LinkedIn account?** Yes. A valid session cookie (`li_at` or an exported cookies JSON array) from a logged-in account is required to read comment data.

**Why would `authorName` be missing from a comment?** Deleted accounts or heavily restricted profiles can leave author fields empty. If a comment has no extractable ID at all, it's skipped entirely.

**Does the actor see deleted comments?** No. Deleted comments are removed from LinkedIn's own response, so the actor only sees whatever is still live at scrape time.

**How deep do reply threads go?** Up to 3 levels via `replyDepth`, only when `includeReplies` is enabled. At each level the actor reads up to 10 replies per comment, and replies beyond the chosen depth aren't fetched.

**Why did I get fewer comments than `maxCommentsPerPost`?** The post may simply have fewer comments, `minReactions`/`excludeAuthorTypes` may have dropped some, or LinkedIn may serve that post's comments in a way that only exposes its first batch. Comments are not de-duplicated across different input URLs pointing to the same post.

**Can I scrape comments on a post I don't have access to?** No. Only posts visible to the account behind your cookie can be scraped — private or connection-restricted posts outside your network will fail.

**Why is a cookie required for public-looking posts?** LinkedIn's comment data isn't available through any unauthenticated public endpoint, even for posts that appear public in a browser without logging in.

**What happens if my cookie expires mid-run?** The run stops and adds a record with `_status: "no_data"` plus a `_reason`/`_message`/`_help` explanation; any comment rows saved before that point remain. Log into LinkedIn, copy a fresh `li_at` value, and start a new run.

**Is this affiliated with LinkedIn?** No. This is an independent tool and is not affiliated with, endorsed by, or sponsored by LinkedIn Corporation.

# Actor input Schema

## `postUrls` (type: `array`):

LinkedIn post URLs to scrape comments from. Accepts formats like: https://www.linkedin.com/feed/update/urn:li:activity:7329761432933134337/ or https://www.linkedin.com/posts/username_some-slug-7329761432933134337/. Use a public, high-engagement post URL for best results. The prefill example uses a Bill Gates post from early 2025.

## `cookie` (type: `string`):

Your LinkedIn session cookie. Accepts either: (1) the li_at value from browser DevTools → Application → Cookies, or (2) full cookies JSON array exported from an extension like EditThisCookie.

## `maxCommentsPerPost` (type: `integer`):

Maximum number of top-level comments to scrape per post.

## `includeReplies` (type: `boolean`):

Whether to fetch replies to top-level comments. Each reply is output as a separate dataset row with isReply=true and parentCommentId linking to the parent.

## `replyDepth` (type: `integer`):

How many levels deep to recurse when fetching replies. Only honored when Include Replies is enabled. 1 = direct replies only, 2 = replies of replies, 3 = three levels.

## `sortBy` (type: `string`):

Sort order for comments. RELEVANCE uses LinkedIn's default 'Most relevant'. RECENT shows newest first.

## `minReactions` (type: `integer`):

Skip comments with fewer than this many reactions (likes + other reaction types). 0 disables the filter and emits every comment.

## `language` (type: `string`):

Preferred LinkedIn UI language. Sets the Accept-Language header and x-li-lang for Voyager API calls; influences which translations LinkedIn returns for comment text.

## `excludeAuthorTypes` (type: `array`):

Drop comments authored by the selected actor types. PERSON = individual member profiles, COMPANY = company / organization pages.

## `proxyConfiguration` (type: `object`):

Optional Apify proxy configuration. Residential proxy recommended for best results.

## Actor input object example

```json
{
  "postUrls": [
    "https://www.linkedin.com/feed/update/urn:li:activity:7329761432933134337/"
  ],
  "maxCommentsPerPost": 50,
  "includeReplies": false,
  "replyDepth": 1,
  "sortBy": "RELEVANCE",
  "minReactions": 0,
  "language": "en",
  "excludeAuthorTypes": []
}
```

# Actor output Schema

## `comments` (type: `string`):

Dataset containing all scraped LinkedIn post comments and replies.

# API

You can run this Actor programmatically using our API. Below are code examples in JavaScript, Python, and CLI, as well as the OpenAPI specification and MCP server setup.

## JavaScript example

```javascript
import { ApifyClient } from 'apify-client';

// Initialize the ApifyClient with your Apify API token
// Replace the '<YOUR_API_TOKEN>' with your token
const client = new ApifyClient({
    token: '<YOUR_API_TOKEN>',
});

// Prepare Actor input
const input = {
    "postUrls": [
        "https://www.linkedin.com/feed/update/urn:li:activity:7329761432933134337/"
    ],
    "maxCommentsPerPost": 50,
    "includeReplies": false,
    "replyDepth": 1,
    "sortBy": "RELEVANCE",
    "minReactions": 0,
    "language": "en",
    "excludeAuthorTypes": []
};

// Run the Actor and wait for it to finish
const run = await client.actor("nimbryxo-studio/linkedin-post-comment-and-reply-thread-extractor").call(input);

// Fetch and print Actor results from the run's dataset (if any)
console.log('Results from dataset');
console.log(`💾 Check your data here: https://console.apify.com/storage/datasets/${run.defaultDatasetId}`);
const { items } = await client.dataset(run.defaultDatasetId).listItems();
items.forEach((item) => {
    console.dir(item);
});

// 📚 Want to learn more 📖? Go to → https://docs.apify.com/api/client/js/docs

```

## Python example

```python
from apify_client import ApifyClient

# Initialize the ApifyClient with your Apify API token
# Replace '<YOUR_API_TOKEN>' with your token.
client = ApifyClient("<YOUR_API_TOKEN>")

# Prepare the Actor input
run_input = {
    "postUrls": ["https://www.linkedin.com/feed/update/urn:li:activity:7329761432933134337/"],
    "maxCommentsPerPost": 50,
    "includeReplies": False,
    "replyDepth": 1,
    "sortBy": "RELEVANCE",
    "minReactions": 0,
    "language": "en",
    "excludeAuthorTypes": [],
}

# Run the Actor and wait for it to finish
run = client.actor("nimbryxo-studio/linkedin-post-comment-and-reply-thread-extractor").call(run_input=run_input)

# Fetch and print Actor results from the run's dataset (if there are any)
print(f"💾 Check your data here: https://console.apify.com/storage/datasets/{run.default_dataset_id}")
for item in client.dataset(run.default_dataset_id).iterate_items():
    print(item)

# 📚 Want to learn more 📖? Go to → https://docs.apify.com/api/client/python/docs/quick-start

```

## CLI example

```bash
echo '{
  "postUrls": [
    "https://www.linkedin.com/feed/update/urn:li:activity:7329761432933134337/"
  ],
  "maxCommentsPerPost": 50,
  "includeReplies": false,
  "replyDepth": 1,
  "sortBy": "RELEVANCE",
  "minReactions": 0,
  "language": "en",
  "excludeAuthorTypes": []
}' |
apify call nimbryxo-studio/linkedin-post-comment-and-reply-thread-extractor --silent --output-dataset

```

## MCP server setup

```json
{
    "mcpServers": {
        "apify": {
            "type": "http",
            "url": "https://mcp.apify.com/?tools=fetch-actor-details,nimbryxo-studio/linkedin-post-comment-and-reply-thread-extractor"
        }
    }
}
```

The hosted server signs you in with OAuth on first connect, so no API token belongs in this config. Clients without OAuth support can send an `Authorization: Bearer <APIFY_API_TOKEN>` header instead, using a token from API & Integrations in Apify Console (https://console.apify.com/settings/integrations).

## OpenAPI specification

Download the OpenAPI definition: https://api.apify.com/v2/actors/9IrDMYd0zWDgF1HtA/builds/CBKbM1dBIO5OKW2ZN/openapi.json
