# Linkedin Profile Details Scraper (`ahmed-khaled/linkedin-profile-details-scraper`) Actor

Scrape full LinkedIn profiles with your own session: headline, about, top skills, experience, education, certifications, skills and optional contact info. Built to protect your account: separate session, your user agent, residential IP, human pacing.

- **URL**: https://apify.com/ahmed-khaled/linkedin-profile-details-scraper.md
- **Developed by:** [Ahmed Khaled Ali](https://apify.com/ahmed-khaled) (community)
- **Categories:** Jobs, Social media
- **Stats:** 511 total users, 2 monthly users, 0.0% runs succeeded, 18 bookmarks
- **User rating**: No ratings yet

## Pricing

from $22.00 / 1,000 profile 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 Profile Details Scraper

Get full LinkedIn profiles as a logged-in member: **headline, about, top skills, complete experience, education, certifications and skills**, plus optionally the **contact info of your 1st-degree connections** (email, phone, websites, birthday). Add a list of profile URLs and download clean data as Excel, CSV or JSON, or pull it through the API.

### ⚠️ Read this first

LinkedIn watches automated browsing of profiles very closely in 2026 and **often ends the session after a few profiles**, even with all the protections below. In rare cases repeated session endings can lead LinkedIn to restrict the account.

- **Never use the cookies of the LinkedIn tab you use every day.** Give the Actor its own session (see step 1 below) so your everyday session stays separate.
- Use **small batches** (a handful of profiles per run) and keep the default pauses.
- If a run says LinkedIn ended the session, wait before trying again and create a new session for the Actor.

### What does LinkedIn Profile Details Scraper do?

It opens each profile with your LinkedIn session, reads every section, opens the full lists ("Show all experiences", "Show all skills"...) when a section has more entries, and saves one row per profile:

- 👤 **Top card**: name, headline, location, profile picture, cover image, connection degree, followers, connections
- 📝 **About** section and **top skills**
- 💼 **Experience**: every position with company, dates, location and description; several roles at one company become separate entries
- 🎓 **Education** and 📜 **licenses & certifications**, with issue dates, credential IDs and credential links
- 🛠️ **All skills**
- 📇 **Contact info** (optional) visible to your account: email, phone, websites, birthday, IM, address (usually only for your 1st-degree connections)

### How to use it

1. **Create a LinkedIn session just for the Actor.** In Chrome open `chrome://extensions`, find [Cookie-Editor](https://chromewebstore.google.com/detail/cookie-editor/hlkenndednhfkekhgcdicdfddnkalmdm) → **Details** → turn on **Allow in Incognito**. Open an **Incognito window** (Ctrl/Cmd+Shift+N), log in to LinkedIn, click **Cookie-Editor → Export → JSON** and paste the result into **LinkedIn cookies**. Then **close the Incognito window without signing out**.
2. **Copy your user agent.** In Chrome open DevTools (F12) → **Console**, type `navigator.userAgent`, press Enter and paste the text (without quotes) into **Your browser's user agent**.
3. **Set the proxy** to **RESIDENTIAL** and select **the country you normally use LinkedIn from**.
4. Add the profile URLs (`linkedin.com/in/...`) and click **Start**.

### How the Actor protects your session

| What LinkedIn checks | What the Actor does |
| --- | --- |
| Is it the same browser? | Full cookie set (not just `li_at`), **your user agent** with a matching platform, screen size and Chrome version |
| Where is it? | A **residential IP in your country**, the same IP for the whole run, and a browser clock set to that country's time zone |
| Is it a real browser? | A full (non-headless) Chrome with automation traces hidden |
| Does it behave like a person? | Reads each profile by scrolling, with natural pauses, and waits **20–50 seconds** (configurable) before the next profile |
| Sensitive actions | Contact info is **off by default**: opening that window is what LinkedIn guards most closely. Edit pages are never opened |

If LinkedIn ends the session anyway, the run stops right away, keeps the profiles already scraped and tells you.

### Input

| Field | Description |
| --- | --- |
| `urls` | Profile URLs (`linkedin.com/in/...`) |
| `cookie` | Cookie export (JSON from Cookie-Editor) of a LinkedIn session made for the Actor in an Incognito window. Stored encrypted |
| `userAgent` | Your browser's user agent (recommended) |
| `proxyConfiguration` | Proxy settings; use RESIDENTIAL in your country |
| `includeContactInfo` | Also open the Contact info window (off by default; see the FAQ) |
| `min`, `max` | Pause between profiles in seconds (default 20–50) |
| `debug` | Saves screenshots and page HTML for troubleshooting |

```json
{
  "urls": ["https://www.linkedin.com/in/jane-example/"],
  "cookie": "[{\"name\":\"li_at\",\"value\":\"...\",\"domain\":\".www.linkedin.com\"}, ...]",
  "userAgent": "Mozilla/5.0 (Macintosh; Intel Mac OS X 10_15_7) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/141.0.0.0 Safari/537.36",
  "proxyConfiguration": { "useApifyProxy": true, "apifyProxyGroups": ["RESIDENTIAL"], "apifyProxyCountry": "EG" }
}
```

### Output

One row per profile. The **Output** tab has three views: **Overview**, **Career** and **Contact info**. Example (a fictional person):

```json
{
  "profileUrl": "https://www.linkedin.com/in/jane-example/",
  "publicIdentifier": "jane-example",
  "name": "Jane Example",
  "title": "Full Stack Web Developer at Example Tech",
  "location": "Cairo, Egypt",
  "profileImgURL": "https://media.licdn.com/dms/image/...",
  "coverURL": "https://media.licdn.com/dms/image/...",
  "distance": "1st",
  "followers": 1834,
  "connections": "500+",
  "about": "A self-taught developer who moved from the medical sector to software...",
  "profileContacts": {
    "linkedinProfile": "https://www.linkedin.com/in/jane-example",
    "websites": ["https://github.com/jane-example"],
    "email": "jane@example.com",
    "birthday": "December 7"
  },
  "experience": [
    {
      "expTitle": "Full Stack Web Developer",
      "expCompName": "Example Tech · Full-time",
      "expDuration": "Jan 2021 - Present · 2 yrs 11 mos",
      "expLocation": "Remote",
      "expDescription": "Built the customer dashboard in React and Node.js...",
      "expCompURL": "https://www.linkedin.com/company/13224787/",
      "expCompLogo": "https://media.licdn.com/dms/image/..."
    }
  ],
  "education": [
    {
      "eduFrom": "Example University",
      "eduDegree": "Bachelor's degree, Veterinary Medicine",
      "eduDate": "Sep 2013 - Jan 2019",
      "eduDescription": "",
      "eduURL": "https://www.linkedin.com/school/926996/",
      "eduLogo": "https://media.licdn.com/dms/image/..."
    }
  ],
  "license": [
    {
      "licenseName": "English Proficiency Certificate",
      "compName": "Example English Test",
      "licenseDate": "Nov 2022 · Expires Nov 2024",
      "credentialID": "1336409705",
      "licenseURL": "https://certs.example.com/1336409705",
      "compURL": "https://www.linkedin.com/company/25016372/",
      "compLogo": "https://media.licdn.com/dms/image/..."
    }
  ],
  "skills": ["SQL", "Career Counseling"],
  "topSkills": ["React", "Node.js"],
  "scrapedAt": "2026-10-03T08:00:00.000Z"
}
```

### How much does it cost?

You pay a fixed price per profile saved to the dataset; see the **Pricing** tab. Proxy and compute costs are included. Profiles that are unavailable or can't be read are skipped and not charged. You can also set a **maximum cost per run** in the run options; the run stops as soon as it is reached.

### Integrations and API

Use the results in Google Sheets, Make, Zapier, n8n, Slack or any CRM through [Apify integrations](https://apify.com/integrations), or call the Actor from code:

```js
import { ApifyClient } from 'apify-client';

const client = new ApifyClient({ token: process.env.APIFY_TOKEN });
const run = await client.actor('ahmed-khaled/linkedin-profile-details-scraper').call({
    urls: ['https://www.linkedin.com/in/jane-example/'],
    cookie: process.env.LINKEDIN_COOKIES_JSON,
    userAgent: process.env.MY_USER_AGENT,
    proxyConfiguration: { useApifyProxy: true, apifyProxyGroups: ['RESIDENTIAL'], apifyProxyCountry: 'US' },
});
const { items } = await client.dataset(run.defaultDatasetId).listItems();
```

```python
import os
from apify_client import ApifyClient

client = ApifyClient(os.environ["APIFY_TOKEN"])
run = client.actor("ahmed-khaled/linkedin-profile-details-scraper").call(run_input={
    "urls": ["https://www.linkedin.com/in/jane-example/"],
    "cookie": os.environ["LINKEDIN_COOKIES_JSON"],
    "userAgent": os.environ["MY_USER_AGENT"],
    "proxyConfiguration": {"useApifyProxy": True, "apifyProxyGroups": ["RESIDENTIAL"], "apifyProxyCountry": "US"},
})
items = client.dataset(run["defaultDatasetId"]).list_items().items
```

### FAQ

**Why does it need my cookies?**
Full profiles, complete lists, skills and contact info are only visible to logged-in members. Your cookies are used only inside your own run and are stored encrypted by Apify.

**The run says LinkedIn ended the session.**
LinkedIn is very strict with automated profile browsing. Wait a while, create a new session for the Actor (Incognito login, export, close without signing out) and use smaller batches with longer pauses.

**Will the Actor log me out of LinkedIn in my browser?**
Not if you give it its own Incognito session: your browser's session is then separate. Logouts happen when the cookies of your everyday LinkedIn tab are used in the Actor at the same time as in your browser.

**Why is `profileContacts` empty?**
**Include contact info** is off by default. When on, LinkedIn still shows contact info mostly to 1st-degree connections, and only what each member chose to share.

**A field is missing or looks wrong.**
Open an issue in the **Issues** tab. Turn on **Save troubleshooting snapshots** and attach the screenshots from the run's **Debug snapshots**; it helps fix the problem fast.

### Legal

This Actor processes personal data. Make sure you have a legitimate reason to collect it, process it in line with data protection laws such as the GDPR, and respect LinkedIn's terms of service.

# Changelog

This Actor's version history is a separate document: https://apify.com/ahmed-khaled/linkedin-profile-details-scraper/changelog.md

# Actor input Schema

## `urls` (type: `array`):

Profiles to scrape, one per line (linkedin.com/in/...).

## `cookie` (type: `string`):

Cookies of a LinkedIn session made just for this Actor, so LinkedIn never sees your everyday session in two places at once. How to get them: 1) in Chrome open chrome://extensions → <a href='https://chromewebstore.google.com/detail/cookie-editor/hlkenndednhfkekhgcdicdfddnkalmdm' target='_blank'>Cookie-Editor</a> → Details → turn on 'Allow in Incognito', 2) open an Incognito window (Ctrl/Cmd+Shift+N) and log in to LinkedIn, 3) click Cookie-Editor → Export → JSON and paste it here, 4) close the Incognito window without signing out. Stored encrypted.

## `userAgent` (type: `string`):

The user agent of the Chrome or Edge browser you exported the cookies from. To get it, open DevTools (F12) → Console, type navigator.userAgent and press Enter, then copy the text without quotes. Strongly recommended.

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

Use RESIDENTIAL proxies and select the country you normally use LinkedIn from. A datacenter IP or a far-away country makes LinkedIn suspicious and can log you out. The same IP is kept for the whole run.

## `includeContactInfo` (type: `boolean`):

Also opens each profile's Contact info window (email, phone, websites, birthday — usually only for your 1st-degree connections). LinkedIn watches this window closely and may end the session, so use it only for small batches of your own connections.

## `min` (type: `integer`):

Shortest pause before opening the next profile. Longer pauses look more natural to LinkedIn.

## `max` (type: `integer`):

Longest pause before opening the next profile. The Actor picks a random pause between the minimum and the maximum.

## `debug` (type: `boolean`):

Saves a screenshot and the page HTML for each URL in the run's storage (Debug snapshots). Turn on only when asked to in a support issue.

## Actor input object example

```json
{
  "urls": [
    "https://www.linkedin.com/in/ahmed-khaled-dev/",
    "https://www.linkedin.com/in/williamhgates/"
  ],
  "proxyConfiguration": {
    "useApifyProxy": true,
    "apifyProxyGroups": [
      "RESIDENTIAL"
    ]
  },
  "includeContactInfo": false,
  "min": 20,
  "max": 50,
  "debug": false
}
```

# Actor output Schema

## `profiles` (type: `string`):

No description

## `career` (type: `string`):

No description

## `contacts` (type: `string`):

No description

## `debugSnapshots` (type: `string`):

No description

# 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 = {
    "urls": [
        "https://www.linkedin.com/in/ahmed-khaled-dev/"
    ],
    "proxyConfiguration": {
        "useApifyProxy": true,
        "apifyProxyGroups": [
            "RESIDENTIAL"
        ]
    }
};

// Run the Actor and wait for it to finish
const run = await client.actor("ahmed-khaled/linkedin-profile-details-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 = {
    "urls": ["https://www.linkedin.com/in/ahmed-khaled-dev/"],
    "proxyConfiguration": {
        "useApifyProxy": True,
        "apifyProxyGroups": ["RESIDENTIAL"],
    },
}

# Run the Actor and wait for it to finish
run = client.actor("ahmed-khaled/linkedin-profile-details-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 '{
  "urls": [
    "https://www.linkedin.com/in/ahmed-khaled-dev/"
  ],
  "proxyConfiguration": {
    "useApifyProxy": true,
    "apifyProxyGroups": [
      "RESIDENTIAL"
    ]
  }
}' |
apify call ahmed-khaled/linkedin-profile-details-scraper --silent --output-dataset

```

## MCP server setup

```json
{
    "mcpServers": {
        "apify": {
            "type": "http",
            "url": "https://mcp.apify.com/?tools=fetch-actor-details,ahmed-khaled/linkedin-profile-details-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/KYzSqU1FJUomdKfHD/builds/cCRbUbKqnVbHRaCq6/openapi.json
