# LinkedIn Posts Scraper - Profile & Company Posts, No Login (`eiv/linkedin-posts-scraper`) Actor

Scrape LinkedIn posts from profiles, company pages and post URLs without login: full text, exact post time, author, reactions, comment count, images, video, hashtags, mentions and reposts. Optional comments, liked posts, articles and related posts. From $0.70 per 1,000 posts.

- **URL**: https://apify.com/eiv/linkedin-posts-scraper.md
- **Developed by:** [Eimantas V](https://apify.com/eiv) (community)
- **Security:** Limited permissions
- **Stats:** 4 total users, 2 monthly users, 82.5% runs succeeded, 0 bookmarks
- **User rating**: No ratings yet

## Pricing

from $0.70 / 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

**LinkedIn Posts Scraper** extracts posts from **LinkedIn** profiles, company pages and post URLs: full text, exact posting time, author, reactions, comment count, images, video, hashtags, mentions, reposts and quotes, with optional comments. Paste profile links or usernames, company pages or post links, get one row per post. No login, no cookies, no LinkedIn account at risk, from **$0.70 per 1,000 posts**.

```
postedAt                  authorName        reactions  comments  mediaType  activityType  text
2026-10-28T22:56:51.348Z  Satya Nadella         11619       475  image      post          Just wrapped our earnings call. It was a fast start to our fiscal year...
2026-10-28T23:43:13.505Z  Microsoft               169         9  video      post          Ready for what's next? Microsoft Chairman and CEO Satya Nadella...
2026-10-28T22:56:51.349Z  Satya Nadella         11619       475  image      repost        (reposted by Microsoft)
```

**Benchmark: 19 posts from a profile and a company page in 4 seconds; 376 posts with 2,989 comments from 41 profiles and companies in 59 seconds.**

### What does LinkedIn Posts Scraper do?

It reads the posts LinkedIn shows to logged-out visitors, the same way your browser does without signing in, and turns them into clean rows. A profile gives the member's recent posts and reposts (and, if you want, the posts they reacted to and their LinkedIn articles); a company page gives its latest posts; a post URL gives that post with its comments and, optionally, the related posts LinkedIn shows beside it.

- **Profiles, companies and posts in one list.** `linkedin.com/in/...` links or plain usernames, `linkedin.com/company/...` and showcase pages, `linkedin.com/posts/...` and `feed/update/urn:li:activity:...` links, even bare URNs.
- **Exact times and full texts.** Posting time to the millisecond (read from the post id, not "3w"), the full post text with its line breaks, hashtags, mentions and links pulled out.
- **Engagement in every row.** Reactions, comments, the top reaction types and an engagement rate against the author's followers.
- **Comments when you want them.** Up to 10 per post with commenter, headline, text, time and likes, charged per comment.
- **Only pay for results.** Hidden profiles, deleted or members-only posts, duplicates and filtered posts return no row or an error row, and are never charged.
- **Built for automation.** Run it on a schedule, call it from the API, or connect it to Make, Zapier, n8n, Google Sheets or an AI agent through Apify's MCP server.

### Why it is fast and cheap

LinkedIn renders profiles, company pages and posts on its servers for visitors who are not signed in. The scraper fetches those pages over plain HTTP with a real browser's network fingerprint and reads LinkedIn's own structured data from them: no browser, no login, no paid proxy. A profile or company page is a single request for all its recent posts: three profiles and companies returned 28 posts in 2.3 seconds. When LinkedIn slows one address down, the scraper moves to another by itself.

### What data can you extract from LinkedIn?

| Field | Example | What it is |
|---|---|---|
| `text` | `Just wrapped our earnings call...` | Full post text with line breaks |
| `postedAt` | `2026-10-28T22:56:51.348Z` | Exact posting time, ISO 8601 UTC |
| `authorName`, `authorUrl`, `authorHeadline` | `Satya Nadella`, `.../in/satyanadella`, `Chairman and CEO at Microsoft` | Who wrote it (member or company) |
| `authorFollowers` | `12264844` | The author's followers, when the page shows them |
| `reactions`, `comments` | `11619`, `475` | Engagement at scrape time |
| `reactionTypes` | `["LIKE", "INTEREST", "PRAISE"]` | The top reaction types |
| `engagementRate` | `0.0986` | (reactions + comments) / followers x 100 |
| `activityType` | `post`, `quote`, `repost`, `reaction`, `article` | What the post is to the profile or company you scraped |
| `mediaType` | `image`, `video`, `link`, `text`, `article` | What the post shows besides text |
| `imageUrls`, `videoUrl`, `videoDurationSecs` | `[...]`, `https://dms.licdn.com/...mp4`, `63` | Media files (video files with post URLs or comments on) |
| `linkUrl`, `linkTitle` | `https://www.linkedin.com/pulse/...` | A shared link and its preview title |
| `hashtags`, `mentions`, `links` | `["MSIgnite"]`, `[{name, url}]`, `["https://lnkd.in/..."]` | Pulled out of the text |
| `resharedAuthorName`, `resharedText`, `resharedPostUrl` | `Agnes Heftberger`, `Wonderful news...` | For quotes: the quoted post |
| `activityByName` | `Microsoft` | For reposts and reactions: who reposted or reacted |
| `commentsList` | `[{authorName, authorHeadline, text, postedAt, likes}]` | With "Include comments" |
| `postId`, `url`, `shareUrn` | `7521344259774660609`, `https://www.linkedin.com/posts/...` | Stable id and clean link |
| `input`, `source` | `https://www.linkedin.com/in/satyanadella`, `profile` | Which of your inputs the row came from |

### How to scrape LinkedIn posts

1. Click **Try for free** and paste LinkedIn profile links or usernames, company pages or post links into **Profiles, companies or posts**, one per line.
2. Optionally set a date range, content types, or turn on comments, reacted-to posts, articles or related posts.
3. Click **Start**. A list of profiles and companies takes seconds; with comments, about a minute per 40 inputs.
4. Open the **Output** tab (views: Overview, Engagement, Media and links, Comments), or download the results as JSON, CSV, Excel or HTML.

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

You pay per post returned, and the price drops on higher Apify plans. Comments are an optional add-on, charged per comment:

| Apify plan | Per 1,000 posts | Per 1,000 comments (add-on) |
|---|---|---|
| Free | $1.20 | $0.60 |
| Starter | $1.00 | $0.50 |
| Scale | $0.85 | $0.42 |
| Business | $0.70 | $0.35 |

- **100 profiles** with about 9 recent posts each = ~900 posts = **$0.90** on Starter.
- **200 posts with their comments** (about 8 each) = $0.20 + 1,600 comments x $0.0005 = **$1.00** on Starter.
- A run also costs **$0.00005** to start. An input that fails, or has nothing that matches your filters, costs nothing more.
- The Free plan's $5 monthly credit covers about **4,000 posts**.

### Input

```json
{
    "targets": [
        "https://www.linkedin.com/in/satyanadella",
        "https://www.linkedin.com/company/microsoft/",
        "https://www.linkedin.com/feed/update/urn:li:activity:7391573088309534720/"
    ],
    "postedAfter": "30 days",
    "includeComments": true,
    "maxCommentsPerPost": 10
}
```

| Field | Default | Notes |
|---|---|---|
| Profiles, companies or posts | `https://www.linkedin.com/in/satyanadella`, `https://www.linkedin.com/company/microsoft/` | Profile links or usernames, company or showcase pages, post links or URNs, one per line |
| Start URLs | empty | The same in the URL-list shape other Actors output, for chaining |
| Max posts per profile or company | 50 | Logged out, LinkedIn shows about 8-10 recent posts per profile or company |
| Max posts in total | 1,000 | Your cost cap for the run |
| Posted after / before | empty | A date (`2026-10-01`) or relative (`7 days`, `3 months`); exact to the millisecond |
| Content types | all | Text, images, videos, documents, links, polls, events, articles |
| Include reposts / quote posts | on / on | Reposts name who reposted; quotes carry the quoted post |
| Include posts the member reacted to | off | Profiles: posts from the Reactions and Comments tabs |
| Include LinkedIn articles | off | Profiles: up to 10 LinkedIn articles |
| Include comments | off | Up to 10 per post; for profile and company posts it opens each post's page |
| Max comments per post | 10 | Lower it to pay less |
| Include related posts | off | Post URLs: the ~10 "More Relevant Posts" beside the post |

No proxy setting is needed: the scraper picks its own addresses.

### Output

Each post is one row in the dataset. The **Overview** view shows the key columns, **Comments** shows one line per comment; every export includes all fields.

```json
{
    "recordType": "post",
    "input": "https://www.linkedin.com/in/satyanadella",
    "source": "profile",
    "activityType": "post",
    "postId": "7521344259774660609",
    "url": "https://www.linkedin.com/posts/satyanadella_just-wrapped-our-earnings-call-it-was-a-activity-7521344259774660609-7i67",
    "text": "Just wrapped our earnings call. It was a fast start to our fiscal year.\n\nMicrosoft Cloud revenue surpassed $63B, with growth accelerating to 30% YoY...",
    "postedAt": "2026-10-28T22:56:51.348Z",
    "postedAgo": "12h",
    "authorName": "Satya Nadella",
    "authorType": "person",
    "authorUrl": "https://www.linkedin.com/in/satyanadella",
    "authorUsername": "satyanadella",
    "authorHeadline": "Chairman and CEO at Microsoft",
    "authorFollowers": 12264844,
    "reactions": 11619,
    "comments": 475,
    "reactionTypes": ["LIKE", "INTEREST", "PRAISE"],
    "engagementRate": 0.0986,
    "mediaType": "image",
    "imageUrls": ["https://media.licdn.com/dms/image/v2/..."],
    "videoUrl": null,
    "hashtags": [],
    "mentions": [],
    "links": ["https://lnkd.in/gVpbWFZK"],
    "resharedAuthorName": null,
    "activityByName": null,
    "commentsList": [
        {
            "authorName": "Satya Nadella",
            "authorType": "person",
            "authorUrl": "https://www.linkedin.com/in/satyanadella",
            "authorHeadline": "Chairman and CEO at Microsoft",
            "text": "Learn more: https://techcommunity.microsoft.com/...",
            "postedAt": "2025-11-04T20:33:02.913Z",
            "postedAgo": "11mo",
            "likes": 62
        }
    ],
    "scrapedAt": "2026-10-29T10:57:22.765Z"
}
```

(The comment shown is from another post; `commentsList` is `null` unless you turn comments on.)

An input that cannot be read becomes a row with `"recordType": "error"` and an `errorCode` instead of failing the whole run:

| `errorCode` | Meaning |
|---|---|
| `NOT_FOUND` | No such post or company page, or the link is wrong |
| `PROFILE_NOT_PUBLIC` | The member hides their profile from logged-out visitors, or the username does not exist |
| `POST_NOT_PUBLIC` | LinkedIn shows this post only to signed-in members, or it was deleted |
| `NO_POSTS` | The profile or company page shows no posts logged out |
| `NOT_SUPPORTED` | School pages, which LinkedIn shows only to members |
| `DUPLICATE` | Another input of the run is the same post; it is delivered once |
| `RATE_LIMITED` | LinkedIn refused every address the run tried; run it again later |

Error rows are never charged.

### Tips and limits

- **Recent posts, not full history.** Logged out, LinkedIn shows about 8-10 recent posts per profile or company page (plus reactions and articles on profiles). To build a history, schedule the scraper daily or weekly and keep the `postId`s you have not seen.
- **No keyword search.** LinkedIn's post search needs a signed-in account, so this scraper takes profiles, companies and post links. Turn on **Include related posts** on a few post links to discover more posts on the same topic.
- **Hidden profiles.** Many members hide their public profile from logged-out visitors; those come back as `PROFILE_NOT_PUBLIC`, uncharged. Their public posts can still be scraped by post link.
- **Comments are the first ~10.** LinkedIn shows logged-out visitors up to about 10 comments per post, without replies and without the list of people who reacted. Some posts open only for members; they are delivered with an empty `commentsList` and no comment charge.
- **Video files and repost counts.** The video file comes from the post's own page (post links, or with comments on). LinkedIn does not show repost counts logged out.
- **Hit your spending limit?** The run stops cleanly at your maximum cost per run and keeps everything it collected. Raise the limit in the run options to get more.

### FAQ

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

This Actor collects only data that LinkedIn shows publicly to visitors who are not signed in, without logging in or bypassing any login. Results can still contain personal data (names, headlines, comments), which laws such as the GDPR protect. Scrape personal data only for a legitimate purpose, keep only what you need, and ask a lawyer if you are unsure. LinkedIn is a trademark of LinkedIn Corporation; this Actor is not affiliated with or endorsed by it.

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

No. Nothing is logged in, so no account can be restricted or banned.

#### Can I use it through the API or with Make, Zapier and n8n?

Yes. Every run can be started through the [Apify API](https://docs.apify.com/api/v2) and returns the dataset as JSON, CSV or Excel. Schedules, webhooks and integrations for Make, Zapier, n8n and Google Sheets are on the **Integrations** tab.

#### Can AI agents use it?

Yes. Agents connected to [Apify's MCP server](https://mcp.apify.com) can find and run this Actor as a tool, with the same per-post pricing.

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

LinkedIn shows only the recent posts of a profile or company to logged-out visitors, your date or type filters left some out, the run reached your maximum cost per run, or an input failed (see its error row). The log's summary line says which.

### Related scrapers

- [LinkedIn Company Scraper](https://apify.com/eiv/linkedin-company-scraper): followers, employee count, industry, offices and website of the companies whose posts you track.
- [LinkedIn Jobs Scraper](https://apify.com/eiv/linkedin-jobs-scraper): the jobs those companies are hiring for, with salaries and applicant counts.
- [LinkedIn Ad Library Scraper](https://apify.com/eiv/linkedin-ad-library-scraper): the ads a company runs on LinkedIn, next to its organic posts.

### Support

Missing a field, or found a profile or post that does not work? Open an issue on the **Issues** tab with the input you used, and it will be looked at quickly.

# Actor input Schema

## `targets` (type: `array`):

One per line: profile URLs (linkedin.com/in/satyanadella) or usernames (satyanadella), company or showcase pages (linkedin.com/company/microsoft), and post URLs (linkedin.com/posts/... or linkedin.com/feed/update/urn:li:activity:...). A profile or company page gives its latest posts as LinkedIn shows them to logged-out visitors (about 10); a post URL gives that post.

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

The same profiles, companies or posts in the URL-list shape other Actors output, so a previous Actor's results (for example LinkedIn company or profile URLs) can be fed straight in. Use this or the field above.

## `maxItemsPerTarget` (type: `integer`):

Stop after this many posts from any one profile, company page or post URL (with related posts). Logged out, LinkedIn shows about 8-10 recent posts per profile or company, plus reactions and articles when you turn those on.

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

Stop after this many posts in the whole run. You pay per post, so this is also your cost cap for the run.

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

Only posts published on or after this date: 2026-10-01 (UTC), or relative such as "7 days", "2 weeks" or "3 months". Exact to the millisecond (LinkedIn post ids encode the time). Applies to profile and company posts and to related posts, not to the post URLs you list.

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

Only posts published before this date: 2026-10-15 (UTC), or relative such as "1 month". Use both date fields for a date range.

## `contentTypes` (type: `array`):

Only posts with this kind of content. Leave empty for every type. For reposts and quotes, the content of the post shown.

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

Posts the profile or company reposted without adding text. The row describes the original post (its author, text and counts) and names who reposted it.

## `includeQuotePosts` (type: `boolean`):

Posts that share another post with the profile's own text on top. The row holds that text and the quoted author and text.

## `includeReactedPosts` (type: `boolean`):

Profiles only: the posts in the member's Reactions and Comments tabs (others' posts they liked, celebrated or commented on; usually 2-8). Good for spotting what a lead engages with. No extra requests.

## `includeArticles` (type: `boolean`):

Profiles only: the member's LinkedIn articles (linkedin.com/pulse/...) with title, date, image and likes, up to 10. No extra requests.

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

Add the comments LinkedIn shows logged out under each post (up to 10: author, headline, text, time, likes). Post URLs already include them; for profile and company posts this opens each post's page, about 10x the requests and slower. Charged per comment (see Pricing).

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

With "Include comments": keep at most this many comments per post (LinkedIn shows at most about 10 to logged-out visitors). Lower it to pay less.

## `includeRelatedPosts` (type: `boolean`):

Post URLs only: also return the ~10 "More Relevant Posts" LinkedIn shows beside the post (other members' posts on the same topic). A cheap way to discover posts and authors around a subject. No extra requests; each is charged as a post.

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

How many profiles, companies or posts are fetched at the same time. LinkedIn limits each address; the Actor rotates addresses by itself, so higher values rarely help.

## `requestTimeoutSecs` (type: `integer`):

How long to wait for one LinkedIn page before trying another address.

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

Retries for a dropped connection on the same address. Refusals by LinkedIn are not retried here; the Actor moves to another address instead.

## Actor input object example

```json
{
  "targets": [
    "https://www.linkedin.com/in/satyanadella",
    "https://www.linkedin.com/company/microsoft/"
  ],
  "maxItemsPerTarget": 50,
  "maxItems": 1000,
  "includeReposts": true,
  "includeQuotePosts": true,
  "includeReactedPosts": false,
  "includeArticles": false,
  "includeComments": false,
  "maxCommentsPerPost": 10,
  "includeRelatedPosts": false,
  "maxConcurrency": 5,
  "requestTimeoutSecs": 30,
  "maxRetries": 1
}
```

# Actor output Schema

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

One row per post (recordType "post"), plus one uncharged row per input that could not be read (recordType "error"). Views: Overview, Engagement, Media and links, Comments.

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

Totals for the run: inputs, posts, comments, failures, why the run stopped, requests and megabytes.

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

With "Include comments": one row per comment, with the post it belongs to.

# 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 = {
    "targets": [
        "https://www.linkedin.com/in/satyanadella",
        "https://www.linkedin.com/company/microsoft/"
    ]
};

// Run the Actor and wait for it to finish
const run = await client.actor("eiv/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 = { "targets": [
        "https://www.linkedin.com/in/satyanadella",
        "https://www.linkedin.com/company/microsoft/",
    ] }

# Run the Actor and wait for it to finish
run = client.actor("eiv/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 '{
  "targets": [
    "https://www.linkedin.com/in/satyanadella",
    "https://www.linkedin.com/company/microsoft/"
  ]
}' |
apify call eiv/linkedin-posts-scraper --silent --output-dataset

```

## MCP server setup

```json
{
    "mcpServers": {
        "apify": {
            "type": "http",
            "url": "https://mcp.apify.com/?tools=fetch-actor-details,eiv/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/7ieQNhxnbDBHQ7JIo/builds/0abuPbfMNs3X36m8L/openapi.json
