# LinkedIn Batch Profile Posts Scraper (`khadinakbar/linkedin-batch-profile-posts-scraper`) Actor

Scrape recent public LinkedIn posts from a batch of person profiles. Use for ABM monitoring, thought-leader cadence, and competitor content research. Returns one row per post with text, URL, date, hashtags, mentions, and cadence. Charged $0.006 per post.

- **URL**: https://apify.com/khadinakbar/linkedin-batch-profile-posts-scraper.md
- **Developed by:** [Khadin Akbar](https://apify.com/khadinakbar) (community)
- **Categories:** Social media, Lead generation, MCP servers
- **Stats:** 1 total users, 0 monthly users, 0.0% runs succeeded, 0 bookmarks
- **User rating**: No ratings yet

## Pricing

from $6.00 / 1,000 linkedin post scrapeds

This Actor is paid per event and usage. You are charged both the fixed price for specific events and for Apify platform usage.

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 Batch Profile Posts Scraper

Turn a list of LinkedIn person profiles into one dataset of recent public posts. Paste profile URLs or vanity handles and get post text, permalink, published date, hashtags, mentions, and posting-cadence stats for every visible item in the public activity preview. No LinkedIn login or cookies.

This Actor is built for ABM and content teams that monitor many people in one run. Providers return the recent public preview (typically a handful of posts per profile), which is enough for cadence, topic, and signal monitoring.

### Best fit for this Actor

- Watch a named ABM list for job-change, launch, and fundraising posts.
- Compare thought-leader posting cadence and hashtag mix across a watchlist.
- Feed a content radar with public executive posts before a weekly briefing.

For a single profile with optional post-detail enrichment, use [LinkedIn Profile Posts Scraper](https://apify.com/khadinakbar/linkedin-profile-posts-scraper). For company pages use [LinkedIn Company Posts Scraper](https://apify.com/khadinakbar/linkedin-company-posts-scraper). For keyword search use [LinkedIn Posts Scraper](https://apify.com/khadinakbar/linkedin-posts-scraper).

### Practical scenario

A content strategist pastes `satyanadella` and `parrsam`, sets `maxPostsPerProfile` to 3, and leaves `postedLimit` at `any`. The run returns one row per recent public post: text, LinkedIn permalink, ISO date, extracted hashtags, and `cadencePostsPerWeek` for that profile. A missing handle finishes `SUCCEEDED` with `VALID_EMPTY` and no `post-scraped` charge.

### Quick start input

```json
{
  "profileUrls": [
    "https://www.linkedin.com/in/satyanadella/",
    "https://www.linkedin.com/in/parrsam/"
  ],
  "maxPostsPerProfile": 3,
  "postedLimit": "any",
  "includeReposts": true,
  "authoredOnly": false,
  "maxConcurrency": 3
}
```

`profileUrls` accepts `/in/` URLs or bare vanity handles. Duplicate URLs are collapsed before any provider call.

### Input reference

| Field | Type | What it controls |
|---|---|---|
| `profileUrls` | array (required) | Person profile URLs or handles. Example: `https://www.linkedin.com/in/satyanadella/`. Max 200 unique values. Company and post URLs are rejected. |
| `maxPostsPerProfile` | integer | Cap billed rows per profile. Default 10, max 50. |
| `maxConcurrency` | integer | Profiles fetched in parallel. Default 3, max 8. |
| `postedLimit` | enum | Keep posts inside `any`, `24h`, `week`, `month`, `3months`, `6months`, or `year`. Default `any`. |
| `includeReposts` | boolean | Keep reshared posts. Default true. |
| `authoredOnly` | boolean | Keep original posts only. Default false. |
| `providerOrder` | enum | `scrapecreators-first` (default) or `sociavault-first`. |

### What data you receive

One dataset item is one public post.

```json
{
  "profileInput": "https://www.linkedin.com/in/parrsam/",
  "profileUrl": "https://www.linkedin.com/in/parrsam/",
  "profileHandle": "parrsam",
  "authorName": "Sam Parr",
  "postUrl": "https://www.linkedin.com/posts/parrsam_a-chocolate-bar-company-came-on-my-first-activity-7496234896357568513-lOe7",
  "postId": "7496234896357568513",
  "activityKind": "posted",
  "isRepost": false,
  "isAuthored": true,
  "publishedAt": "2026-08-20T16:01:12.559Z",
  "text": "A chocolate bar company came on My First Million and walked through its revenue...",
  "hashtags": [],
  "mentions": [],
  "cadencePostsInWindow": 3,
  "cadenceDaysSinceLastPost": 1,
  "cadencePostsPerWeek": 4.2,
  "provider": "scrapecreators",
  "scrapedAt": "2026-08-21T12:00:00.000Z"
}
```

| Field | Meaning |
|---|---|
| `text` + `postUrl` | Public post body and permalink |
| `publishedAt` | ISO 8601 date from the provider, or from the activity ID when needed |
| `hashtags` / `mentions` | Tags parsed from the post text |
| `cadencePostsPerWeek` | Matching posts for that profile, expressed per week |
| `activityKind` | `posted`, `repost`, `liked`, `commented`, or `reacted` |

`OUTPUT` and `RUN_SUMMARY` in the default key-value store hold `outcome`, `itemsPushed`, and `chargedEventCounts`.

### Use through the API

```bash
curl -X POST "https://api.apify.com/v2/acts/khadinakbar~linkedin-batch-profile-posts-scraper/runs" \
  -H "Authorization: Bearer $APIFY_TOKEN" \
  -H "Content-Type: application/json" \
  -d '{"profileUrls":["https://www.linkedin.com/in/satyanadella/","https://www.linkedin.com/in/parrsam/"],"maxPostsPerProfile":3}'
```

Download rows as JSON, CSV, Excel, or HTML from the Dataset tab.

### Use with AI agents through Apify MCP

> Scrape the last 3 public LinkedIn posts from satyanadella and parrsam. Return authorName, postUrl, publishedAt, text, hashtags, and cadencePostsPerWeek.

Connect via <https://mcp.apify.com>. Read `OUTPUT.outcome` and `itemsPushed` to interpret empty datasets.

### Connect the workflow

- After you have post URLs, extract commenters with [LinkedIn Post Engagers Scraper](https://apify.com/khadinakbar/linkedin-post-engagers-scraper).
- For person identity without posts, use [LinkedIn Profile Details Scraper](https://apify.com/khadinakbar/linkedin-profile-details-scraper).

### Pricing

Pay per event plus platform usage. Confirm current event prices on the live Pricing tab; that tab is the source of truth if this page ever lags.

- `apify-actor-start`: $0.00005 per run
- `post-scraped`: **$0.006** per saved post row

A two-profile, three-post run is about $0.036 in result events plus a few seconds of Apify platform usage. Missing profiles and empty windows have no `post-scraped` charge. Provider credits are paid by the Actor owner.

### How it works

1. Normalize and deduplicate profile URLs and handles.
2. Fetch each public profile concurrently from ScrapeCreators, then SociaVault on failure.
3. Keep posts that match `postedLimit`, `includeReposts`, and `authoredOnly`.
4. Attach hashtags, mentions, and per-profile cadence, charge `post-scraped`, then write the row.

### Best results

- Pass person `/in/` URLs or vanity handles, not company pages or post URLs.
- Keep `maxPostsPerProfile` near 10. The public preview rarely returns a full archive.
- Use `postedLimit` when you only want last-week or last-month activity.
- A typo handle finishes `SUCCEEDED` with `VALID_EMPTY` and no post charge.

### Builder's note

I found that both public-data providers return a short `recentPosts` preview with `link`, `id`, `title`, `datePublished`, and `activityType` on live person profiles. In my testing that preview is enough for cadence and tags, and SociaVault wraps the same posts in a numeric-key object, so the runtime treats objects and arrays the same. The product stays a batch monitor of the public preview.

### Legal and responsible use

Use this Actor on public LinkedIn data you are authorized to process, follow applicable law and LinkedIn's terms, and keep the output in your own compliance workflow. This Actor is independent of LinkedIn and Microsoft.

Issues and feature requests: use the Actor Issues tab on Apify.

# Actor input Schema

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

Public LinkedIn person profiles to scrape in this batch, one per line. Accepts full /in/ URLs such as https://www.linkedin.com/in/satyanadella/ or a bare vanity handle such as satyanadella. Up to 200 unique profiles per run. Company pages, search queries, and post URLs are rejected — use linkedin-company-posts-scraper or linkedin-posts-scraper for those.

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

Cap on billed post rows saved for each profile. Accepts 1 to 50, for example 10. Default is 10. Providers expose only the recent public activity preview, so values above about 10 often return the same handful of posts rather than a full archive.

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

How many profiles to fetch in parallel. Accepts 1 to 8, for example 3. Default is 3. Raise for large ABM lists; lower to 1 if a provider rate-limits the run.

## `postedLimit` (type: `string`):

Keep only posts whose published date falls inside this window, counted from now. Accepts any, 24h, week, month, 3months, 6months, or year. Default is any. Posts without a usable date are dropped when a window other than any is set.

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

Whether to keep posts the person reshared from others. Accepts true or false. Default is true. Set false to keep original posts only. Ignored when Authored posts only is enabled.

## `authoredOnly` (type: `boolean`):

When enabled, keep only posts the person originally authored and drop likes, comments, reactions, and reshares from their public activity preview. Accepts true or false. Default is false.

## `providerOrder` (type: `string`):

Which managed public-data provider to try first, with automatic fallback to the other. Accepts scrapecreators-first, sociavault-first, scrapecreators-only, or sociavault-only. Default is scrapecreators-first. Use an only mode only when you need to pin one vendor for a test.

## Actor input object example

```json
{
  "profileUrls": [
    "https://www.linkedin.com/in/satyanadella/",
    "https://www.linkedin.com/in/parrsam/"
  ],
  "maxPostsPerProfile": 3,
  "maxConcurrency": 3,
  "postedLimit": "any",
  "includeReposts": true,
  "authoredOnly": false,
  "providerOrder": "scrapecreators-first"
}
```

# Actor output Schema

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

Dataset items containing post URL, text, published date, hashtags, mentions, cadence stats, author identity, and provider provenance.

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

OUTPUT record with outcome, itemsPushed, chargedEventCounts, cadence notes, and provider diagnostics.

## `runSummary` (type: `string`):

Machine-readable RUN\_SUMMARY record mirroring OUTPUT for integrations that read RUN\_SUMMARY directly.

# 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/satyanadella/",
        "https://www.linkedin.com/in/parrsam/"
    ],
    "maxPostsPerProfile": 3,
    "maxConcurrency": 3
};

// Run the Actor and wait for it to finish
const run = await client.actor("khadinakbar/linkedin-batch-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 = {
    "profileUrls": [
        "https://www.linkedin.com/in/satyanadella/",
        "https://www.linkedin.com/in/parrsam/",
    ],
    "maxPostsPerProfile": 3,
    "maxConcurrency": 3,
}

# Run the Actor and wait for it to finish
run = client.actor("khadinakbar/linkedin-batch-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 '{
  "profileUrls": [
    "https://www.linkedin.com/in/satyanadella/",
    "https://www.linkedin.com/in/parrsam/"
  ],
  "maxPostsPerProfile": 3,
  "maxConcurrency": 3
}' |
apify call khadinakbar/linkedin-batch-profile-posts-scraper --silent --output-dataset

```

## MCP server setup

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