# LinkedIn Post Scraper (`boncross/linkedin-post-details-scraper`) Actor

Scrape any public LinkedIn post by URL, with no login. Just add post links and get the full text, date, reactions, comment count, author, media type and preview image, plus the comments LinkedIn publishes. Export to CSV or Excel, or run it on a schedule. $1.50 per 1,000 posts.

- **URL**: https://apify.com/boncross/linkedin-post-details-scraper.md
- **Developed by:** [BonCross API](https://apify.com/boncross) (community)
- **Categories:** Social media, Lead generation
- **Stats:** 3 total users, 2 monthly users, 100.0% runs succeeded, 0 bookmarks
- **User rating**: No ratings yet

## Pricing

from $1.05 / 1,000 post-details

This Actor is paid per event. You are not charged for the Apify platform usage, but only a fixed price for specific events.
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 Scraper

### What is LinkedIn Post Scraper?

Got a list of LinkedIn post links? LinkedIn Post Scraper turns each one into a record: the full text, who posted it, the reaction count, the comment count, and the comments LinkedIn shows publicly. The comments are in the post price. You aren't billed per comment row.

Paste the links in either of LinkedIn's formats, or bare activity ids. There's no login.

- **Comments included at $1.50 per 1,000 posts.** A post and its public comments are one row and one charge.
- **1,000 posts in about two and a half minutes.** Measured with comments on, 2 October 2026, at about 430 posts a minute.
- **Duplicates are caught by post, not by string.** The `/feed/update/…` link and the `/posts/…` link to one post count once.
- **Dead links are cheap and visible.** A deleted or private post returns a row with the reason and costs $0.0005.

**BonCross Verified** means we tested this actor against the live site before release and kept the record:

- 13 of 13 live checks on its inputs and filters passed on 7 October 2026
- 20 inputs run the same day, posts, articles, a made-up id and a bare URN: 15 posts, 5 error rows
- Charges matched the rows: 1 start, 15 posts, 4 checked

### What data do you get for each post?

| | |
|---|---|
| 📝 Full post text | 👍 Reaction count |
| 💬 Comment count | The comments LinkedIn shows publicly, with authors |
| 👤 Author name and profile | Whether the author is a person or a company |
| 📅 When it was posted, as written and as a date | Media type: text, image, video or document |
| Preview image | 🔗 Canonical post URL and activity id |

The row has one preview image per post, not a gallery.

### What people do with it

- Archive a post you care about before it's edited or deleted
- Measure the engagement on one campaign post, then rerun the same link to see it grow
- Pull the public comments on a post for sentiment analysis
- Check the author and media type of a link someone sent you
- Collect a set of competitor posts by URL for a teardown

### How to scrape a LinkedIn post

1. [Create your free Apify account](https://console.apify.com/sign-up).
2. Open [LinkedIn Post Scraper](https://apify.com/boncross/linkedin-post-details-scraper) and paste your post links.
3. If you only need the post and its counts, turn "Include the comments shown on the page" off.
4. Press Start. Two posts take 3 or 4 seconds.
5. Download the results as Excel, CSV, JSON, XML or HTML.

### ⬇️ Input

Links are all you have to supply. Use either link format, or a bare activity id if that's what you've stored.

One post is one page, so there's a single limit: "Maximum posts" caps what the run returns. It defaults to 0, which is no cap.

**Two posts given three ways (the bare id is the first link again, and counts once)**

```json
{
  "postUrls": [
    "https://www.linkedin.com/feed/update/urn:li:activity:7503853799422382081/",
    "https://www.linkedin.com/posts/google_google-pics-activity-7503561556371320833-JtK5",
    "7503853799422382081"
  ]
}
```

**A list from a file or Google Sheet, posts only, capped at 200**

```json
{
  "startUrls": [{ "url": "https://www.linkedin.com/feed/update/urn:li:activity:7503853799422382081/" }],
  "includeComments": false,
  "maxItems": 200
}
```

| Field | Notes |
|---|---|
| `postUrls` | Post links in either form, or bare activity ids. De-duplicated by post, not by string. |
| `startUrls` | The same, pasted or loaded in bulk from a file or a Google Sheet. |
| `includeComments` | Adds the comments LinkedIn shows publicly. On by default. |
| `maxItems` | A ceiling on the run. Default 0, no limit. |
| `delayMs`, `maxConcurrency` | An optional extra pause before each request (default 0), and how many posts are read at once (default 8). |

#### For developers

- `postUrls` and `startUrls` are merged and de-duplicated by post, not by string.
- `includeComments` (default true) adds `sampleComments` and `sampleCommentCount`. With it off, both fields are left out of the row.
- `maxConcurrency` (default 8, from 1 to 8) sets how many posts are read at once, and `delayMs` (default 0) adds a pause before each request.
- Rows are written as posts are read. A run stopped early keeps what it has.
- A link LinkedIn answered with no post bills `target-checked`. A link LinkedIn never answered bills nothing.

### ⬆️ Output

One record per post.

```json
{
  "id": "7503853799422382081",
  "activityUrn": "urn:li:activity:7503853799422382081",
  "url": "https://www.linkedin.com/posts/google_the-gemini-app-is-now-available-for-windows-activity-7503853799422382081-6P4U",
  "text": "The Gemini app is now available for Windows. Gemini is now just a keyboard shortcut away (Alt + Space) for instant AI assistance alongside your daily …",
  "reactions": 986,
  "comments": 116,
  "postedText": "3d",
  "postedAt": "2026-09-11",
  "authorName": "Google",
  "authorUrl": "https://www.linkedin.com/company/google",
  "authorType": "company",
  "image": "https://dms.licdn.com/playlist/vid/v2/D5605AQFtXpMPTlB0hg/thumbnail-with-play-button-overlay-high/B56aCMLP2PIkC0-/0/1789058156244?e=2147483647&v=beta&t=OZ7jiIhUviVOaicCCpgxNg7t1NRIABBylIdO7RSxsQQ",
  "mediaType": "video",
  "sampleComments": [
    {
      "author": "Sam Example",
      "authorUrl": "https://www.linkedin.com/in/example-member-1",
      "text": "The admin console covers the Workspace account. Spark's Connected Apps do not run on work …",
      "postedText": "3d",
      "reactions": 4
    },
    "…"
  ],
  "sampleCommentCount": 9,
  "scrapedAt": "2026-09-14T00:12:06.517Z"
}
```

Read `comments` when you want the real total. `sampleComments` holds the comments LinkedIn shows publicly, and `sampleCommentCount` says how many that is. `postedText` is LinkedIn's own wording ("3d"), and `postedAt` is the approximate date worked out from it.

### How much does it cost to scrape LinkedIn posts?

| Event | Free plan | Starter | Scale | Business |
|---|---|---|---|---|
| `actor-start`, per run | $0.001 | $0.001 | $0.001 | $0.001 |
| `post-detail`, per post returned | $0.0015 | $0.00135 | $0.0012 | $0.00105 |
| `target-checked`, per link LinkedIn answered with no post (no such post, or a page that is not a post) | $0.0005 | $0.0005 | $0.0005 | $0.0005 |

Enterprise plans pay the Business price.

**$1.50 per 1,000 posts** on the Free plan, $1.05 on Business, with the public comments included and no usage or proxy fees added.

100 posts cost $0.001 + 100 × $0.0015 = **$0.151** ($0.11 on Business). If ten of those links were dead, they'd cost 10 × $0.0005 = $0.005 in place of 10 × $0.0015.

Apify's Free plan comes with $5 of credits a month, enough for about 3,300 posts here.

### Run times and limits

| Run | Result |
|---|---|
| Two posts with comments on | 2 records in 2.8-4.0 seconds |
| 1,000 posts with comments on | 1,000 records in 2 minutes 13 seconds to 2 minutes 27 seconds (about 430 a minute) |
| Comments shown publicly | roughly nine or ten, whatever the real total |

Both timings are whole runs on Apify from 2 October 2026. An hour at that pace gets you roughly 25,000 posts.

The limits are LinkedIn's, and they're worth knowing before you plan around this data:

- **Comments are a sample.** LinkedIn shows roughly nine or ten on a post and keeps the others behind a login. The example above has 116 comments in total, and the row says so in `comments`.
- **Timestamps are relative.** LinkedIn gives "3d", which is returned as written, with an approximate date beside it.
- **Reaction counts move.** Two runs a few minutes apart can give you different numbers. That's the post changing.
- **Private and deleted posts return no data.** Each is an error row with an `error` field, billed `target-checked` ($0.0005).
- **An article link isn't a post.** In our release check, four LinkedIn article URLs each returned an error row saying the page carried no post.

### FAQ

#### Can I get all the comments on a post?

Only the ones LinkedIn shows without a login, which is roughly nine or ten. You do get the true total in `comments`, so you can tell a post with 12 comments from one with 1,200.

#### Which link formats work?

The `/feed/update/urn:li:activity:…` form, the `/posts/…-activity-…` form, and a bare activity id. Paste whichever you have.

#### How do I track a post's engagement over time?

Schedule a run on the same links, hourly or daily, and compare `reactions` and `comments` between datasets.

#### Do I need proxies, or my LinkedIn login?

Neither one. The post is read the way a signed-out visitor sees it, so your own account is never involved, and proxy usage is already in the price.

#### Can it list the posts on a company page?

This actor works from post links. To list a company's posts use [LinkedIn Company Posts Scraper](https://apify.com/boncross/linkedin-company-posts-scraper), then paste the links you want in here.

#### Is it legal to scrape a LinkedIn post?

The actor only opens posts that are public and never uses an account. Scraping public pages is generally lawful in the UK, EU and US (hiQ v LinkedIn is the case usually cited). A post and its comments name people, so GDPR and similar laws apply to what you do with them, and that part is your responsibility.

### Calling it from code or an agent

One request does it: `POST https://api.apify.com/v2/acts/boncross~linkedin-post-details-scraper/run-sync-get-dataset-items`, with `{"postUrls": [...]}` as the body, returns the records for a short list. For thousands of links, start a run and read the dataset afterwards. Apify publishes `apify-client` for Node.js and Python.

Agents reach it through the Apify MCP server (`mcp.apify.com`). Hand an agent a post URL and it can read the post and its comments before drafting your reply.

Results can also flow to Google Sheets, Slack, Make or Zapier when a run ends, which is handy for an archive that fills itself.

### More from BonCross

- [LinkedIn Company Scraper](https://apify.com/boncross/linkedin-company-details-scraper): LinkedIn company pages by URL, slug or name, with no login.
- [LinkedIn Company Posts Scraper](https://apify.com/boncross/linkedin-company-posts-scraper): The latest posts from any LinkedIn company page, with no login.
- [LinkedIn Jobs Scraper](https://apify.com/boncross/linkedin-jobs-scraper): LinkedIn jobs from keywords and locations or search URLs, no login needed.
- [Marriott Hotel Details Scraper](https://apify.com/boncross/marriott-hotel-details): Everything a Marriott property publishes: address, coordinates, phones, brand, guest…
- [Marriott Hotel Search Scraper](https://apify.com/boncross/marriott-hotel-search): Every Marriott hotel for a destination and dates.
- [Marriott Reviews Scraper](https://apify.com/boncross/marriott-reviews): Guest reviews for any Marriott hotel.

### Your feedback

A link that should have worked and didn't is the most useful thing you can send us. Put it on the Issues tab in Apify Console with what you expected. We read them all and answer there.

# Changelog

This Actor's version history is a separate document: https://apify.com/boncross/linkedin-post-details-scraper/changelog.md

# Actor input Schema

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

LinkedIn post links in either form (/posts/…-activity-{id}-{hash} or /feed/update/urn:li:activity:{id}/) or just the numeric activity id. Both forms of the same post are treated as one.

## `startUrls` (type: `array`):

The same as Post URLs, in the format Apify's scheduler and integrations pass links in.

## `includeComments` (type: `boolean`):

LinkedIn shows a handful of comments publicly and keeps the rest behind a login. The total count is always returned; this adds the comments that are actually published, with their authors and reaction counts.

## `maxItems` (type: `integer`):

A ceiling on the posts this run returns. Nothing past it is fetched or charged for. Leave at 0 for no limit.

## `delayMs` (type: `integer`):

Extra pause before each request, jittered by about 30 percent either way. The run already keeps to a request rate measured safe for LinkedIn, so the default is 0; raise it only if a run reports refusals.

## `maxConcurrency` (type: `integer`):

How many targets are read at once. The default is the fastest level measured clean; lower it only if a run reports refusals or errors.

## `restartAttempt` (type: `integer`):

Set by the actor when it restarts itself in a fresh container after being refused. Leave it alone.

## Actor input object example

```json
{
  "postUrls": [
    "https://www.linkedin.com/feed/update/urn:li:activity:7503853799422382081/"
  ],
  "startUrls": [],
  "includeComments": true,
  "maxItems": 0,
  "delayMs": 0,
  "maxConcurrency": 8,
  "restartAttempt": 0
}
```

# Actor output Schema

## `dataset` (type: `string`):

Every post the run returned.

## `stats` (type: `string`):

Counts for the run.

# 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:7503853799422382081/"
    ]
};

// Run the Actor and wait for it to finish
const run = await client.actor("boncross/linkedin-post-details-scraper").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:7503853799422382081/"] }

# Run the Actor and wait for it to finish
run = client.actor("boncross/linkedin-post-details-scraper").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:7503853799422382081/"
  ]
}' |
apify call boncross/linkedin-post-details-scraper --silent --output-dataset

```

## MCP server setup

```json
{
    "mcpServers": {
        "apify": {
            "type": "http",
            "url": "https://mcp.apify.com/?tools=fetch-actor-details,boncross/linkedin-post-details-scraper"
        }
    }
}
```

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/MRAUlMxGkMRrK69Kq/builds/xbvS27YHudsxEDZkv/openapi.json
