# LinkedIn Profile Posts Scraper (`capable_cauldron/linkedin-profile-posts-scraper`) Actor

Scrape LinkedIn profile posts with automatic pagination. No cookies needed. Get rich post data including engagement metrics, content categories, hashtags, mentioned companies/profiles, and computed fields not available in other actors.

- **URL**: https://apify.com/capable_cauldron/linkedin-profile-posts-scraper.md
- **Developed by:** [Capable Cauldron](https://apify.com/capable_cauldron) (community)
- **Categories:** Social media, Automation, Lead generation
- **Features:** Limited permissions
- **Stats:** 35 total users, 8 monthly users, 100.0% runs succeeded, 1 bookmarks
- **User rating**: 5.00 out of 5 stars

## Pricing

from $1.00 / 1,000 post scrapeds

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

Scrape **public posts from personal LinkedIn profiles** with **no cookies and no login**. You get the text, media, article links, a full reaction breakdown, comment and repost counts, and **56 enriched fields per post** including computed engagement totals, content category, hashtags and mentioned companies. Give it one or more profile usernames, set how many posts you want, and it paginates on its own.

Nothing touches your own LinkedIn account. Built on Apify, so you can **schedule** runs to track a profile over time, trigger them from the **API** or a webhook, and push results to **Google Sheets** or your warehouse. Click **Try for free** to open it in Console. Apify's free plan includes $5 of monthly credit, enough for about **1,600 posts when collecting 100 posts per profile**.

### What can LinkedIn Profile Posts Scraper do?

- 🔓 **No account needed**, so there is no risk to your LinkedIn profile
- 📜 **Automatic pagination**: ask for 10 posts or 2,000 and the Actor handles paging
- 👥 **Many profiles per run**, one username or hundreds
- 🧮 **56 fields per post**, pre-computed so you don't have to:
  - total engagement (reactions + comments + reposts)
  - content category (text, image, video, article, document, carousel, poll)
  - hashtags extracted and counted
  - mentioned companies and profiles as structured objects
  - reaction breakdown (like, love, celebrate, support, insight, funny, curious)
  - ISO-8601 dates for clean sorting, word and character counts
- 🔁 **Repost filter**: keep only the profile's own writing with `includeReposts: false`
- 💸 **Hard cost cap** on dataset items
- 📤 Export to **CSV, Excel, JSON or XML**, or pull results via API

#### What data can you extract from LinkedIn posts?

Grouped by what you would use them for:

| Group | Fields |
|---|---|
| Identity | `activity_urn`, `share_urn`, `ugcPost_urn`, `full_urn`, `post_url`, `post_type`, `is_repost`, `is_shared_content` |
| Content | `text`, `content_category`, `word_count`, `char_count`, `hashtags`, `hashtag_count` |
| Media | `media_type`, `media_url`, `media_thumbnail`, `media_images` |
| Article / document | `has_article`, `article_url`, `article_title`, `article_subtitle`, `article_thumbnail`, `has_document`, `document_title`, `document_page_count`, `document_url`, `document_thumbnail` |
| Author | `author_name`, `author_first_name`, `author_last_name`, `author_headline`, `author_username`, `author_profile_url`, `author_profile_picture`, `author_actor_type` |
| Engagement | `total_reactions`, `reaction_like`, `reaction_love`, `reaction_celebrate`, `reaction_support`, `reaction_insight`, `reaction_funny`, `reaction_curious`, `num_comments`, `num_reposts`, `total_engagement` |
| Mentions | `mentioned_companies`, `mentioned_profiles`, `text_annotations` |
| Dates | `posted_date`, `posted_relative`, `posted_timestamp`, `posted_date_iso` |
| Run metadata | `profile_username`, `scraped_at` |

Three pre-built dataset views in Console: **Overview**, **Engagement Metrics** and **Content Analysis**.

### How to scrape LinkedIn posts from a profile

[![linkedin profile posts scraper input form](https://api.apify.com/v2/key-value-stores/9FGooi7IrKs0P8DcV/records/linkedin-profile-posts-scraper-input.png)](https://console.apify.com/sign-up)

1. Click **Try for free** to open the Actor in Apify Console.
2. Enter one or more **usernames**. That is the last part of a profile URL, e.g. `satyanadella` from `linkedin.com/in/satyanadella`. Full URLs and member IDs work too.
3. Set **Max posts per profile**. 100 is enough to see what the data looks like.
4. Turn off **Include reposts** if you only want the profile's own writing.
5. Click **Start**. Posts stream into the dataset as each page arrives.
6. Open the **Storage** tab and export as CSV, Excel or JSON, or fetch the dataset from the API.

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

Pricing is per event. There is no charge for compute time.

| Event | When it fires | Price |
|---|---|---|
| `post-scraped` | Each post added to your dataset | $0.003 |
| `profile-processed` | Each profile that was read. A profile that could not be found or read is free | $0.01 |
| `apify-default-dataset-item` | Each result in the default dataset | $0.00001 |
| `apify-actor-start` | Per GB of allocated memory, with a minimum of one event | $0.00005 per GB ($0.0002 at the 4 GB default) |

Volume discounts on paid Apify plans bring the per-post price down to $0.001.

**Worked examples**

- 100 posts from 1 profile costs **$0.3112**
- 1,000 posts from 10 profiles costs **$3.1102**
- 5,000 posts from 50 profiles costs **$15.5502**

These examples use free-plan event prices and one run at the default 4 GB memory. The calculation is posts × $0.00301 + readable profiles × $0.01 + $0.0002 for starting the run.

At 100 posts per profile, Apify's free plan ($5/month) covers about 1,600 posts across 16 readable profiles ($4.9762 at the default memory). Nothing is charged on top. `maxDatasetItems` is a hard ceiling; the run stops as soon as it is reached.

The `profile-processed` event is charged when a profile was successfully read, including a readable profile with zero posts. A profile that could not be read is not charged that event; the run's start fee still applies.

### Input

| Field | Type | Required | Default | Description |
|---|---|---|---|---|
| `usernames` | array | yes | — | LinkedIn usernames, profile URLs or member IDs, e.g. `["satyanadella", "williamhgates"]` |
| `maxPostsPerProfile` | integer | no | 100 | Posts to collect per profile, 1–2,000 |
| `includeReposts` | boolean | no | `true` | When `false`, returns only posts the profile authored (see below) |
| `maxDatasetItems` | integer | no | 10,000 | Hard cap on total posts across all profiles |
| `maxRetries` | integer | no | 3 | Retries for a failed request |

```json
{
  "usernames": ["adamselipsky"],
  "maxPostsPerProfile": 100,
  "includeReposts": true,
  "maxDatasetItems": 10000
}
```

#### Filtering out reposts

A LinkedIn feed mixes three kinds of posts:

| `post_type` | What it is | Kept when `includeReposts: false`? |
|---|---|---|
| `regular` | Written by the profile | Yes |
| `repost` | Someone else's post, reshared as-is | No |
| `quote` | Someone else's post with added commentary | No |

Set `includeReposts` to `false` for voice analysis, content audits or training data where reshared material is noise. Every row also carries `is_shared_content` so you can verify the filter yourself.

**You still get the full count you asked for.** Filtering happens per page, and the Actor keeps paginating until it has `maxPostsPerProfile` original posts. The only exception is a profile that does not have that many, in which case you get everything available and the log says how many were filtered. Reshare-heavy profiles take a little longer to reach the count.

### Output

One item per post. This representative excerpt uses the profile in the input above; post content, dates and engagement change over time. The complete field list is in the table above.

```json
{
  "activity_urn": "7470793400858984449",
  "share_urn": "7470793399273537536",
  "full_urn": "urn:li:activity:7470793400858984449",
  "post_url": "https://www.linkedin.com/posts/adamselipsky_achieving-success-with-ai-the-official",
  "post_type": "repost",
  "is_repost": true,
  "is_shared_content": true,

  "text": "My conversations with customers today are less about whether to adopt AI...",
  "content_category": "article",
  "word_count": 157,
  "char_count": 990,
  "hashtags": ["AI", "CloudComputing"],
  "hashtag_count": 2,

  "media_type": "image",
  "media_url": "https://media.licdn.com/dms/image/...",
  "media_thumbnail": "https://media.licdn.com/dms/image/...",

  "has_article": true,
  "article_url": "https://blogs.microsoft.com/blog/2026/06/16/achieving-success-with-ai/",
  "article_title": "Achieving success with AI - The Official Microsoft Blog",
  "article_subtitle": "blogs.microsoft.com",

  "has_document": false,
  "document_title": "",
  "document_page_count": null,

  "author_name": "Adam Selipsky",
  "author_headline": "CEO of Helix Digital Infrastructure. Former CEO at Amazon Web Services.",
  "author_username": "adamselipsky",
  "author_profile_url": "https://www.linkedin.com/in/adamselipsky",
  "author_profile_picture": "https://media.licdn.com/dms/image/...",

  "total_reactions": 2173,
  "reaction_like": 1882,
  "reaction_love": 44,
  "reaction_celebrate": 204,
  "reaction_support": 12,
  "reaction_insight": 30,
  "reaction_funny": 1,
  "reaction_curious": 0,
  "num_comments": 187,
  "num_reposts": 55,
  "total_engagement": 2415,

  "mentioned_companies": [
    { "name": "Amazon Web Services (AWS)", "urn": "https://www.linkedin.com/company/amazon-web-services/" }
  ],
  "mentioned_profiles": [],

  "posted_date": "2026-06-11 11:05:47",
  "posted_relative": "1w",
  "posted_timestamp": 1781175947394,
  "posted_date_iso": "2026-06-11T11:05:47.394000+00:00",

  "profile_username": "adamselipsky",
  "scraped_at": "2026-06-17T15:30:00.000000+00:00"
}
```

A run summary is saved to the key-value store as `OUTPUT`, and its `message` is shown as the run's status in Console:

```json
{
  "status": "SUCCESS",
  "reason": null,
  "profiles_processed": 1,
  "total_profiles": 1,
  "total_posts_scraped": 100,
  "message": "Collected 100 posts from 1 of 1 profile.",
  "profiles": [
    { "profile": "adamselipsky", "status": "OK", "posts": 100, "reason": null, "message": null }
  ]
}
```

`status` is `SUCCESS`, `PARTIAL_SUCCESS` (some profiles could not be read in full), `NO_RESULTS`, `STOPPED` (the run could not continue, and the message says why) or `VALIDATION_ERROR` (a problem with the input). When something goes wrong, `reason` names it, `message` says what to do, and each entry in `profiles` carries its own reason.

### Popular use cases (ready-to-run templates)

Each link opens a pre-filled run you can start in one click:

- [Top GTM leaders' LinkedIn posts](https://apify.com/capable_cauldron/linkedin-profile-posts-scraper/examples/top-gtm-leaders-linkedin-posts)
- [Track competitor LinkedIn posts and engagement](https://apify.com/capable_cauldron/linkedin-profile-posts-scraper/examples/track-competitor-linkedin-posts)
- [Analyze what makes LinkedIn posts go viral](https://apify.com/capable_cauldron/linkedin-profile-posts-scraper/examples/analyze-viral-linkedin-posts)
- [Reverse-engineer a creator's content strategy](https://apify.com/capable_cauldron/linkedin-profile-posts-scraper/examples/research-creator-content-strategy)
- [Export LinkedIn posts to Google Sheets](https://apify.com/capable_cauldron/linkedin-profile-posts-scraper/examples/export-linkedin-posts-to-sheets)
- [Find B2B sales triggers in LinkedIn posts](https://apify.com/capable_cauldron/linkedin-profile-posts-scraper/examples/extract-sales-intelligence-from-posts)
- [Monitor executives' LinkedIn activity](https://apify.com/capable_cauldron/linkedin-profile-posts-scraper/examples/monitor-executive-linkedin-activity)
- [LinkedIn posts for AI agents and RAG pipelines](https://apify.com/capable_cauldron/linkedin-profile-posts-scraper/examples/linkedin-posts-for-ai-agents)
- [Benchmark LinkedIn engagement across profiles](https://apify.com/capable_cauldron/linkedin-profile-posts-scraper/examples/benchmark-linkedin-engagement)
- [Track LinkedIn hashtag performance](https://apify.com/capable_cauldron/linkedin-profile-posts-scraper/examples/track-linkedin-hashtag-performance)
- [Analyze B2B social selling posts](https://apify.com/capable_cauldron/linkedin-profile-posts-scraper/examples/analyze-b2b-social-selling-posts)

### API and integrations

Run it from your own code with the Apify API. Swap in your token; the Actor id stays as written.

**Python**

```python
from apify_client import ApifyClient

client = ApifyClient("<YOUR_API_TOKEN>")
run = client.actor("capable_cauldron/linkedin-profile-posts-scraper").call(run_input={
    "usernames": ["satyanadella"],
    "maxPostsPerProfile": 100,
})
for item in client.dataset(run["defaultDatasetId"]).iterate_items():
    print(item["posted_date_iso"], item["total_engagement"], item["text"][:80])
```

**JavaScript**

```javascript
import { ApifyClient } from "apify-client";

const client = new ApifyClient({ token: "<YOUR_API_TOKEN>" });
const run = await client.actor("capable_cauldron/linkedin-profile-posts-scraper").call({
  usernames: ["satyanadella"],
  maxPostsPerProfile: 100,
});
const { items } = await client.dataset(run.defaultDatasetId).listItems();
```

**CLI**

```bash
echo '{"usernames": ["satyanadella"], "maxPostsPerProfile": 100}' | apify call capable_cauldron/linkedin-profile-posts-scraper --silent --output-dataset
```

Connect results to **Google Sheets, Airtable, Slack, Make, Zapier or n8n** from the Actor's **Integrations** tab, run it on a **Schedule** to track a profile weekly, or fire a **webhook** when a run finishes.

### FAQ

#### Is it legal to scrape LinkedIn posts?

This Actor collects posts that are publicly visible on LinkedIn, without logging in. You are responsible for how you use the data, including compliance with LinkedIn's terms and the data-protection laws that apply to you (GDPR, CCPA). The Actor is an independent tool and is not affiliated with or endorsed by LinkedIn.

#### Do I need LinkedIn cookies or an account?

No. The Actor reads public post data without a session, so there is nothing to export or refresh and your own account is never involved.

#### Why did I get fewer posts than I asked for?

The profile has fewer posts than `maxPostsPerProfile`, or `maxDatasetItems` was reached across all profiles. With `includeReposts: false`, a profile that mostly reshares may not have enough original posts. Occasionally the feed stops responding part way; the posts collected so far are kept and the profile is marked `PARTIAL`. The run's status message and the `profiles` list in `OUTPUT` say which.

#### What happens if a profile can't be found?

That profile is skipped with the message "No public posts could be found for this profile", no profile or post event is charged for it, and the rest of the run continues. The run's start fee still applies. Check the spelling, or paste the full profile link. A readable profile with no posts is different: it still incurs the profile-processing event.

#### Can I scrape company pages?

This Actor is built for personal profiles (`linkedin.com/in/...`). Company page URLs are not supported.

#### How far back does it go?

As far as the profile's activity feed allows. Set `maxPostsPerProfile` up to 2,000 to walk a long history.

#### Can I scrape LinkedIn posts with Python?

Yes. See the Python snippet under **API and integrations**. The `apify-client` package is on PyPI; pass the same input you would use in Console.

#### How do I also get the comments on each post?

Feed the `post_url` values into [LinkedIn Comment Scraper](https://apify.com/capable_cauldron/linkedin-comment-scraper). That Actor needs your LinkedIn cookies because LinkedIn hides comments from anonymous visitors.

### Other Actors by capable_cauldron

| Actor | What it does |
|---|---|
| App Store Reviews Scraper (private testing) | Reviews and ratings for iPhone and iPad apps, grouped by app and country |
| Company Job Postings Scraper (private testing) | Open roles and hiring summaries from supported company job boards |
| Bulk Email Validator (private testing) | Syntax, mail-routing, disposable-domain and role-inbox checks |
| Work Email Finder (private testing) | Verified professional emails from LinkedIn URLs or a name and company domain |
| GTM Account Enrichment (private testing) | Public company contacts, technologies and hiring signals with an account fit score |
| [Investor Database Search](https://apify.com/capable_cauldron/investor-database-search) | Filter investors by stage, industry and geography and export available partner contacts |
| [LinkedIn Comment Scraper](https://apify.com/capable_cauldron/linkedin-comment-scraper) | LinkedIn comments and replies using your own session cookies |
| LinkedIn Post Comments Scraper (private testing) | Comments, replies and reactions on public LinkedIn posts without cookies |
| [Multi-Channel Ad Intelligence](https://apify.com/capable_cauldron/multi-channel-ad-intelligence) | Competitor ads from Meta, Google, LinkedIn and TikTok in one dataset |
| TikTok Shop USA Scraper (private testing) | US product, shop, creator and shoppable-video data from TikTok Shop |
| Website Contact Scraper (private testing) | Public emails, phone numbers and social profile links from company websites |
| Website Tech Stack Detector (private testing) | Visible website technologies and the evidence supporting each detection |

### Support

Found a bug or need a field that isn't here? Open an issue on the Actor's **Issues** tab. Issues are usually answered within 24 hours. If you need a custom version (company pages, comment threads, a private deployment), describe it in an issue and we will scope it.

# Actor input Schema

## `usernames` (type: `array`):

LinkedIn usernames, member IDs, or profile URLs.

Accepted formats:

- Vanity username: satyanadella
- Profile URL: https://www.linkedin.com/in/satyanadella/
- Member ID: ACoAAAEkwwAB9KEc2TrQgOLEQ-vzRyZeCDyc6DQ
- Sales Navigator: linkedin.com/sales/people/ACoAAAEkwwAB9KEc2TrQgOLEQ-vzRyZeCDyc6DQ,name,qU7\_

Pagination is handled automatically.

## `maxPostsPerProfile` (type: `integer`):

Maximum number of posts to scrape per profile. The actor automatically handles pagination — no need to manually pass pagination tokens.

## `includeReposts` (type: `boolean`):

When enabled (default), every post on the profile is returned, including reposts and reposts with commentary.

When disabled, only posts originally authored by the profile are returned — both plain reposts and reposts with added commentary are excluded. Filtering happens after each page is fetched, and the actor keeps paginating until it has collected the number of original posts you asked for, so you still receive the full 'Max Posts Per Profile' count where the profile has enough original content.

## `maxDatasetItems` (type: `integer`):

Hard cap on the total number of items pushed to the dataset across all profiles. Prevents runaway costs on large runs.

## `maxRetries` (type: `integer`):

How many times to retry a failed API request before giving up. Applies exponential backoff on retries.

## Actor input object example

```json
{
  "usernames": [
    "satyanadella"
  ],
  "maxPostsPerProfile": 100,
  "includeReposts": true,
  "maxDatasetItems": 10000,
  "maxRetries": 3
}
```

# Actor output Schema

## `posts` (type: `string`):

All scraped posts from LinkedIn profiles, including post text, engagement metrics, author details, content categories, hashtags, mentioned entities, and computed fields.

## `summary` (type: `string`):

Summary of the scraping run including profiles processed, total posts scraped, and pagination tokens.

# 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 = {
    "usernames": [
        "satyanadella"
    ]
};

// Run the Actor and wait for it to finish
const run = await client.actor("capable_cauldron/linkedin-profile-posts-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 = { "usernames": ["satyanadella"] }

# Run the Actor and wait for it to finish
run = client.actor("capable_cauldron/linkedin-profile-posts-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 '{
  "usernames": [
    "satyanadella"
  ]
}' |
apify call capable_cauldron/linkedin-profile-posts-scraper --silent --output-dataset

```

## MCP server setup

```json
{
    "mcpServers": {
        "apify": {
            "type": "http",
            "url": "https://mcp.apify.com/?tools=fetch-actor-details,capable_cauldron/linkedin-profile-posts-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/nIejzIcDE5QY5qgsA/builds/6444yYLTuJjEJ4vdU/openapi.json
