# LinkedIn Profile Reactions Scraper (No Cookies) (`data-slayer/linkedin-profile-reactions`) Actor

Extract posts reacted to by public LinkedIn profiles, including action labels, post text, authors, timestamps, engagement counts, reaction breakdowns, attachments, and shared-post context. Batch up to 1,000 profiles and export JSON, CSV, or Excel—no LinkedIn cookies or login required.

- **URL**: https://apify.com/data-slayer/linkedin-profile-reactions.md
- **Developed by:** [Data Slayer](https://apify.com/data-slayer) (community)
- **Categories:** Social media, Lead generation, Automation
- **Stats:** 2 total users, 1 monthly users, 100.0% runs succeeded, 0 bookmarks
- **User rating**: No ratings yet

## Pricing

$2.00 / 1,000 profile reaction results

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 Reactions Scraper (No Cookies)

Extract structured records of posts that public LinkedIn profiles reacted to—including action labels, post content, authors, engagement counts, reaction breakdowns, and attachments—without providing LinkedIn cookies or login credentials.

### Watch the demo

YouTube video coming soon.

### What this LinkedIn profile reactions scraper does

Give the Actor one or more public LinkedIn profile URLs. It returns the posts those profiles reacted to, together with the public action label, reacted-post text, publication time, author details, engagement counts, aggregate reaction breakdown, attachments, mentions, and shared-post context when available.

The output is designed for both analysis and automation:

- Batch up to 1,000 LinkedIn profile URLs in one run.
- Limit results per profile or use `0` to continue through the available pages, with a 100-page safety cap.
- Filter reacted-to posts by publication age: 24 hours, 7 days, 30 days, 3 months, 6 months, or 1 year.
- Export structured JSON, CSV, Excel, XML, or HTML through Apify datasets.
- Use stable input order, automatic pagination, duplicate removal, and per-profile run status.
- Connect runs to the Apify API, schedules, webhooks, Make, Zapier, Google Sheets, or an MCP client.

### Common use cases

- **Sales research:** understand which public posts a prospect or buyer reacts to before outreach.
- **Account intelligence:** track themes and authors receiving engagement from selected profiles.
- **Creator and influencer research:** analyze the content and people that attract reactions from industry voices.
- **Content research:** compare reacted-post topics, formats, authors, and engagement levels.
- **Market and audience analysis:** build structured datasets from public profile activity for dashboards or research workflows.
- **Automation:** send new reaction records to a CRM, warehouse, spreadsheet, webhook, or AI workflow.

### Input

Open the **Input** tab, paste public LinkedIn profile URLs, choose a per-profile limit and optional post-age filter, then click **Start**.

| Field | Type | Required | Default | Description |
|---|---|---:|---:|---|
| `profile_urls` | Array of strings | Yes | Satya Nadella example | Between 1 and 1,000 public `linkedin.com/in/...` profile URLs. |
| `max_reactions_per_profile` | Integer | No | `100` | Save between 0 and 1,000 unique records per profile. `0` continues until pagination ends or the 100-page cap is reached. |
| `posted_within` | String | No | `any` | Keep posts published within `24h`, `week`, `month`, `3months`, `6months`, `year`, or use `any`. |

Example:

```json
{
  "profile_urls": [
    "https://www.linkedin.com/in/satyanadella"
  ],
  "max_reactions_per_profile": 100,
  "posted_within": "any"
}
```

#### Accepted profile URLs

Use full public profile URLs such as:

```text
https://www.linkedin.com/in/satyanadella
https://in.linkedin.com/in/satyanadella/
```

Regional LinkedIn hosts are accepted. The Actor normalizes accepted URLs to `https://www.linkedin.com/in/...`, removes tracking parameters, fragments, and trailing slashes, and removes duplicates while keeping the first-seen input order.

Company pages, post URLs, search pages, Sales Navigator links, bare profile slugs, and bare URNs are rejected before any extraction request. If one URL in the submitted input is malformed, the run stops before processing and identifies the failing input position.

For migration from an existing workflow, the hidden aliases `profiles`, `profileUrls`, `linkedin_profile_url`, `maxItems`, and `postedLimit` are accepted. New integrations should use the canonical fields shown above. Conflicting canonical and alias values are rejected.

### Output

Each dataset item represents one unique reacted-to post for one input profile. Records keep normalized input-profile order and then source page/item order. The Actor does not re-sort records by time.

The default **Profile reactions** view exposes the full record. The compact **Profile activity** view keeps the reacting profile, action, post, author, and engagement context most useful for spreadsheet and CRM exports.

#### Output fields

| Field | Type | Meaning |
|---|---|---|
| `reaction_id` | String | Deterministic SHA-256 identity for the reacting profile and reacted-to post. |
| `reacting_profile_url` | URL | Canonical input profile URL. |
| `reacting_profile_identifier` | String | Public identifier from the `/in/...` path. |
| `reacting_profile_name` | String or null | Display name parsed from a recognized public action label. |
| `reaction_action` | String or null | Public label such as `Satya Nadella likes this`. |
| `reaction_target` | String or null | Content type receiving the reaction, such as `Post`. |
| `post_id` | String or null | Precision-safe numeric post ID. |
| `post_urn` | String or null | Supplied or unambiguously derived post URN. |
| `post_url` | URL or null | Canonical reacted-to post URL without tracking parameters. |
| `post_text` | String or null | Reacted-to post text. |
| `post_created_at` | Date-time or null | Reacted-to post publication time in UTC. This is not a reaction timestamp. |
| `post_created_at_timestamp` | Integer or null | Unix milliseconds for `post_created_at`. |
| `post_relative_age` | String or null | Source display label such as `1d`; not an exact sortable timestamp. |
| `post_is_repost` | Boolean or null | Whether the reacted-to post is marked as a repost. |
| `post_is_edited` | Boolean or null | Whether the reacted-to post is marked as edited. |
| `total_reaction_count` | Integer or null | Aggregate post reactions reported at fetch time. |
| `post_comment_count` | Integer or null | Aggregate comment count. |
| `post_share_count` | Integer or null | Aggregate share count. |
| `like_reaction_count` | Integer or null | Aggregate Like count. |
| `praise_reaction_count` | Integer or null | Aggregate Praise count. |
| `empathy_reaction_count` | Integer or null | Aggregate Empathy count. |
| `appreciation_reaction_count` | Integer or null | Aggregate Appreciation count. |
| `interest_reaction_count` | Integer or null | Aggregate Interest count. |
| `entertainment_reaction_count` | Integer or null | Aggregate Entertainment count. |
| `other_reaction_count` | Integer or null | Other supplied categories or the gap between the total and named counts. |
| `reaction_breakdown` | Array | Ordered aggregate post reaction counts as `{reaction_type, count}` objects. |
| `post_author_id` | String or null | Supplied post-author URN or ID. |
| `post_author_identifier` | String or null | Public post-author identifier. |
| `post_author_type` | String | `profile`, `company`, or `unknown`. |
| `post_author_name` | String or null | Post-author display name. |
| `post_author_headline` | String or null | Public headline or occupation. |
| `post_author_linkedin_url` | URL or null | Canonical post-author LinkedIn URL. |
| `post_author_image_url` | URL or null | Current source-hosted author image URL; it can expire. |
| `attachments` | Array | Attachment objects with the source fields retained. |
| `mentions` | Array | Mention objects with the source fields retained. |
| `shared_post` | Object or null | Shared-post context when supplied. |
| `input_index` | Integer | Zero-based normalized input-profile position. |
| `reaction_index` | Integer | Zero-based per-profile order after filtering and duplicate removal. |
| `fetched_at` | Date-time | UTC timestamp shared by rows from the same profile operation. |

#### Important reaction semantics

`reaction_action` is the public action label available for the queried profile. `reaction_breakdown` and the named reaction-count columns describe aggregate engagement on the reacted-to post. They do not identify the queried profile's exact machine-readable reaction subtype.

Likewise, `post_created_at` is the post's publication timestamp—not the time the profile reacted. The Actor does not invent an unavailable reaction timestamp or feed-activity ID.

#### Example dataset item

```json
{
  "reaction_id": "9b2f49c47228405419cebf6120a9f10613a0279cfd71e664bc4201a56fae441b",
  "reacting_profile_url": "https://www.linkedin.com/in/satyanadella",
  "reacting_profile_identifier": "satyanadella",
  "reacting_profile_name": "Satya Nadella",
  "reaction_action": "Satya Nadella likes this",
  "reaction_target": "Post",
  "post_id": "7481741318122110976",
  "post_urn": "urn:li:ugcPost:7481741318122110976",
  "post_url": "https://www.linkedin.com/posts/bradsmi_a250-ugcPost-7481741318122110976-ImDL",
  "post_text": "To coincide with the #A250, Microsoft unveiled an AI experience...",
  "post_created_at": "2026-07-12T00:13:45.784Z",
  "post_created_at_timestamp": 1783815225784,
  "post_relative_age": "1d",
  "post_is_repost": false,
  "post_is_edited": false,
  "total_reaction_count": 960,
  "post_comment_count": 84,
  "post_share_count": 90,
  "like_reaction_count": 795,
  "praise_reaction_count": 41,
  "empathy_reaction_count": 87,
  "appreciation_reaction_count": 10,
  "interest_reaction_count": 26,
  "entertainment_reaction_count": 0,
  "other_reaction_count": 1,
  "reaction_breakdown": [
    {"reaction_type": "LIKE", "count": 795},
    {"reaction_type": "APPRECIATION", "count": 10},
    {"reaction_type": "EMPATHY", "count": 87},
    {"reaction_type": "INTEREST", "count": 26},
    {"reaction_type": "PRAISE", "count": 41}
  ],
  "post_author_id": null,
  "post_author_identifier": "bradsmi",
  "post_author_type": "profile",
  "post_author_name": "Brad Smith",
  "post_author_headline": "Vice Chair and President at Microsoft Corporation",
  "post_author_linkedin_url": "https://www.linkedin.com/in/bradsmi",
  "post_author_image_url": "https://media.licdn.com/dms/image/example",
  "attachments": [],
  "mentions": [],
  "shared_post": null,
  "input_index": 0,
  "reaction_index": 0,
  "fetched_at": "2026-07-13T00:00:00.000Z"
}
```

Post engagement values are a snapshot and can change between runs. If the reported total exceeds the sum of the six named reaction columns, the nonnegative gap appears in `other_reaction_count`. Unknown categories remain visible in `reaction_breakdown`.

For CSV and spreadsheet exports, scalar fields remain columns. `reaction_breakdown`, `attachments`, `mentions`, and `shared_post` are compact JSON cells. Unavailable scalar values export as empty cells, while IDs stay strings to prevent precision loss.

### Filtering, limits, and pagination

- Pagination is automatic; cursors are not exposed in the input form.
- `max_reactions_per_profile` is applied after the post-age filter and duplicate removal.
- `0` continues through the available result pages, subject to 100 pages per profile.
- A bounded `posted_within` filter uses the reacted-to post's UTC publication timestamp and includes the exact cutoff.
- A missing or invalid publication time is excluded from bounded windows and retained when `posted_within` is `any`.
- First occurrence wins when the same reacted-to post appears more than once for a profile.
- A repeated cursor stops safely instead of looping.

### Run status and partial results

Only reaction records are written to the dataset; errors are never mixed in as dataset rows. The default key-value store contains `RUN_SUMMARY` with overall and per-profile counts and status.

```json
{
  "status": "succeeded",
  "profile_count": 1,
  "saved_reaction_count": 99,
  "provider_page_count": 1,
  "started_at": "2026-07-28T10:00:00Z",
  "finished_at": "2026-07-28T10:00:06Z",
  "profiles": [
    {
      "profile_url": "https://www.linkedin.com/in/satyanadella",
      "input_index": 0,
      "status": "succeeded",
      "saved_reaction_count": 99,
      "provider_page_count": 1,
      "duplicate_count": 1,
      "filtered_out_count": 0,
      "error_code": null,
      "error_message": null
    }
  ]
}
```

Possible statuses are `succeeded`, `no_results`, `partial`, `failed`, and `capped`.

- A valid profile with no matching items produces an empty dataset and `no_results`.
- If some profiles or later pages fail, recovered records remain available and the summary becomes `partial`.
- If every profile fails, the summary is written before the Actor run fails.
- Reaching the 100-page safety cap is reported as `capped`.

### Use through the Apify API

Start a run with the Actor slug:

```bash
curl -X POST \
  "https://api.apify.com/v2/acts/data-slayer~linkedin-profile-reactions/runs?token=YOUR_APIFY_TOKEN" \
  -H "Content-Type: application/json" \
  -d '{
    "profile_urls": ["https://www.linkedin.com/in/satyanadella"],
    "max_reactions_per_profile": 100,
    "posted_within": "month"
  }'
```

After the run finishes, fetch dataset items using the run's `defaultDatasetId`, or read the `results` and `run_summary` links from the Actor output.

### Automation and integrations

This Actor works with standard Apify platform features:

- **Schedules:** run profile research daily, weekly, or on a custom cadence.
- **Webhooks:** trigger another system when a run succeeds or fails.
- **API clients:** call the Actor from Python, JavaScript, or any HTTP client.
- **Make and Zapier:** route records into CRMs, spreadsheets, alerts, or enrichment workflows.
- **Google Sheets and Excel:** export flat columns with nested context retained as JSON cells.
- **MCP:** expose the Actor as a structured tool to compatible AI agents.

### Frequently asked questions

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

No. The input contains public LinkedIn profile URLs; you do not provide LinkedIn session cookies or account credentials.

#### Does this return the people who reacted to a profile's posts?

No. This Actor starts from a person's profile and returns posts that profile reacted to. A post-reactions Actor answers the different question of who reacted to one specific post.

#### Does `reaction_breakdown` show the profile's own reaction type?

No. It is the aggregate breakdown for the reacted-to post. Use `reaction_action` for the public action label supplied for the queried profile.

#### Can I filter by when the reaction happened?

No reaction timestamp is available. `posted_within` filters on when the reacted-to post was published.

#### Why can engagement counts differ between runs?

Comments, shares, and reactions can continue changing after publication. Each record captures the values reported when that profile operation was fetched.

#### Why are some values null?

Public records do not always expose every identifier, author value, timestamp, or media field. Null means the value was unavailable or could not be parsed safely; the Actor does not fill gaps with guesses.

#### Can profile-image or attachment links expire?

Yes. LinkedIn-hosted media URLs can be temporary. Store or download permitted assets promptly if your workflow needs them later.

#### How are large batches handled?

Up to five profiles are processed concurrently in bounded windows. Results are still pushed in normalized input order. Pages for one profile are processed serially.

### Responsible use

Use the Actor only for legitimate purposes and handle personal data appropriately. You are responsible for complying with applicable laws, platform terms, and your organization's data-retention and security requirements. The Actor is an independent tool and is not affiliated with or endorsed by LinkedIn.

### Support

If a public profile produces an unexpected result, open an issue from the Actor's **Issues** tab and include the run ID, sanitized input, expected behavior, and observed behavior. Do not post account credentials, session cookies, API tokens, or private data.

# Actor input Schema

## `profile_urls` (type: `array`):

Required. Add 1–1,000 public LinkedIn profile URLs in linkedin.com/in/… format. Regional LinkedIn hosts are accepted. Tracking parameters, fragments, and trailing slashes are removed.

## `max_reactions_per_profile` (type: `integer`):

Maximum number of unique reaction records to save for each profile. Enter 0 to fetch all available reactions, with a 100-page safety cap per profile.

## `posted_within` (type: `string`):

Only save reactions to posts published within this time window. Choose Any time to keep all available reactions.

## Actor input object example

```json
{
  "profile_urls": [
    "https://www.linkedin.com/in/satyanadella"
  ],
  "max_reactions_per_profile": 100,
  "posted_within": "any"
}
```

# Actor output Schema

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

One dataset item per unique reacted-to post, in input-profile and source order.

## `dataset_table` (type: `string`):

The default human-readable dataset view.

## `run_summary` (type: `string`):

Per-profile completion, page, count, and sanitized error details.

# 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 = {
    "profile_urls": [
        "https://www.linkedin.com/in/satyanadella"
    ],
    "max_reactions_per_profile": 100,
    "posted_within": "any"
};

// Run the Actor and wait for it to finish
const run = await client.actor("data-slayer/linkedin-profile-reactions").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 = {
    "profile_urls": ["https://www.linkedin.com/in/satyanadella"],
    "max_reactions_per_profile": 100,
    "posted_within": "any",
}

# Run the Actor and wait for it to finish
run = client.actor("data-slayer/linkedin-profile-reactions").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 '{
  "profile_urls": [
    "https://www.linkedin.com/in/satyanadella"
  ],
  "max_reactions_per_profile": 100,
  "posted_within": "any"
}' |
apify call data-slayer/linkedin-profile-reactions --silent --output-dataset

```

## MCP server setup

```json
{
    "mcpServers": {
        "apify": {
            "type": "http",
            "url": "https://mcp.apify.com/?tools=fetch-actor-details,data-slayer/linkedin-profile-reactions"
        }
    }
}

```

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/lUd4tf5YgGDINvQGj/builds/x1FFv8aqu9HfOkJe4/openapi.json
