# LinkedIn Post Scraper - $0.90 per 1,000, No Login (`dami_studio/linkedin-profile-posts-scraper`) Actor

Pull public posts from any LinkedIn profile: post text, title, author, image, publish time and the canonical post URL. No login, no cookies, no API key - public pages only. $0.90 per 1,000 posts plus $0.001 per run, and blocked or empty look-ups are never charged.

- **URL**: https://apify.com/dami\_studio/linkedin-profile-posts-scraper.md
- **Developed by:** [Dami's Studio](https://apify.com/dami_studio) (community)
- **Categories:** Lead generation, Social media, Automation
- **Stats:** 1 total users, 0 monthly users, 100.0% runs succeeded, 0 bookmarks
- **User rating**: No ratings yet

## Pricing

from $0.90 / 1,000 validated public posts

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

## LinkedIn Profile Posts Scraper

Extract only public LinkedIn posts that LinkedIn itself exposes through supplied public profile or post URLs. This actor does not use a login, cookies, private endpoints, residential proxies, contact enrichment, profile search, or data behind a sign-in wall.

### Pricing

**$0.90 per 1,000 posts** ($0.0009 each), plus $0.001 each time a run starts. Flat rate — no volume tiers, no plan gates — and you are charged only for posts actually returned.

A `post` event is charged only after a validated genuine row has been written to the dataset. Samples, diagnostics, duplicates, blocked look-ups and no-result runs **never incur the per-result fee** — a run that returns nothing costs only the $0.001 start fee.

### Input

```json
{
  "profileUrls": ["https://www.linkedin.com/in/reidhoffman/"],
  "postUrls": [],
  "maxPostsPerProfile": 10,
  "maxPosts": 25,
  "requestTimeoutSecs": 20
}
```

| Field | Type | Default | Range / limit |
|---|---|---|---|
| `profileUrls` | string list | `[]` | up to 20 public `/in/` profile URLs per run |
| `postUrls` | string list | `[]` | up to 100 direct public `/posts/...activity-...` URLs |
| `maxPostsPerProfile` | integer | `10` | 1–25 post pages fetched per supplied profile |
| `maxPosts` | integer | `25` | 1–100, overall cap across both inputs |
| `requestTimeoutSecs` | integer | `20` | 5–60 seconds per page request |

`profileUrls` must be public `https://www.linkedin.com/in/<identifier>/` pages. The actor only follows matching public `/posts/...activity-...` links present in each returned profile page. `postUrls` is optional, for exact public post pages. The two inputs can be combined in a single run: direct URLs and profile-discovered URLs are de-duplicated by activity id before anything is fetched, so the same post is never fetched — or charged — twice.

### Output

Each genuine row is verified against a matching canonical public post page before it is written or charged.

| Field | What it holds |
|---|---|
| `postUrl` | canonical public post URL |
| `activityId` | numeric LinkedIn activity id parsed from that URL |
| `sourceProfileUrl` | the profile the post was discovered from, or `null` for direct post URLs |
| `authorPublicIdentifier` | author slug taken from the canonical URL |
| `authorName` | author name as published in the page title |
| `title` | public `og:title` of the post page |
| `content` | public post body as exposed to logged-out readers |
| `imageUrl` | public post image, or `null` |
| `publishedAt` | publication timestamp, when the page exposes one |
| `transport` | `direct_http` |
| `retrievedAt` | ISO timestamp of the fetch |
| `ok`, `sourceType`, `_sample` | row-type markers, so genuine rows can be filtered in one pass |

A row is emitted only when the canonical URL matches the requested activity id **and** the page exposes public title or body text. Pages that redirect, block, rate-limit, omit public post links, or expose no matching canonical metadata return an uncharged diagnostic row carrying a machine-readable `errorCode` — `BAD_INPUT`, `BLOCKED`, `RATE_LIMITED`, `SERVER_ERROR`, `NETWORK` or `NO_RESULTS` — plus the URL that failed and a short reason. The actor does not infer missing content or author data. Reaction and comment counts are not returned: LinkedIn does not expose them to logged-out requests, so they are not promised here.

### Proxy policy

The actor uses direct HTTP only. It never starts residential or SERP proxy traffic, so there is no bandwidth surcharge sitting behind the per-post price. Public profile discovery can be blocked by LinkedIn's cloud IP controls; when that happens, supply exact public `postUrls` instead, or take the free diagnostic row. No proxy fallback is attempted.

### Empty input

Empty input returns exactly one clearly labelled `_sample: true` row without making any LinkedIn request. It is always uncharged, so you can inspect the exact output shape before spending anything.

# Actor input Schema

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

Public /in/ profile URLs. The actor reads only public post links that LinkedIn includes in that profile response.

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

Optional direct public /posts/...activity-... URLs. This does not discover or access private posts.

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

Bounded number of public post pages to fetch from each supplied public profile.

## `maxPosts` (type: `integer`):

Overall cap for direct post URLs and post links discovered from profiles.

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

Timeout for each public LinkedIn page request.

## Actor input object example

```json
{
  "profileUrls": [
    "https://www.linkedin.com/in/reidhoffman/"
  ],
  "postUrls": [
    "https://www.linkedin.com/posts/example_activity-1234567890123456789-example"
  ],
  "maxPostsPerProfile": 10,
  "maxPosts": 25,
  "requestTimeoutSecs": 20
}
```

# Actor output Schema

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

Rows are emitted only when a requested public page exposes a matching canonical post and public title or body. Samples and diagnostics are uncharged.

# 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 = {};

// Run the Actor and wait for it to finish
const run = await client.actor("dami_studio/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 = {}

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

```

## MCP server setup

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