# Posts Scraper for LinkedIn - Profiles, Pages & Search (`scrapesage/linkedin-posts-scraper`) Actor

Scrape LinkedIn posts from any profile, company page, keyword search or direct post URL. Returns the full post text, exact reaction and comment counts, the top comments, hashtags, links and media. No login and no cookies.

- **URL**: https://apify.com/scrapesage/linkedin-posts-scraper.md
- **Developed by:** [Scrape Sage](https://apify.com/scrapesage) (community)
- **Categories:** Social media, Lead generation, Marketing
- **Stats:** 2 total users, 1 monthly users, 100.0% runs succeeded, 0 bookmarks
- **User rating**: No ratings yet

## Pricing

$4.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.

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

## Posts Scraper for LinkedIn - Profiles, Pages & Search

**Four ways in, one clean table out.** Point it at a person, a company page, a keyword, or a post URL and get the posts back with the full text, exact reaction and comment counts, and the comments themselves. No login, no cookies, no session tokens.

Most LinkedIn post scrapers make you buy the pieces separately - one actor for profile posts, another for company posts, another for keyword search, and another again for comments. This one does all four, and the comments come included.

### Four inputs

| Input | What you get | Typical use |
|---|---|---|
| `profileUrls` | A person's recent public posts | Track a founder, exec, or competitor's spokesperson |
| `companyUrls` | A company page's recent posts | Competitor content monitoring, brand tracking |
| `searchKeywords` | Public posts mentioning a phrase | Social listening, buying-signal hunting ("hiring a CTO") |
| `postUrls` | Exactly the posts you name | Enrich a list you already have |

Mix them freely in one run. Every row says which source found it via `sourceType`.

### What each post row contains

```json
{
  "type": "post",
  "postUrl": "https://www.linkedin.com/posts/supabase_today-were-open-sourcing-supabase-evals-activity-7489047352075460608-EGgJ",
  "activityId": "7489047352075460608",
  "authorName": "Supabase",
  "authorType": "company",
  "authorUrl": "https://www.linkedin.com/company/supabase",
  "text": "Today we're open-sourcing Supabase Evals, our benchmark for how well AI coding agents build with Supabase...",
  "textLength": 1001,
  "datePublished": "2026-07-31T20:00:28.487Z",
  "postedAgoText": "1w",
  "reactionCount": 286,
  "commentCount": 25,
  "engagementTotal": 311,
  "topComments": [
    {
      "text": "Nice. The part I'd want as a user is a way to know the copy in the warehouse still matches Postgres...",
      "authorName": "Renee Romero",
      "authorUrl": "https://www.linkedin.com/in/renee-romero",
      "postedAgoText": "2w"
    }
  ],
  "hashtags": ["postgres"],
  "mentions": [],
  "externalLinks": ["https://lnkd.in/gbRHqH-e"],
  "imageUrl": "https://media.licdn.com/dms/image/...",
  "hasMedia": true,
  "detailFetched": true,
  "sourceType": "company",
  "scrapedAt": "2026-08-07T04:10:00.000Z"
}
```

### Filters that run while it crawls

`postedAfter` / `postedBefore` for a date window, and `minReactions` to keep only the posts that actually performed. They are applied during the crawl, not to a truncated sample afterwards, so a filtered run still fills up to your `maxResults`.

### What LinkedIn does and does not serve logged-out

Measured on this actor's own runs, so you know what you are buying.

- **Recent posts, not the full archive.** A profile or company page publishes roughly its latest 6-20 posts to a logged-out visitor. There is no way to page back through years of history without an account, and this actor will not pretend otherwise. To go deeper on a topic rather than an author, use `searchKeywords`.
- **Engagement counts need the post page.** Company page listings do not publish reaction counts; the post's own page does. That is why `fetchPostDetails` defaults to on - turning it off is faster and cheaper but returns text and author only.
- **Post pages carry a relative age, not a timestamp.** Posts discovered from a profile or company page carry an exact ISO `datePublished`; posts reached only by URL or keyword may have just `postedAgoText` ("1w"). Both fields are emitted separately rather than converting a guess into a fake timestamp.
- **Comments are the ones LinkedIn shows publicly** - typically the top ~10, with author, relative age and (where published) a like count. Not the full thread.
- **Never returned:** anything behind the login wall - private posts, full reaction lists, connection graphs, or personal contact details.

### Pricing

Pay-per-event: **$0.004 per post**, comments included. A run that finds nothing charges nothing, and every finished run tells you what to change.

### Use with AI assistants (MCP)

This actor works as a tool in any MCP-compatible assistant through the [Apify MCP server](https://docs.apify.com/platform/integrations/mcp) - ask your agent to "find what our competitors posted on LinkedIn this month and how it performed" and it can call this actor directly.

### Agent-ready: autonomous payments (x402 & Skyfire)

This actor is **agent-ready** — AI agents can discover it, run it, and **pay for it autonomously**, with no Apify account and no human in the loop. It uses [pay-per-event](https://docs.apify.com/platform/actors/publishing/monetize/pay-per-event) pricing and [limited permissions](https://docs.apify.com/platform/actors/development/permissions), so it qualifies for Apify's agentic-payment standards:

- **[x402](https://docs.apify.com/platform/integrations/x402)** — an open, HTTP-native payment protocol. Agents pay per run in USDC on the Base network directly through the [Apify MCP server](https://docs.apify.com/platform/integrations/mcp) — no account, no API key.
- **[Skyfire](https://docs.apify.com/platform/integrations/skyfire)** — agent-to-service payments for fully autonomous AI-agent workflows.

Building an AI agent, MCP tool, or autonomous data pipeline? This scraper is ready to plug in and pay as it goes.

### Legal

This actor reads only what LinkedIn publishes to logged-out visitors. It does not log in, use cookies or session tokens, or attempt to reach private content. Post text and commenter names relate to identifiable people, so if you are in the EU or UK you are the data controller for whatever you do with the output: have a lawful basis, and honour deletion requests. Do not use it for spam.

This actor is not affiliated with, endorsed by, or sponsored by LinkedIn Corporation. LinkedIn is a trademark of LinkedIn Corporation.

# Actor input Schema

## `profileUrls` (type: `array`):

LinkedIn profile URLs (https://www.linkedin.com/in/username) or bare usernames. Returns that person's recent public posts.

## `companyUrls` (type: `array`):

LinkedIn company URLs (https://www.linkedin.com/company/supabase), slugs (supabase) or names. Returns that company page's recent posts.

## `searchKeywords` (type: `array`):

Find public posts mentioning a phrase, e.g. "hiring a CTO" or a product name. Use this for social listening and competitor monitoring when you do not know whose posts you want.

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

Specific LinkedIn post permalinks (https://www.linkedin.com/posts/...-activity-...). Fastest and most precise input when you already know the posts.

## `fetchPostDetails` (type: `boolean`):

Open each post's own page to get the exact reaction count, comment count, the top comments and any image or video. Turn off for a faster, cheaper run that returns text and author only - company page listings do not publish engagement counts on their own.

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

Include the comments LinkedIn publishes on the post page, each with its author, date and like count. Requires Fetch full post details.

## `maxComments` (type: `integer`):

How many top comments to keep on each post.

## `maxPostsPerSource` (type: `integer`):

Cap per profile, company page or keyword, so one busy source cannot consume the whole run.

## `maxResults` (type: `integer`):

Total cap across every source. Set 0 for no limit (explicit opt-in).

## `postedAfter` (type: `string`):

Only keep posts published on or after this date, e.g. 2026-01-01. Leave empty for no lower bound.

## `postedBefore` (type: `string`):

Only keep posts published on or before this date. Leave empty for no upper bound.

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

Only keep posts with at least this many reactions - useful for finding what actually performed. Needs Fetch full post details to be meaningful.

## `searchPages` (type: `integer`):

How deep to page the web search for each keyword. Pagination stops early when it goes dry.

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

How many posts to fetch in parallel. Lower is gentler on rate limits; higher is faster.

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

LinkedIn needs residential proxies for reliable logged-out access. Keep the default unless you know what you are changing.

## `urlsFromFile` (type: `string`):

Paste a list of URLs (one per line), OR one link to a .txt/.csv file, Google Sheet or Google Drive file containing them. Lets you import many Start URLs at once instead of typing each. Google Sheet/Drive share links are handled automatically.

## Actor input object example

```json
{
  "profileUrls": [
    "https://www.linkedin.com/in/paulcopplestone"
  ],
  "companyUrls": [
    "supabase"
  ],
  "searchKeywords": [
    "supabase"
  ],
  "postUrls": [],
  "fetchPostDetails": true,
  "includeComments": true,
  "maxComments": 10,
  "maxPostsPerSource": 20,
  "maxResults": 100,
  "minReactions": 0,
  "searchPages": 2,
  "maxConcurrency": 6,
  "proxyConfiguration": {
    "useApifyProxy": true,
    "apifyProxyGroups": [
      "RESIDENTIAL"
    ]
  }
}
```

# Actor output Schema

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

Every scraped post as a JSON item in the default dataset - text, author, date, engagement counts, top comments, hashtags, external links and media.

# 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 = {
    "profileUrls": [
        "https://www.linkedin.com/in/paulcopplestone"
    ],
    "companyUrls": [
        "https://www.linkedin.com/company/supabase"
    ],
    "searchKeywords": [],
    "postUrls": [],
    "proxyConfiguration": {
        "useApifyProxy": true,
        "apifyProxyGroups": [
            "RESIDENTIAL"
        ]
    },
    "urlsFromFile": ""
};

// Run the Actor and wait for it to finish
const run = await client.actor("scrapesage/linkedin-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 = {
    "profileUrls": ["https://www.linkedin.com/in/paulcopplestone"],
    "companyUrls": ["https://www.linkedin.com/company/supabase"],
    "searchKeywords": [],
    "postUrls": [],
    "proxyConfiguration": {
        "useApifyProxy": True,
        "apifyProxyGroups": ["RESIDENTIAL"],
    },
    "urlsFromFile": "",
}

# Run the Actor and wait for it to finish
run = client.actor("scrapesage/linkedin-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 '{
  "profileUrls": [
    "https://www.linkedin.com/in/paulcopplestone"
  ],
  "companyUrls": [
    "https://www.linkedin.com/company/supabase"
  ],
  "searchKeywords": [],
  "postUrls": [],
  "proxyConfiguration": {
    "useApifyProxy": true,
    "apifyProxyGroups": [
      "RESIDENTIAL"
    ]
  },
  "urlsFromFile": ""
}' |
apify call scrapesage/linkedin-posts-scraper --silent --output-dataset

```

## MCP server setup

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