# LinkedIn Profile Scraper (`calm_builder/linkedin-profile-scraper`) Actor

Scrape public LinkedIn profiles by URL or username, no login or cookies. Get full work history with job titles, education, complete skills, certifications, languages, projects and honors as JSON, plus optional recent posts with comments. Only retrieved profiles are charged.

- **URL**: https://apify.com/calm_builder/linkedin-profile-scraper.md
- **Developed by:** [Coder](https://apify.com/calm_builder) (community)
- **Categories:** Lead generation, Social media, Developer tools
- **Features:** Limited permissions
- **Stats:** 221 total users, 60 monthly users, 100.0% runs succeeded, 1 bookmarks
- **User rating**: 5.00 out of 5 stars

## Pricing

from $1.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 Scraper

Scrape public [LinkedIn](https://www.linkedin.com) profiles from a list of profile URLs or usernames, **without a LinkedIn account, login or cookies**. For each profile you get the full work history (job titles, companies, dates, descriptions), education, **the complete skills list**, certifications, languages, projects, volunteering, honors, publications, patents and more, as clean JSON.

Use it for **recruiting and sourcing**, **lead enrichment**, **sales intelligence**, **investor and expert research**, and **talent mapping**.

***

### Why this LinkedIn scraper

- **No account needed.** It never signs in, so there is no risk to your LinkedIn account and no cookies to paste in.
- **Full experience entries.** Every job has its title, company, company page link, employment type, dates, duration, location, workplace type (on-site, hybrid or remote) and full description. Several roles at one company come back as separate entries.
- **The complete skills list.** It returns every skill on the profile (50+ on many profiles), not just the first 20.
- **Every profile section.** Education with degree and field of study, certifications with issuer and date, languages with proficiency, projects, volunteering, honors and awards, publications, patents, courses, organizations and causes.
- **Results as they arrive.** Each profile is saved the moment it is ready, so you can watch the dataset fill while the run goes on.
- **You pay only for delivered profiles.** Profiles that cannot be retrieved are reported in the run log and not written to the dataset.

***

### Quick start

1. Open the Actor in Apify Console.
2. Under **LinkedIn profiles**, add profile URLs or usernames, one per line.
3. Click **Start**, then open the **Output** tab and watch profiles appear.

Accepted formats:

- Username: `satyanadella`
- Profile URL: `https://www.linkedin.com/in/williamhgates`
- Country URL: `https://pk.linkedin.com/in/username`, `https://uk.linkedin.com/in/username`

```json
{
  "profiles": [
    "reidhoffman",
    "https://www.linkedin.com/in/williamhgates",
    "https://in.linkedin.com/in/username"
  ]
}
```

Duplicates are scraped once. Entries that are not LinkedIn profiles are skipped and named in the run log.

***

### What you get

One dataset row per profile:

| Field                                                         | What it contains                                                                                                                                                                 |
| ------------------------------------------------------------- | -------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- |
| `fullName`, `headline`, `location`, `country`                 | Identity                                                                                                                                                                         |
| `about`                                                       | About text as LinkedIn shows it to visitors who are not logged in (usually the first ~90 characters)                                                                             |
| `followers`, `followersText`, `connections`                   | Audience size                                                                                                                                                                    |
| `profilePictureUrl`, `backgroundImageUrl`                     | Images                                                                                                                                                                           |
| `currentCompany`, `currentSchool`                             | Name and LinkedIn page link                                                                                                                                                      |
| `experience`                                                  | Every job: `title`, `company`, `companyUrl`, `employmentType`, `dateRange`, `startDate`, `endDate`, `current`, `duration`, `location`, `workplaceType`, `description`, `logoUrl` |
| `education`                                                   | `school`, `schoolUrl`, `degree`, `fieldOfStudy`, dates, `grade`, `activities`, `description`, `logoUrl`                                                                          |
| `skills`                                                      | Every skill name                                                                                                                                                                 |
| `certifications`                                              | `name`, `issuer`, `issuedDate`, `expirationDate`, `credentialId`                                                                                                                 |
| `languages` / `languageDetails`                               | Language names / names with `proficiency`                                                                                                                                        |
| `projects`                                                    | `name`, dates, `description`, `contributors`                                                                                                                                     |
| `volunteering`                                                | `role`, `organization`, `organizationUrl`, dates, `cause`, `description`                                                                                                         |
| `honors` / `awards`                                           | Honors with `issuer`, `date`, `description` / award titles                                                                                                                       |
| `publications`                                                | `title`, `publisher`, `date`, `description`                                                                                                                                      |
| `patents`, `courses`, `testScores`, `organizations`, `causes` | When listed on the profile                                                                                                                                                       |
| `posts`, `articles`                                           | Recent public activity and LinkedIn articles                                                                                                                                     |
| `recentPosts`, `recentPostCount`                              | Optional (**Include recent posts**): the person's own recent posts with text, exact date, reactions, comment count, media and optional top comments                             |
| `websites`                                                    | Links listed on the profile                                                                                                                                                      |
| `linkedinUrl`, `publicIdentifier`                             | Profile link and username, a stable key across runs                                                                                                                              |

Sections a person has not filled in are left out of that row rather than saved empty.

#### Example (real run, shortened)

```json
{
  "linkedinUrl": "https://www.linkedin.com/in/reidhoffman",
  "publicIdentifier": "reidhoffman",
  "fullName": "Reid Hoffman",
  "location": "United States",
  "connections": "500+ connections",
  "experience": [
    {
      "title": "Co-Founder, Executive Board Chair",
      "company": "Manas AI",
      "companyUrl": "https://www.linkedin.com/company/106067845/",
      "dateRange": "Jan 2025 - Present",
      "startDate": "Jan 2025",
      "current": true,
      "duration": "1 yr 9 mos",
      "description": "Manas AI leverages proprietary AI, generative computational chemistry..."
    }
  ],
  "education": [
    {
      "school": "Babson College",
      "schoolUrl": "https://www.linkedin.com/school/6716/",
      "degree": "Honorary Doctor of Laws",
      "fieldOfStudy": "Entrepreneurship/Entrepreneurial Studies",
      "dateRange": "2012 - 2012"
    }
  ],
  "skills": [
    "CEOs",
    "Founding",
    "Early-Stage Startups",
    "Start-ups",
    "Entrepreneurship",
    "Strategy"
  ],
  "volunteering": [
    {
      "role": "Chair, Board of Directors",
      "organization": "Opportunity@Work",
      "dateRange": "Jun 2016 - Present",
      "cause": "Economic Empowerment"
    }
  ],
  "honors": [
    {
      "title": "Sigillum Magnum",
      "issuer": "University of Bologna",
      "date": "Sep 2023"
    }
  ],
  "publications": [
    {
      "title": "Superagency",
      "publisher": "Authors Equity",
      "date": "Jan 28, 2025"
    }
  ]
}
```

***

### What is not available without logging in

This Actor collects what LinkedIn shows to visitors who are not logged in. That covers almost every profile section, with these exceptions:

- **The About section is shortened**, usually to its first ~90 characters.
- **Recommendations** are generally not included.
- **Some very senior or long careers are cut short** by LinkedIn for logged-out visitors (for example, the most recent 13 of 30+ roles).
- **Profiles whose owner turned off public visibility** return "Profile not found".
- **Email addresses and phone numbers** are not included.

***

### What you will see during a run

The run log is written for you, in plain language:

- `Starting: 25 profile(s), 4 at a time.`
- `Progress: 10 of 25 profiles processed, 10 saved.`
- `Still working: 12 of 25 profiles processed, 12 saved so far.`
- `Could not retrieve some-username - Profile not found.`
- `Run complete. Saved 24 of 25 profile(s); the rest could not be retrieved from LinkedIn.`

At the end, profiles that could not be retrieved are grouped by reason.

***

### Recent posts (optional)

Turn on **Include recent posts** to add the person's own recent posts to each profile, in `recentPosts`: full text, exact publish date, reactions, comment count, images, videos and documents. Turn on **Include top comments on posts** to add the top public comments of each post at no extra cost.

- Charged per post delivered (see the Pricing tab). Off by default, so existing runs cost exactly the same.
- A public profile shows about 10 recent posts, so you get up to 10 per person, and some people have fewer or none.
- Posts that cannot be loaded are skipped and not charged. The profile itself is always saved.

***

### Free plan

On the Apify free plan each run scrapes the first **2** profiles of your list (and up to 3 recent posts each when enabled), with every section included, so you can check the output before upgrading. The run log says how many were skipped. Paid plans have no per-run cap.

***

### FAQ

**Do I need a LinkedIn account or cookies?**
No. The Actor never signs in and never asks for your credentials.

**Why is the About text short?**
LinkedIn shows logged-out visitors only the start of the About section. No logged-out method gets the full text.

**Am I charged for profiles that fail?**
No. A profile that cannot be retrieved (deleted, hidden or temporarily blocked) is reported in the run log and not saved, so it is not billed.

**How fast is it?**
Usually a few seconds per profile, with several profiles running at once. Rows appear in the dataset as each profile finishes.

**Can it scrape company pages, jobs or posts?**
This Actor is for person profiles (`linkedin.com/in/...`), including each person's recent posts when **Include recent posts** is on. Use a dedicated company or jobs scraper for those pages.

**How do I match results to my input?**
Use `publicIdentifier` (the username). Profiles missing from the dataset are named in the run log with the reason.

***

### Compliance

Use collected data in line with applicable data protection laws and [LinkedIn's User Agreement](https://www.linkedin.com/legal/user-agreement). Only publicly visible profile information is collected.

### Support

Use the **Issues** tab on the Store listing for bugs or feature requests.

# Actor input Schema

## `profiles` (type: `array`):

Enter profile URLs or public usernames, one per line. Supported formats include full profile links (for example, https://www.linkedin.com/in/satyanadella), regional links (for example, https://pk.linkedin.com/in/username), and plain usernames (for example, satyanadella).

## `includeRecentPosts` (type: `boolean`):

When enabled, each profile includes the person's own recent posts with full text, exact date, reactions, comment count and media, in the recentPosts field. Charged per post delivered. A public profile shows about 10 recent posts, so some people have fewer or none.

## `maxRecentPosts` (type: `integer`):

How many recent posts to collect for each profile (up to 10). Only applies when recent posts are enabled.

## `includePostComments` (type: `boolean`):

When enabled, each recent post also includes the top comments LinkedIn shows publicly (commenter, text, date, likes), at no extra cost. Only applies when recent posts are enabled.

## Actor input object example

```json
{
  "profiles": [
    "satyanadella",
    "https://www.linkedin.com/in/williamhgates"
  ],
  "includeRecentPosts": false,
  "maxRecentPosts": 5,
  "includePostComments": false
}
```

# Actor output Schema

## `results` (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 = {
    "profiles": [
        "satyanadella",
        "https://www.linkedin.com/in/williamhgates"
    ]
};

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

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

```

## MCP server setup

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