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

Extract public LinkedIn post text, author details, publish time, likes, comments, reposts when shown, media links, captions, and transcripts from known post URLs.

- **URL**: https://apify.com/chronometrica/linkedin-post-scraper.md
- **Developed by:** [Chronometrica](https://apify.com/chronometrica) (community)
- **Categories:** Social media, Automation, Developer tools
- **Stats:** 3 total users, 2 monthly users, 100.0% runs succeeded, 0 bookmarks
- **User rating**: No ratings yet

## Pricing

from $2.50 / 1,000 linkedin post results

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/platform/actors/running/actors-in-store#pay-per-event

## What's an Apify Actor?

Actors are web data automations that power AI and operations. They run on the Apify platform to scrape websites, process data, connect APIs, and automate workflows.
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.
Actors are written with capital "A".

## 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.
The best way to integrate Actors is as follows.

- **AI agents and MCP clients** — the [Apify MCP server](https://docs.apify.com/integrations/mcp.md) at `https://mcp.apify.com` (remote, streamable HTTP, OAuth on first use).
- **Agentic workflows and local Actor development** — [Agent Skills](https://apify.com/.well-known/agent-skills/index.json) with the [Apify CLI](https://docs.apify.com/cli/docs.md): `npm install -g apify-cli`, then `apify login`.
- **JavaScript/TypeScript projects** — the official [JS/TS client](https://docs.apify.com/api/client/js/docs.md): `npm install apify-client`.
- **Python projects** — the official [Python client](https://docs.apify.com/api/client/python/docs.md): `pip install apify-client`.
- **Any other language** — the [REST API](https://docs.apify.com/api/v2.md).

For usage examples, see the [API](#api) section below.

For more details, see Apify documentation as [Markdown index](https://docs.apify.com/llms.txt) and [Markdown full-text](https://docs.apify.com/llms-full.txt).

# README

## LinkedIn Post Scraper

### 📊 What does LinkedIn Post Scraper do?

LinkedIn Post Scraper turns known public LinkedIn post URLs into clean post
rows. Use it for content research, author research, campaign tracking, reports,
and scheduled post checks.

Each input creates one row. A successful row can contain stable post and author
identity, post text, publish time, public engagement counts, author details,
and public media details.

This Actor reads public LinkedIn post pages. It does not sign in, use customer
LinkedIn accounts, collect private data, or reveal hidden post details.

With LinkedIn Post Scraper, you can:

- 🆔 Collect typed activity IDs, UGC post IDs, post URNs, and author IDs.
- 📝 Save public post text, headlines, and publish times.
- 📊 Collect public likes, comments, reposts, and author follower counts.
- 🎬 Save public media details, thumbnails, captions, and transcripts when
  LinkedIn shows them.
- 📦 Export rows as JSON, JSONL, CSV, Excel, XML, RSS, or HTML.
- 🔄 Send post rows to an API, webhook, spreadsheet, or data pipeline.

### 📦 What LinkedIn post data can I extract?

One dataset row represents one attempted public LinkedIn post input.

| Data group         | Example fields                                                                            |
| ------------------ | ----------------------------------------------------------------------------------------- |
| 🔗 Post identity   | `inputUrl`, `url`, `activityId`, `ugcPostId`, `postUrn`, `postType`                       |
| 🆔 Author identity | `authorId`, `authorUrn`, `authorPublicIdentifier`, `authorUrl`                            |
| 🧑 Author details  | `authorName`, `authorType`, `authorImageUrl`, `authorFollowersCount`                      |
| 📝 Post details    | `headline`, `text`, `publishedAt`                                                         |
| 📊 Public counts   | `likesCount`, `commentsCount`, `repostsCount`                                             |
| 🎬 Media details   | `durationMs`, `width`, `height`, `contentUrl`, `thumbnailUrl`, `captionUrl`, `transcript` |
| 🚦 Row state       | `status`, `statusReason`, `observedAt`                                                    |

Missing public values stay `null`. The Actor does not guess hidden values or
change missing counts to zero.

### ⚙️ Can I use this Actor through an API?

Yes. Run the Actor in Apify Console or connect it through:

- Apify API
- Python SDK
- JavaScript SDK
- Webhooks
- Scheduled runs
- Apify integrations

This lets you send fresh post rows to a spreadsheet, database, warehouse, or
internal service.

### 🎯 Why scrape LinkedIn posts?

| Use case            | How the data helps                                               |
| ------------------- | ---------------------------------------------------------------- |
| 🔎 Content research | Review public post text, media, authors, and engagement.         |
| 📈 Post monitoring  | Compare public post snapshots from scheduled runs.               |
| 🧑 Author research  | Connect posts with stable public author identity when available. |
| 📣 Campaign reports | Save public engagement counts for known campaign posts.          |
| 🧱 Data pipelines   | Load clean post rows into a database or internal tool.           |

### 💵 Pricing Event

This Actor uses pay-per-result pricing. One paid result means one successfully
resolved public post row. Failed, private, deleted, missing, or unsupported
posts are not paid results.

| Apify plan | Price per 1,000 successful posts |
| ---------- | -------------------------------: |
| Free       |                            $3.50 |
| Starter    |                            $3.00 |
| Scale      |                            $2.75 |
| Business   |                            $2.50 |

Platform usage is included. Use Apify's maximum charge setting to limit paid
results before a run.

### 🚀 How do I use LinkedIn Post Scraper?

1. Open **LinkedIn Post Scraper** in Apify Console.
2. Add one or more public LinkedIn post URLs.
3. Click **Start**.
4. Open the **Output** tab while the run is active to see completed rows.
5. Download the dataset or connect it to your workflow.

### ⬇️ Input

#### 🔗 LinkedIn post URLs

Add public LinkedIn post URLs to `startUrls`.

```json
{
  "startUrls": [
    "https://www.linkedin.com/posts/timferriss_i-took-my-whole-genome-dumped-it-into-ai-activity-7333162625675038720-TJPX"
  ]
}
```

The Actor supports standard and country LinkedIn domains with a `/posts/`
path. Tracking parameters can remain in the input URL. The output includes the
clean post URL when the post is available. The clean URL uses the standard
`www.linkedin.com` host and has no query string or fragment.

Exact duplicate input strings are checked once. Different URL forms for the
same post can create separate attempts.

Results are saved as soon as each post finishes.

### ⬆️ Output sample

The sample below shows the exact field order. Public values vary by post and
run time.

```json
{
  "inputUrl": "https://www.linkedin.com/posts/timferriss_i-took-my-whole-genome-dumped-it-into-ai-activity-7333162625675038720-TJPX",
  "url": "https://www.linkedin.com/posts/timferriss_i-took-my-whole-genome-dumped-it-into-ai-activity-7333162625675038720-TJPX",
  "activityId": "7333162625675038720",
  "ugcPostId": null,
  "postUrn": "urn:li:activity:7333162625675038720",
  "postType": "VideoObject",
  "authorName": "Tim Ferriss",
  "authorType": "Person",
  "authorId": "15499",
  "authorUrn": "urn:li:member:15499",
  "authorPublicIdentifier": "timferriss",
  "authorUrl": "https://www.linkedin.com/in/timferriss",
  "authorImageUrl": "https://media.licdn.com/dms/image/v2/D4E03AQFJUaA3RAZDIw/profile-displayphoto-shrink_200_200/profile-displayphoto-shrink_200_200/0/1687979278495?e=2147483647&v=beta&t=jU3Gf5QEuNbTGOvCToR36R3NEIvZFbzySzZzySeGofw",
  "authorFollowersCount": 1538200,
  "headline": "\"I took my whole genome, dumped it into AI, and we worked out a playbook together.\" — Kevin Rose",
  "text": "\"I took my whole genome, dumped it into AI, and we worked out a playbook together.\" — Kevin Rose",
  "publishedAt": "2025-05-27T16:10:13.501Z",
  "likesCount": 60,
  "commentsCount": 10,
  "repostsCount": null,
  "durationMs": 43000,
  "width": 720,
  "height": 1280,
  "contentUrl": "https://dms.licdn.com/playlist/vid/v2/D4D05AQGulHZiCPUQxA/mp4-720p-30fp-crf28/B4DZcSgOoFGUBM-/0/1748362198190?e=2147483647&v=beta&t=5uuNhUZ1SMfCepiAg5rgM8UcJHrv1_CaWw0dQpcXMPc",
  "thumbnailUrl": "https://media.licdn.com/dms/image/v2/D4D05AQGulHZiCPUQxA/videocover-high/B4DZcSgOoFGUBo-/0/1748362192116?e=2147483647&v=beta&t=a0_ktMIjBTUTKt_Teat8e4cE4-I9ckXCAAz59Ln_iQg",
  "captionUrl": "https://dms.licdn.com/playlist/vid/v2/D4D05AQGulHZiCPUQxA/video-auto-caption-srt-acs-singleton/B4DZcSgOoFGUEE-/0/1748362211491?e=2147483647&v=beta&t=kUV4b-IXm1eu5KoIfEbhgoSd82sx16X-i8y6Yv1khAU",
  "transcript": "I took my whole genome, dumped it into AI and we worked out a playbook together on where we could find mental doctors to and which methylated B vitamins I could give to help fix the broken cycle because I have the MTHFR genetic mutation. It's a very fancy way of saying 1 biomarker completely jacked up. My dad died of heart disease. I don't want to have heart disease. How can we fix this ****? We work through a way for me to supplement and start adding on supplements. I'm 8 weeks. In and for the first time, my homocysteine is at normal levels after many years of trying to figure this out, and I was working through this process in tandem with my AI.",
  "status": "ok",
  "statusReason": null,
  "observedAt": "2026-08-13T14:05:36.171Z"
}
```

#### 📌 Run summary

The `OUTPUT` record contains:

- `actorName`: stable Actor output name;
- `schemaVersion`: public output contract version;
- `startedAt` and `finishedAt`: run times;
- `inputCount`: number of unique input strings;
- `usefulRows`: number of successful post rows;
- `failedRows`: number of failed post rows;
- `datasetId`: ID of the result dataset;
- `stopReason`: why the Actor stopped.

### 🎯 Status and quality fields

- `ok`: the Actor found a public post and saved its public data.
- `failed`: the public post could not be read or did not expose enough data.
- `invalid_url`: the input is not a supported LinkedIn post URL.

Failed rows keep the same field order as successful rows. Unknown values stay
`null`. Check `statusReason` for a safe explanation.

`activityId` contains only an activity ID. `ugcPostId` contains only a UGC post
ID. `postUrn` keeps the typed post URN shown by LinkedIn. These values can be
different. The stable `authorId` and `authorUrn` identify the author when
LinkedIn shows them. The public author identifier and profile URL can change.

### 🔒 Source boundary

This Actor reads only public LinkedIn post pages available without a customer
account. It does not:

- sign in to LinkedIn;
- use customer passwords, saved browser data, or accounts;
- open private posts or hidden post sections;
- collect private contact details;
- guess values that LinkedIn does not show.

### ⚠️ Limits and interpretation

- LinkedIn can show different public fields by post, visitor region, and time.
- Private, deleted, missing, or login-limited posts can return failed rows.
- A public count, author field, caption, transcript, or media field can be
  missing.
- Public media, image, thumbnail, and caption links can change or expire.
- Results are post snapshots. Use scheduled runs to build history.
- LinkedIn can change its public pages. A later change can require an Actor
  update.

### ❓ FAQ

#### Does this Actor need a LinkedIn login or API key?

No. It reads public post pages without a customer LinkedIn account.

#### Why is a field `null`?

LinkedIn did not show that value publicly for the post at run time. The Actor
does not guess the value or change a missing count to zero.

#### Why did I receive a failed row?

The post can be private, missing, deleted, limited to signed-in visitors, or
unavailable at run time. Check `statusReason` and confirm that the input is a
public LinkedIn `/posts/` URL.

#### How are duplicate posts handled?

The Actor checks an exact duplicate input string once per run. Different URL
forms for the same post can create separate attempts.

### 🏠 Related Actors

Continue the same workflow on this platform or compare public data across
platforms.

#### Continue on LinkedIn

- [LinkedIn Profile Scraper](https://apify.com/chronometrica/linkedin-profile-scraper)
  — collect public profile identity, headlines, and visible profile facts.
- [LinkedIn Comments Scraper](https://apify.com/chronometrica/linkedin-comments-scraper)
  — collect public comments, replies, authors, dates, and reactions.

### 🛟 Support

For help, share the run ID, public post URL, expected result, and actual result.
State whether the issue affects one row or the full run. Never share a LinkedIn
password, saved browser data, or private token.

Use public data in line with applicable laws, LinkedIn rules, and Apify rules.

# Actor input Schema

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

Paste one or more public LinkedIn post URLs.

## Actor input object example

```json
{
  "startUrls": [
    "https://www.linkedin.com/posts/timferriss_i-took-my-whole-genome-dumped-it-into-ai-activity-7333162625675038720-TJPX"
  ]
}
```

# Actor output Schema

## `results` (type: `string`):

No description

## `output` (type: `string`):

No description

# 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 = {
    "startUrls": [
        "https://www.linkedin.com/posts/timferriss_i-took-my-whole-genome-dumped-it-into-ai-activity-7333162625675038720-TJPX"
    ]
};

// Run the Actor and wait for it to finish
const run = await client.actor("chronometrica/linkedin-post-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 = { "startUrls": ["https://www.linkedin.com/posts/timferriss_i-took-my-whole-genome-dumped-it-into-ai-activity-7333162625675038720-TJPX"] }

# Run the Actor and wait for it to finish
run = client.actor("chronometrica/linkedin-post-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 '{
  "startUrls": [
    "https://www.linkedin.com/posts/timferriss_i-took-my-whole-genome-dumped-it-into-ai-activity-7333162625675038720-TJPX"
  ]
}' |
apify call chronometrica/linkedin-post-scraper --silent --output-dataset

```

## MCP server setup

```json
{
    "mcpServers": {
        "apify": {
            "type": "http",
            "url": "https://mcp.apify.com/?tools=fetch-actor-details,chronometrica/linkedin-post-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/lB0DRaOyItRbrC6LU/builds/6mcBv8W2JMWmL2Vco/openapi.json
