# LinkedIn Profile Scraper | 9 Fields, No Login or Cookies (`themineworks/linkedin-profile-scraper`) Actor

Scrape public LinkedIn profiles in bulk with no login. Name, headline, experience, education, skills, connections, followers. From $4 per 1,000. MCP-ready.

- **URL**: https://apify.com/themineworks/linkedin-profile-scraper.md
- **Developed by:** [The Mine Works](https://apify.com/themineworks) (community)
- **Categories:** Lead generation, Social media, MCP servers
- **Features:** Limited permissions
- **Stats:** 86 total users, 8 monthly users, 100.0% runs succeeded, 0 bookmarks
- **User rating**: No ratings yet

## Pricing

from $4.00 / 1,000 linkedin profiles

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 | Public Profiles, No Login or Cookies

[![16 LinkedIn profiles in 101 seconds: a test run on 20 public profiles delivered 16 and charged nothing for the 4 that LinkedIn refused](https://api.apify.com/v2/key-value-stores/cUXz95yxflDho41nn/records/linkedin-profile-scraper-hero.png)](https://console.apify.com/actors/lDghPuhZBgVdt0olp/input?fpr=ymnoit\&utm_source=apify-readme\&utm_medium=referral)

From **The Mine Works**, makers of [Threads Scraper](https://apify.com/themineworks/threads-scraper?fpr=ymnoit\&utm_source=apify-readme\&utm_medium=referral) and [B2B Leads Finder](https://apify.com/themineworks/b2b-leads-finder?fpr=ymnoit\&utm_source=apify-readme\&utm_medium=referral), with over 290,000 runs across 310+ public actors.

### Why choose this actor?

- **One plain request per profile, with no LinkedIn account.** There is no login, no cookies and no browser: the actor reads the structured record LinkedIn itself puts in every public profile page. A test run on 20 well known business leaders delivered 16 profiles in 101 seconds at 512 MB.
- **Only what LinkedIn really shows, never asterisks.** For most members, LinkedIn now masks job titles and past employers when the visitor is logged out. The actor leaves every masked value out and counts what was hidden, so a short row never passes for a short career. On 27 ordinary profiles read on 27 Oct 2026, every row had the name, location, current employer, connections and follower count.
- **You pay only for profiles that land in your dataset.** $4 to $7 per 1,000 profiles depending on your Apify plan. Profiles LinkedIn refuses, keeps behind its sign in wall or cannot find, duplicate URLs and the summary rows are never charged.

[![Run it on Apify](https://api.apify.com/v2/key-value-stores/cUXz95yxflDho41nn/records/button-run.png)](https://console.apify.com/actors/lDghPuhZBgVdt0olp/input?fpr=ymnoit\&utm_source=apify-readme\&utm_medium=referral)

**Part of The Mine Works LinkedIn family:** [LinkedIn Company Scraper](https://apify.com/themineworks/linkedin-company-details?fpr=ymnoit\&utm_source=apify-readme\&utm_medium=referral), [LinkedIn Post Scraper](https://apify.com/themineworks/linkedin-post-search?fpr=ymnoit\&utm_source=apify-readme\&utm_medium=referral), [LinkedIn Employees Scraper](https://apify.com/themineworks/linkedin-employees?fpr=ymnoit\&utm_source=apify-readme\&utm_medium=referral), [LinkedIn Email Finder](https://apify.com/themineworks/linkedin-email-finder?fpr=ymnoit\&utm_source=apify-readme\&utm_medium=referral), [LinkedIn Newsletter Scraper](https://apify.com/themineworks/linkedin-newsletter-scraper?fpr=ymnoit\&utm_source=apify-readme\&utm_medium=referral), [LinkedIn Candidate Finder](https://apify.com/themineworks/linkedin-candidate-finder?fpr=ymnoit\&utm_source=apify-readme\&utm_medium=referral).

### Try it in one minute

Paste this into the input's JSON tab and start the run. It asks for 10 public profiles of well known founders and executives, all of which came back in our 1 Oct 2026 test.

```json
{
  "profileUrls": [
    "https://www.linkedin.com/in/satyanadella",
    "https://www.linkedin.com/in/williamhgates",
    "https://www.linkedin.com/in/reidhoffman",
    "https://www.linkedin.com/in/jeffweiner08",
    "https://www.linkedin.com/in/andrewyng",
    "https://www.linkedin.com/in/melindagates",
    "https://www.linkedin.com/in/simonsinek",
    "https://www.linkedin.com/in/adammgrant",
    "https://www.linkedin.com/in/garyvaynerchuk",
    "https://www.linkedin.com/in/patrickcollison"
  ],
  "maxResults": 10
}
```

Every entry in `profileUrls` can be written five ways: a full URL (`https://www.linkedin.com/in/satyanadella`), a country subdomain URL (`https://in.linkedin.com/in/kunalshah1`), a URL without `https://` (`linkedin.com/in/satyanadella`), the short form `in/satyanadella`, or the bare username `satyanadella`. Query strings and trailing slashes are dropped, usernames are lowercased, and the same profile written two ways is fetched and charged once. Company, school and post URLs are not profile URLs and are skipped.

Apify's free plan includes $5 of credit every month, which covers about 707 profiles at this actor's price (the Free plan rate of $0.007 per profile, plus the $0.005 start fee on each of 10 runs at the default memory).

#### Copy to your AI assistant

```
themineworks/linkedin-profile-scraper on Apify. Turns public LinkedIn profile URLs into structured rows (name, location, current and past employers, schools with years, connection count, follower count, and job titles and about text when LinkedIn shows them) by reading the public page's embedded JSON-LD record, with no login, cookies or browser. For most ordinary members LinkedIn masks job titles and past employers for logged out visitors: those values are left out, never returned as asterisks, and counted in headline_hidden, experience_hidden and education_hidden. Call ApifyClient("TOKEN").actor("themineworks/linkedin-profile-scraper").call(run_input={...}), then client.dataset(run["defaultDatasetId"]).list_items().items. Required: profileUrls (list of https://www.linkedin.com/in/<username> URLs, country subdomain URLs or bare usernames; up to 500). Optional: maxResults (default 10, up to 500, also the cost cap), proxy (default Apify datacenter proxy), monitorMode (default false; true delivers and charges only profiles new or changed since an earlier run with the same list, and only profiles LinkedIn shows in full can come back as changed). Profile rows have no _type and no status field; a profile that could not be read comes back as {profile_url, status} where status is "blocked" (LinkedIn refused the request; worth a retry later), "not_public" (LinkedIn showed its sign in wall after 2 tries on 2 IPs, which is also how it answers a profile that does not exist) or "not_found"; every run ends with one row with _type "summary" and, when profiles were delivered, one row with _type "info"; none of these extra rows is charged. Full spec: GET https://api.apify.com/v2/acts/themineworks~linkedin-profile-scraper/builds/default (Bearer TOKEN), which returns inputSchema and readme. Token: https://console.apify.com/account/integrations?fpr=ymnoit&utm_source=apify-readme&utm_medium=referral
```

### Key features

- **One plain HTTP request per profile, no browser.** LinkedIn keeps public profiles open to logged out visitors so search engines can index them, and embeds a `Person` record as JSON-LD in the page. The actor reads that record, not the visual page, at 512 MB of memory.
- **13 fields per profile.** `profile_url`, `name`, `headline`, `headline_hidden`, `location`, `about`, `connections`, `followers`, `experience`, `experience_hidden`, `education`, `education_hidden` and `scraped_at`. Employers carry `current` plus start and end dates when LinkedIn shows them, and schools carry their years.
- **Masked values are left out and counted.** Anything LinkedIn replaced with asterisks stays out of the row, and the three `_hidden` fields say how much LinkedIn held back.
- **Schools and jobs kept apart.** LinkedIn's record puts schools and past employers in one list. The actor sorts them by the type LinkedIn gives each entry, so `education` holds only schools and past jobs go to `experience`.
- **Up to 500 profiles per run, deduplicated.** Paste a list of any length: the actor cleans each entry, removes duplicates, and stops at `maxResults` (and never past 500).
- **Two tries per profile, each on a fresh IP.** Every request goes out on a new Apify datacenter proxy session. If the first try fails, the actor waits about a second and tries once more on a different IP. That helps when LinkedIn refused an IP. A profile that still shows LinkedIn's sign in wall after both tries comes back as `not_public`.
- **A row for every profile you asked for.** Profiles that could not be read come back as a short row with `status: "blocked"`, `"not_public"` or `"not_found"`, so you can see exactly which ones are worth a retry. Those rows are free.
- **A stop switch for bad IP luck that ignores closed profiles.** If 5 profiles in a row are refused (`blocked`), the run stops early instead of working through the rest of your list against a wall. Profiles behind the sign in wall (`not_public`) do not count toward it, because they say nothing about the IP: a 27 Oct run on 61 ordinary profiles, 34 of them closed, went through all 61. Only when the first 12 profiles, or 20 in a row, cannot be read at all does the run stop, because that usually means LinkedIn is walling the IP pool. The summary row says why and how many were not tried.

### How to use it

#### Basic: one profile

```json
{
  "profileUrls": ["https://www.linkedin.com/in/satyanadella"],
  "maxResults": 1
}
```

This is the smallest useful run: one profile, one charge, done in about 5 seconds on Apify.

#### Several profiles in one run, written any way

```json
{
  "profileUrls": [
    "https://www.linkedin.com/in/reidhoffman/",
    "in.linkedin.com/in/kunalshah1",
    "in/guykawasaki",
    "adammgrant",
    "https://www.linkedin.com/in/adammgrant?trk=public_profile"
  ],
  "maxResults": 50
}
```

The last two entries are the same person, so the run fetches 4 profiles and charges for at most 4. `maxResults` is a ceiling, not a target: a list of 4 profiles with `maxResults: 50` costs the same as `maxResults: 4`.

#### Enrich a candidate shortlist for your ATS

```json
{
  "profileUrls": [
    "https://www.linkedin.com/in/candidate-one",
    "https://www.linkedin.com/in/candidate-two",
    "https://www.linkedin.com/in/candidate-three"
  ],
  "maxResults": 500
}
```

Paste the profile URLs from your sourcing sheet, up to 500 at a time. Export the dataset as CSV or Excel and map `name`, `location`, `experience` and `education` to your ATS fields. For most candidates LinkedIn hides job titles and past employers from logged out visitors, so expect the current employer, a school and the location rather than a full work history. For longer lists, split them into runs of 500.

#### Check prospects' current employers before outreach

Put your target accounts' contact URLs into a saved task and schedule it weekly (Apify Console, Schedules, Create new). Compare the `experience` entries with `current: true` against last week's export: a new current employer is often a job change worth acting on. The current employer was readable on all 27 ordinary profiles in our 27 Oct test. Without monitor mode every scheduled run delivers, and charges for, every profile on the list again. With `"monitorMode": true` a run delivers only the profiles that changed, for profiles LinkedIn shows in full (see Run it on a schedule).

#### Feed it from our discovery actors

[LinkedIn Employees Scraper](https://apify.com/themineworks/linkedin-employees?fpr=ymnoit\&utm_source=apify-readme\&utm_medium=referral) finds public profiles at a company by job title, and [LinkedIn Post Scraper](https://apify.com/themineworks/linkedin-post-search?fpr=ymnoit\&utm_source=apify-readme\&utm_medium=referral) finds the authors of posts on a topic. Both return LinkedIn profile URLs. Pass those URLs to this actor in `profileUrls` to add the current employer, schools, connections and follower counts to each person.

#### Retry only the profiles that were refused

```json
{
  "profileUrls": [
    "https://www.linkedin.com/in/refused-profile-one",
    "https://www.linkedin.com/in/refused-profile-two"
  ],
  "maxResults": 2
}
```

Filter the last run's dataset on `status = "blocked"`, copy those `profile_url` values into a new run, and start it a little later. Those are the profiles LinkedIn refused because of the IP, and a fresh run gets fresh IPs. Skip the `not_public` ones: the actor already tried each of them twice on two IPs, and on 27 Oct a further try from a US residential IP opened only 1 of 34. A refused profile costs nothing either time it is refused.

### Input parameters

| Parameter | Type | Default | What it does |
|---|---|---|---|
| `profileUrls` | array of strings | none (prefilled with one example) | Public LinkedIn profiles to read: full URLs, country subdomain URLs, `linkedin.com/in/...` without `https://`, `in/<username>` or bare usernames. Duplicates are removed. At most 500 are used. |
| `maxResults` | integer | `10` | Most profiles processed in the run, 1 to 500. Applied after duplicates are removed. This is also your cost cap. |
| `monitorMode` | boolean | `false` | Deliver only profiles that are new or whose headline, employers, schools, location or About text changed since an earlier run with the same list. Unchanged profiles are not charged. Made for weekly schedules. |
| `proxy` | object | Apify proxy, datacenter | Proxy settings. Leave it as it is: public profile pages need no special proxy, and each profile already goes out on a fresh datacenter IP session. |

If no entry in `profileUrls` looks like a LinkedIn profile, the run writes only a summary row with `note: "no_valid_urls"` and charges no profiles.

### What LinkedIn shows a logged out visitor

LinkedIn serves two kinds of public record. Public figures usually get the full one. Most ordinary members get a masked one, where job titles, past employers and job descriptions are replaced with asterisks. This is what the actor delivered on 27 Oct 2026:

| Field | Public figures (Satya Nadella, Bill Gates, Reid Hoffman) | Ordinary members (27 profiles found through Google) |
|---|---|---|
| Name and location | yes | 27 of 27 |
| Current employer with its LinkedIn page | yes | 27 of 27 |
| Connections and followers | yes | 27 of 27 |
| At least one school | yes, with years | 21 of 27 (19 with years) |
| About text, often cut short | yes | 17 of 27 |
| Job titles (`headline`) | yes | hidden on 27 of 27 |
| Past employers | yes, with dates | hidden on all 26 that listed any |

Being well known is not always enough: YouTube's CEO Neal Mohan gets the masked record (see the examples below).

Some profiles show nothing at all to a logged out visitor. Of 61 ordinary profiles found through Google on 27 Oct, 34 answered with LinkedIn's sign in wall (HTTP 999) from a datacenter IP, and a second try from a US residential IP opened only 1 of them. Those come back as `status: "not_public"` and are never charged. Even some well known people are closed: Sundar Pichai and Jensen Huang both came back `not_public` on 27 Oct, while 16 of 20 well known leaders opened in our 1 Oct test.

### What data do you get?

One row per profile you asked for, then a summary row. Profile rows have no `_type` and no `status` field, which is the simplest way to filter them.

**The person:** `name`, `profile_url` (the address LinkedIn's record gives, which can be a country subdomain such as `https://in.linkedin.com/in/kunalshah1`), `location` (as shown on the profile, for example `Redmond, Washington, United States`), `about` (the about text from the public record, which LinkedIn often cuts short with "…"), `followers` (the follower count, as a string) and `connections` (as LinkedIn shows it to logged out visitors: `"500+"` above 500, otherwise the exact count, such as `"461"`).

**Job titles:** `headline` holds the job titles LinkedIn lists in the profile's public record, joined with commas, one per position, for example `Chairman and CEO, Member Board Of Trustees`. It is not the free text headline under the person's name, and the titles are not paired with companies. `headline_hidden` is `true` when LinkedIn masked titles. Masked titles are left out, so for most ordinary members `headline` is missing and `headline_hidden` is `true`.

**Employers:** `experience`, an array of `{ "company", "company_url", "current" }`, plus `location`, `start`, `end` and `description` when LinkedIn shows them. Current jobs come first (`current: true`), then past ones (`current: false`). Dates look like `"2017"` or `"2014-02"`. `experience_hidden` counts the employers LinkedIn masked and the actor left out. LinkedIn sometimes files a role at a university as a job (Satya Nadella is a trustee of the University of Chicago), and the actor keeps it in `experience` as LinkedIn files it.

**Schools:** `education`, an array of `{ "school", "school_url" }`, plus `start` and `end` years when shown. It holds only the entries LinkedIn marks as schools. `education_hidden` counts the schools LinkedIn masked.

**When:** `scraped_at`, the ISO time the row was written.

**Rows for profiles that could not be read** (never charged): `profile_url`, `status` and `scraped_at`. `status` is `not_public` when LinkedIn showed its sign in wall (HTTP 999) on both tries, which is also how LinkedIn answers a profile that does not exist. It is `blocked` when LinkedIn refused the request in another way (rate limit, error page, connection failure), which a later run may get past. It is `not_found` only when LinkedIn says plainly that the page does not exist (HTTP 404 or 410).

**Summary row** (`_type: "summary"`, never charged): `requested`, `scraped`, `blocked`, `not_public`, `not_found`, `charged_for`, `charge_failures` and `scraped_at`, plus `note: "no_valid_urls"` when the input had no usable profile. A run that stopped early adds `stopped_early` (`"consecutive_blocks"` or `"walled"`) and `not_tried`, the number of profiles it did not reach. A run that reaches its time limit writes a summary marked as ended on the deadline.

**Info row** (`_type: "info"`, never charged): written when at least one profile was delivered, with `delivered`, a `message`, a scheduling tip and `scraped_at`. With monitor mode on, profile rows also carry `monitor_status` (`new` or `changed`), and a last info row gives the monitor counts.

#### Stable fields for automations

These fields are written for every delivered profile; all 27 ordinary rows and every public figure row of the 27 Oct runs had them. Their names will not change, so a Google Sheet, Zapier zap or n8n flow can map them once.

| Field | What it is |
|---|---|
| `profile_url` | The profile's LinkedIn URL, the key to store and join on |
| `name` | Full name as shown on the profile, never masked |
| `experience` | Array of employers, current first; can be empty |
| `experience[].company` | Organization name as LinkedIn labels it |
| `experience[].company_url` | That organization's LinkedIn page, or `null` |
| `experience[].current` | `true` for a current job, `false` for a past one |
| `experience_hidden` | How many employers LinkedIn masked, `0` when none |
| `education` | Array of schools; can be empty |
| `education[].school` | School name as LinkedIn labels it |
| `education[].school_url` | That school's LinkedIn page, or `null` |
| `education_hidden` | How many schools LinkedIn masked, `0` when none |
| `headline_hidden` | `true` when LinkedIn masked the job titles |
| `scraped_at` | When this row was written, ISO 8601 |

`location`, `connections` and `followers` were also in all 27 ordinary rows and `about` in 17, but the actor leaves any of them out when LinkedIn shows no value, so treat them as optional, like `headline`.

**Changed on 27 Oct 2026.** Masked text is no longer passed through: a field that used to hold asterisks is now missing, with the matching `_hidden` field set. Past employers that LinkedIn lists next to schools used to appear under `education` and now appear under `experience` with `current: false`. `connections` is now filled. Profiles behind LinkedIn's sign in wall used to come back as `blocked` and could stop the run; they now come back as `not_public` and the run carries on.

#### Output examples

**A full profile** (test run, 27 Oct 2026):

```json
{
  "profile_url": "https://www.linkedin.com/in/satyanadella",
  "name": "Satya Nadella",
  "experience": [
    { "company": "Microsoft", "company_url": "https://www.linkedin.com/company/microsoft", "current": true, "location": "Greater Seattle Area", "start": "2014-02" },
    { "company": "University of Chicago", "company_url": "https://www.linkedin.com/school/uchicago/", "current": true, "start": "2018" },
    { "company": "Starbucks", "company_url": "https://www.linkedin.com/company/starbucks", "current": false, "start": "2017", "end": "2024" },
    { "company": "The Business Council U.S.", "company_url": "https://www.linkedin.com/company/the-business-council-us", "current": false, "start": "2021", "end": "2023" },
    { "company": "Fred Hutch", "company_url": "https://www.linkedin.com/company/fredhutch", "current": false, "start": "2016", "end": "2022" }
  ],
  "education": [
    { "school": "The University of Chicago Booth School of Business", "school_url": "https://www.linkedin.com/school/universityofchicagoboothschoolofbusiness/", "start": "1994", "end": "1996" }
  ],
  "headline_hidden": false,
  "experience_hidden": 0,
  "education_hidden": 0,
  "headline": "Chairman and CEO, Member Board Of Trustees",
  "location": "Redmond, Washington, United States",
  "about": "As chairman and CEO of Microsoft, I define my mission and that of my company as empowering every person and every organization on the planet to achieve more.",
  "followers": "12257773",
  "connections": "500+",
  "scraped_at": "2026-10-27T11:44:27.357Z"
}
```

**A masked profile** (same day): LinkedIn hid the job titles, 16 employers and one school. The row keeps what LinkedIn shows and counts the rest. This is the shape most ordinary members' rows take.

```json
{
  "profile_url": "https://www.linkedin.com/in/neal-mohan",
  "name": "Neal Mohan",
  "experience": [
    { "company": "YouTube", "company_url": "https://www.linkedin.com/company/youtube", "current": true }
  ],
  "education": [
    { "school": "Stanford University", "school_url": "https://www.linkedin.com/school/stanford-university/", "start": "1992", "end": "1996" }
  ],
  "headline_hidden": true,
  "experience_hidden": 16,
  "education_hidden": 1,
  "location": "San Francisco Bay Area",
  "followers": "264988",
  "connections": "500+",
  "scraped_at": "2026-10-27T11:48:29.692Z"
}
```

**A profile behind the sign in wall** (same day; nothing charged):

```json
{
  "profile_url": "https://www.linkedin.com/in/sundarpichai",
  "status": "not_public",
  "scraped_at": "2026-10-27T12:08:41.444Z"
}
```

**The summary row of a run on 61 ordinary profiles** (27 Oct 2026): 34 sat behind the sign in wall, 12 of them in a row at one point, and the run still went through the whole list.

```json
{
  "_type": "summary",
  "requested": 61,
  "scraped": 27,
  "blocked": 0,
  "not_public": 34,
  "not_found": 0,
  "charged_for": 0,
  "charge_failures": 0,
  "scraped_at": "2026-10-27T12:06:35.353Z"
}
```

`charged_for` is 0 in these runs only because they ran on our own machine, outside Apify billing. On Apify it counts the profiles charged, 27 in the run above.

### Pricing

Pay per event. You are charged for each profile delivered to your dataset, plus a small start fee per run. The rate falls as your Apify plan rises.

| Event | Free | Bronze | Silver | Gold and above |
|---|---|---|---|---|
| Profile delivered (`profile-scraped`), per profile | $0.007 | $0.00625 | $0.0056 | $0.004 |
| Per 1,000 profiles | $7.00 | $6.25 | $5.60 | $4.00 |
| Run start (`apify-actor-start`) | $0.005 per GB of run memory, minimum one event | same | same | same |

**The start fee, exactly.** Apify's `apify-actor-start` event is charged once when a run starts, one event per GB of memory with a minimum of one. At the default 512 MB, and at 1 GB, that is one event, $0.005 per run. A 4 GB run would pay $0.02. This actor does not need more than 512 MB.

**Never charged:** profiles LinkedIn refused (`status: "blocked"`), keeps behind its sign in wall (`"not_public"`) or says do not exist (`"not_found"`), duplicate URLs in your list, the summary row and the info row. A run in which every profile is refused pays only the start fee.

**Charged like any other profile:** a profile LinkedIn has partly masked. The row has the person's real name, and in every masked profile we measured also the location and current employer; the masked parts are left out and counted. A profile without a readable name is never delivered or charged.

**What real jobs cost on Gold:** 500 profiles cost $2.00 plus $0.005. A weekly check of 50 prospects costs $0.205 a week. On the Free plan, 100 profiles cost $0.70 plus $0.005.

There is no price change scheduled for this actor. The Pricing tab on this page always shows the rate for your own plan.

### Run it on a schedule

Switch on `monitorMode` to hear about a person only when their profile changes. The first run delivers every profile. After that, a profile comes back only when the name, headline, location, About text, employers or schools change, and you pay only for the profiles delivered. A new first employer is what a job change looks like.

1. Fill in the input, tick **Monitor mode**, and save it as a task.
2. In Apify Console open **Schedules**, click **Add schedule**, and pick **Weekly** (or a cron such as `0 6 * * 1`).
3. Add the saved task to the schedule and click **Save**.

```json
{
  "profileUrls": [
    "https://www.linkedin.com/in/satyanadella",
    "https://www.linkedin.com/in/rbranson"
  ],
  "maxResults": 50,
  "monitorMode": true
}
```

Each delivered row carries `monitor_status`: `new` the first time, `changed` when the profile differs from the version you last received. An unchanged profile is read but not delivered and not charged; the start fee applies to every run as usual. The follower count alone does not count as a change. The last row of each run (`_type: "info"`) gives `new_this_run`, `changed_this_run` and `skipped_already_seen`. The history belongs to the list: change `profileUrls` and a new history starts; change `maxResults` and it carries on.

Monitor mode reports changes only on profiles LinkedIn shows in full. A profile where LinkedIn hid anything from logged out visitors (`headline_hidden` is `true` or a `_hidden` count is above 0, which is most ordinary members) is delivered the first time and then skipped, so a job change on it is not reported. The 27 Oct 2026 update did not reset anyone's history: a watched profile that has not changed is still skipped and not charged.

### FAQ

**What does this actor read from LinkedIn?**
LinkedIn is the professional network where people list their jobs and education. For each public profile page (`linkedin.com/in/...`) it reads the structured `Person` record that LinkedIn embeds for search engines, plus the connection count from the page's description: name, location, employers, schools, follower and connection counts, and job titles and about text when LinkedIn shows them.

**How many profiles can I get?**
Up to 500 per run, set with `maxResults`. How many come back depends on who is on the list. LinkedIn keeps many ordinary members' profiles behind its sign in wall for logged out visitors: on 27 Oct 2026, 34 of 61 ordinary profiles found through Google answered that way, from datacenter and residential IPs alike. Well known people open more often: 16 of 20 in our 1 Oct test. Refused profiles are free, and the run tells you which ones they were.

**How fresh is the data?**
Live. Every run requests each page at the moment it runs, so employers and follower counts are what LinkedIn shows that day, stamped in `scraped_at`.

**Do I need a LinkedIn account, cookies or an API key?**
No. The actor never logs in, never uses cookies and never acts as any LinkedIn user, so there is no account on your side that could be restricted.

**Do I need a proxy?**
No setup is needed. The actor uses Apify's datacenter proxy by default and sends each profile on a fresh IP session.

**Why are job titles or past employers missing?**
LinkedIn masks them for most members when the visitor is logged out, replacing the text with asterisks. In our 27 Oct test, job titles were masked on all 27 ordinary profiles we could read, and past employers on all 26 that listed any. The actor never returns asterisks as data: it leaves those values out and sets `headline_hidden`, `experience_hidden` and `education_hidden`, so you know how much LinkedIn held back. Public figures usually get the full record, but not always.

**Why is there no skills list?**
Skills are not on the page LinkedIn shows logged out visitors, and the actor never invents values it cannot read. Job titles per company are not there either: `headline` lists titles without saying which company each one belongs to.

**Did the output change?**
Yes, on 27 Oct 2026. Masked values used to come through as asterisks, for example `"headline": "********** * ***"`, and past employers were listed under `education`, because LinkedIn files them in the same list as schools. Now masked values are left out and counted, past employers go to `experience` with `current: false`, schools carry their years and `connections` is filled. Profiles behind the sign in wall come back as `not_public` instead of `blocked` and no longer stop the run. A filter on `school_url` containing `/school/` still works but is no longer needed.

**What happens with private, deleted or misspelled profiles?**
They come back as `status: "not_public"` and are not charged. To a logged out visitor, LinkedIn answers a misspelled or deleted profile the same way as one it keeps behind its sign in wall (HTTP 999), so the actor cannot tell them apart; made up usernames tested on 27 Oct all came back `not_public`. `status: "not_found"` appears only when LinkedIn returns a plain not found page. The actor tries twice on two different IPs first, so check the spelling of any profile that stays `not_public`.

**Why did my run stop before the end of my list?**
Two things stop a run early, and the summary row says which in `stopped_early`, with the number of profiles not reached in `not_tried`. `consecutive_blocks`: 5 profiles in a row were refused (`blocked`), which points at the IPs. `walled`: the first 12 profiles, or 20 in a row, could not be read at all, including closed ones, which usually means LinkedIn is walling the IP pool. Closed profiles on their own do not stop a run: on 27 Oct a list of 61 ordinary profiles with 34 closed, 12 of them in a row, went through to the end. A list made almost entirely of closed profiles can still reach 20 in a row. Start a new run with the rest of the list a little later. A run also stops delivering profiles when your maximum cost per run in Apify is reached.

**How do I get the data out?**
From the run's Storage tab as JSON, CSV, Excel, XML or HTML, or through the Apify API. JSON keeps the `experience` and `education` arrays intact. CSV and Excel flatten them into numbered columns.

**Can I run it on a schedule?**
Yes. Save your input as a task, then add a schedule in Apify Console (Schedules, then Create new, for example every Monday at 06:00). Without monitor mode every run delivers and charges every profile in the list; with `monitorMode` on, only profiles that are new or changed since the last run (see Run it on a schedule for the limit on masked profiles).

**Can I use it from Claude, ChatGPT or another AI assistant?**

- Connector URL: `https://mcp.apify.com/?tools=themineworks/linkedin-profile-scraper`.
- Claude: Settings > Connectors > Add custom connector, paste the URL, sign in with Apify.
- ChatGPT: developer mode, add an MCP connector with the URL, sign in with Apify.
- Cursor or VS Code: add it as an HTTP MCP server with that URL.
- Claude Code: `claude mcp add -t http linkedin-profile-scraper "https://mcp.apify.com/?tools=themineworks/linkedin-profile-scraper"`.

It is also one of the tools inside our [Recruiting & Jobs MCP](https://apify.com/themineworks/recruiting-jobs-mcp?fpr=ymnoit\&utm_source=apify-readme\&utm_medium=referral) server, which bundles 10 recruiting tools.

**Is it legal to scrape public LinkedIn profiles?**
The actor reads only pages LinkedIn shows to anyone without logging in, and nothing behind a login. In *hiQ Labs v. LinkedIn*, a US appeals court held that scraping publicly accessible pages does not by itself violate the Computer Fraud and Abuse Act. Profiles still contain personal data, so you are responsible for how you use it, including LinkedIn's terms and data protection law such as GDPR and CCPA. This is general information, not legal advice. This actor is independent and not affiliated with or endorsed by LinkedIn.

### Integrations

Results land in a standard Apify dataset, so they connect without extra code:

- **Google Sheets:** send each run's profiles to a sheet with Apify's Google Sheets integration.
- **Make, Zapier and n8n:** start a run and read its dataset with the official Apify apps and nodes.
- **Webhooks:** get a call to your own URL when a run succeeds, then fetch the dataset.
- **API and SDKs:** start runs and read results with the Apify API, or the Python and JavaScript clients.
- **MCP clients:** Claude, ChatGPT, Cursor and other MCP clients can call the actor through `https://mcp.apify.com/?tools=themineworks/linkedin-profile-scraper`.

### More from The Mine Works

**LinkedIn**

- [LinkedIn Company Scraper](https://apify.com/themineworks/linkedin-company-details?fpr=ymnoit\&utm_source=apify-readme\&utm_medium=referral)
- [LinkedIn Post Scraper](https://apify.com/themineworks/linkedin-post-search?fpr=ymnoit\&utm_source=apify-readme\&utm_medium=referral)
- [LinkedIn Employees Scraper](https://apify.com/themineworks/linkedin-employees?fpr=ymnoit\&utm_source=apify-readme\&utm_medium=referral)
- [LinkedIn Email Finder](https://apify.com/themineworks/linkedin-email-finder?fpr=ymnoit\&utm_source=apify-readme\&utm_medium=referral)
- [LinkedIn Newsletter Scraper](https://apify.com/themineworks/linkedin-newsletter-scraper?fpr=ymnoit\&utm_source=apify-readme\&utm_medium=referral)
- [LinkedIn Candidate Finder](https://apify.com/themineworks/linkedin-candidate-finder?fpr=ymnoit\&utm_source=apify-readme\&utm_medium=referral)

**Social media and video**

- [Threads Scraper](https://apify.com/themineworks/threads-scraper?fpr=ymnoit\&utm_source=apify-readme\&utm_medium=referral)
- [Reddit Scraper](https://apify.com/themineworks/reddit-scraper?fpr=ymnoit\&utm_source=apify-readme\&utm_medium=referral)
- [Threads Search Scraper](https://apify.com/themineworks/threads-search-scraper?fpr=ymnoit\&utm_source=apify-readme\&utm_medium=referral)
- [Instagram Profile Scraper](https://apify.com/themineworks/instagram-profile-scraper?fpr=ymnoit\&utm_source=apify-readme\&utm_medium=referral)

**Leads and business directories**

- [B2B Leads Finder](https://apify.com/themineworks/b2b-leads-finder?fpr=ymnoit\&utm_source=apify-readme\&utm_medium=referral)
- [Skip Trace Lookup](https://apify.com/themineworks/skip-trace-lookup?fpr=ymnoit\&utm_source=apify-readme\&utm_medium=referral)
- [Google Maps Email Scraper](https://apify.com/themineworks/maps-leads?fpr=ymnoit\&utm_source=apify-readme\&utm_medium=referral)
- [JustDial Scraper](https://apify.com/themineworks/justdial-business?fpr=ymnoit\&utm_source=apify-readme\&utm_medium=referral)

**Marketing, SEO and reviews**

- [Facebook Ad Library Scraper](https://apify.com/themineworks/meta-ad-library-scraper?fpr=ymnoit\&utm_source=apify-readme\&utm_medium=referral)
- [Similarweb Scraper](https://apify.com/themineworks/similarweb-scraper?fpr=ymnoit\&utm_source=apify-readme\&utm_medium=referral)
- [Google Ads Transparency Scraper](https://apify.com/themineworks/google-ads-transparency?fpr=ymnoit\&utm_source=apify-readme\&utm_medium=referral)
- [Google News Scraper](https://apify.com/themineworks/google-news?fpr=ymnoit\&utm_source=apify-readme\&utm_medium=referral)

**Real estate**

- [Zillow Rentals Scraper](https://apify.com/themineworks/zillow-rental-listings?fpr=ymnoit\&utm_source=apify-readme\&utm_medium=referral)
- [Zillow Sold Comps Scraper](https://apify.com/themineworks/zillow-recently-sold?fpr=ymnoit\&utm_source=apify-readme\&utm_medium=referral)
- [Housing.com Scraper](https://apify.com/themineworks/housing-com-scraper?fpr=ymnoit\&utm_source=apify-readme\&utm_medium=referral)
- [India Real Estate MCP](https://apify.com/themineworks/india-real-estate-mcp?fpr=ymnoit\&utm_source=apify-readme\&utm_medium=referral)

**Science, health and government data**

- [CourtListener Scraper](https://apify.com/themineworks/courtlistener-court-records?fpr=ymnoit\&utm_source=apify-readme\&utm_medium=referral)
- [data.gov.in Scraper](https://apify.com/themineworks/india-data-gov-scraper?fpr=ymnoit\&utm_source=apify-readme\&utm_medium=referral)
- [Socrata Open Data Scraper](https://apify.com/themineworks/socrata-open-data?fpr=ymnoit\&utm_source=apify-readme\&utm_medium=referral)
- [Academic Research MCP](https://apify.com/themineworks/academic-research-mcp?fpr=ymnoit\&utm_source=apify-readme\&utm_medium=referral)

**Jobs and hiring**

- [Foundit Monster India Jobs](https://apify.com/themineworks/foundit-jobs-scraper?fpr=ymnoit\&utm_source=apify-readme\&utm_medium=referral)
- [Hirist Jobs Scraper](https://apify.com/themineworks/hirist-jobs-scraper?fpr=ymnoit\&utm_source=apify-readme\&utm_medium=referral)
- [India Jobs MCP](https://apify.com/themineworks/india-jobs-mcp?fpr=ymnoit\&utm_source=apify-readme\&utm_medium=referral)
- [Naukri Jobs Scraper](https://apify.com/themineworks/naukri-jobs?fpr=ymnoit\&utm_source=apify-readme\&utm_medium=referral)

**E-commerce and marketplaces**

- [Ozon.ru Scraper](https://apify.com/themineworks/ozon-product-search?fpr=ymnoit\&utm_source=apify-readme\&utm_medium=referral)
- [⭐ Amazon Reviews Scraper](https://apify.com/themineworks/amazon-reviews?fpr=ymnoit\&utm_source=apify-readme\&utm_medium=referral)
- [Amazon Product Scraper](https://apify.com/themineworks/amazon-products?fpr=ymnoit\&utm_source=apify-readme\&utm_medium=referral)
- [Carsales.com.au Scraper](https://apify.com/themineworks/carsales-scraper?fpr=ymnoit\&utm_source=apify-readme\&utm_medium=referral)

**Company and business data**

- [Company Domain Finder](https://apify.com/themineworks/company-domain-finder?fpr=ymnoit\&utm_source=apify-readme\&utm_medium=referral)
- [GST Taxpayer Lookup](https://apify.com/themineworks/gst-taxpayer-lookup?fpr=ymnoit\&utm_source=apify-readme\&utm_medium=referral)
- [World Bank Trade Scraper](https://apify.com/themineworks/global-trade-data?fpr=ymnoit\&utm_source=apify-readme\&utm_medium=referral)
- [Company KYB Resolver](https://apify.com/themineworks/company-identity-resolver?fpr=ymnoit\&utm_source=apify-readme\&utm_medium=referral)

**Food and local services**

- [NoBroker Scraper](https://apify.com/themineworks/nobroker-scraper?fpr=ymnoit\&utm_source=apify-readme\&utm_medium=referral)
- [Swiggy Restaurant Scraper](https://apify.com/themineworks/swiggy-scraper?fpr=ymnoit\&utm_source=apify-readme\&utm_medium=referral)
- [Zomato Scraper](https://apify.com/themineworks/zomato-scraper?fpr=ymnoit\&utm_source=apify-readme\&utm_medium=referral)

**Developer and AI tools**

- [Website to Markdown Crawler](https://apify.com/themineworks/rag-crawler?fpr=ymnoit\&utm_source=apify-readme\&utm_medium=referral)
- [GitHub Skill Finder](https://apify.com/themineworks/github-skill-discovery?fpr=ymnoit\&utm_source=apify-readme\&utm_medium=referral)
- [GitHub Repo Scraper](https://apify.com/themineworks/github-repo-intelligence?fpr=ymnoit\&utm_source=apify-readme\&utm_medium=referral)
- [GitHub Trending Scraper](https://apify.com/themineworks/github-trending-scraper?fpr=ymnoit\&utm_source=apify-readme\&utm_medium=referral)

**More tools**

- [Tennis Match & Player Data Scraper](https://apify.com/themineworks/tennis-match-data?fpr=ymnoit\&utm_source=apify-readme\&utm_medium=referral)
- [Google Hotels Prices Scraper](https://apify.com/themineworks/google-hotels-prices-scraper?fpr=ymnoit\&utm_source=apify-readme\&utm_medium=referral)
- [LandWatch Scraper](https://apify.com/themineworks/landwatch-land-for-sale-scraper?fpr=ymnoit\&utm_source=apify-readme\&utm_medium=referral)

### Support

Found a bug or need a field? Open an issue on the Issues tab of this actor. To ask for a new source, email dmineworks@gmail.com.

*LinkedIn Profile Scraper turns public LinkedIn profile URLs into rows of name, location, employers, schools, connections and follower counts, with no login, from $4 per 1,000 profiles.*

# Actor input Schema

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

List of public LinkedIn profiles to scrape. Accepts full URLs (e.g. https://www.linkedin.com/in/satyanadella), locale subdomains (in.linkedin.com/in/...), or bare usernames (e.g. satyanadella). Up to 500 per run.

## `maxResults` (type: `integer`):

Maximum number of profiles to return. Set to a small number (e.g. 3) for quick tests.

## `monitorMode` (type: `boolean`):

Run on a schedule and deliver ONLY profiles that are new or whose headline, employers, schools, location or About text changed since a previous run (for example a job change). The follower count alone does not count. You are charged per delivered profile, not for the whole list each time. Ideal for weekly monitoring. Requires the same input across runs.

## `proxy` (type: `object`):

Apify proxy. Defaults to datacenter. Public profile pages are Google-indexed and served over plain HTTP, so residential is not required. Each profile is fetched on a fresh proxy session (first-view IP). Set a group explicitly to override.

## Actor input object example

```json
{
  "profileUrls": [
    "https://www.linkedin.com/in/satyanadella"
  ],
  "maxResults": 1,
  "monitorMode": false,
  "proxy": {
    "useApifyProxy": true
  }
}
```

# 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 = {
    "profileUrls": [
        "https://www.linkedin.com/in/satyanadella"
    ],
    "maxResults": 1,
    "proxy": {
        "useApifyProxy": true
    }
};

// Run the Actor and wait for it to finish
const run = await client.actor("themineworks/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 = {
    "profileUrls": ["https://www.linkedin.com/in/satyanadella"],
    "maxResults": 1,
    "proxy": { "useApifyProxy": True },
}

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

```

## MCP server setup

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