# LinkedIn Profile Scraper — No Login, No Cookies (`memo23/linkedin-profile-scraper`) Actor

Scrape LinkedIn profiles from a list of URLs with no login and no cookies, so your account is never involved. Name, headline, location, about, current company, work history, education and top skills, as JSON or CSV. $0.003 per profile; hidden or deleted profiles are free.

- **URL**: https://apify.com/memo23/linkedin-profile-scraper.md
- **Developed by:** [Muhamed Didovic](https://apify.com/memo23) (community)
- **Categories:** Lead generation, Automation
- **Features:** Limited permissions
- **Stats:** 107 total users, 17 monthly users, 100.0% runs succeeded, 5 bookmarks
- **User rating**: 5.00 out of 5 stars

## Pricing

from $1.00 / 1,000 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/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 — No Login, No Cookies

<p align="center">
  <img src="https://raw.githubusercontent.com/muhamed-didovic/muhamed-didovic.github.io/main/assets/linkedin-profile-logo.png" alt="LinkedIn Profile Scraper" width="140" height="140">
</p>

**Scrape LinkedIn profiles from a list of URLs with no login and no cookies.** Paste profile URLs and get each person's name, headline, location, about, current company, work history with dates, schools with degrees and top skills, as clean JSON or CSV.

No LinkedIn account of yours is involved: each profile is read as LinkedIn shows it to logged-out visitors, so there is no session to get restricted and nothing to export from your browser.

| Input | Rows emitted |
|---|---|
| LinkedIn profile URLs | One public profile per URL |

> No browser and no headless Chrome. Profiles come from a public-profile data source over plain HTTP.

**You pay per profile delivered: $0.003 each.** A profile that is deleted, mistyped or hidden from logged-out visitors is not billed, and a run that returns nothing costs half a cent (the $0.005 start fee), never dollars.

***

### Switching from another LinkedIn profile scraper?

If you've been burned elsewhere, here is exactly how this actor behaves on the failure modes people complain about most:

| What happens elsewhere | What happens here |
|---|---|
| "My account got restricted" | No account is used. You never paste cookies or log in. |
| "Charged $2 and got an empty JSON" | Profile charges fire **only when a profile row lands in your dataset**. Nothing delivered = $0.005 total for the run start, nothing more. |
| "Aborted runs charged in full" | Pay-per-event billing accrues per delivered row. Abort a run and you pay only for the profiles already in your dataset at that moment. |
| "Anomalous billing across runs" | Every event is listed on the pricing tab. A 1,000-profile run is about **$3.01**, so you can predict the bill before you press Start. |

***

### Related LinkedIn Scrapers

- **[LinkedIn Company Profile Scraper](https://apify.com/memo23/linkedin-company-profile-scraper)** — company details from About pages
- **[LinkedIn Search Jobs Scraper (Without Cookies)](https://apify.com/memo23/apify-linkedin-search-results-scraper)** — job listings, no authentication
- **[LinkedIn Search Groups Scraper](https://apify.com/memo23/linkedin-search-groups-scraper)** — find and extract groups
- **[LinkedIn Company Employees/People Scraper](https://apify.com/memo23/linkedin-company-people-scraper)** — employee profiles from companies
- **[LinkedIn People Search Scraper](https://apify.com/memo23/linkedin-people-search)** — search people by keyword, title, company or school

***

### How it works

1. **You paste profile URLs.** Anything of the form `https://www.linkedin.com/in/<name>/`.
2. **Each profile is read without a login.** The actor asks a public-profile data source for the profile LinkedIn shows to logged-out visitors. Nothing of yours is used.
3. **It writes one row per person** to the dataset, ready to export as JSON, CSV or Excel. Profiles that do not exist or are hidden are skipped, counted in the status message, and not billed.

***

### How to use it

Paste profile URLs into **Start URLs** and press Start.

```json
{
  "startUrls": [
    { "url": "https://www.linkedin.com/in/williamhgates/" },
    { "url": "https://www.linkedin.com/in/satyanadella/" }
  ],
  "maxItems": 100
}
```

***

### Input

| Field | Type | Required | Notes |
|---|---|---|---|
| `startUrls` | array | yes | LinkedIn profile URLs. |
| `maxItems` | integer | no | Max profiles scraped per run. Default `100`. |
| `maxSkills` | integer | no | Keep only the first N skills on each profile (at most three come back). Default `0` keeps them all. |
| `maxConcurrency` | integer | no | Parallel lookups. Default `10`, which is also the most it uses. |
| `maxRequestRetries` | integer | no | Retries before giving up on a request. Default `10`. |
| `proxy` | object | no | Optional override. Leave empty to use the built-in proxy. |

***

### Output

One row per profile. Values below are illustrative.

```jsonc
{
  "firstName": "Jane",
  "lastName": "Doe",
  "headline": "Product Operations Manager @ Panax | Chartered Accountant",
  "location": "Melbourne, Victoria, Australia",
  "publicIdentifier": "jane-doe-4242",
  "profileUrl": "https://www.linkedin.com/in/jane-doe-4242",
  "about": "Chartered accountant turned product operator...",
  "currentCompany": "Panax",
  "currentCompanyUrl": "https://www.linkedin.com/company/panax",
  "followerCount": 1662,
  "connectionCount": 500,
  "workHistory": [
    { "title": "Product Operations Manager", "company": "Panax", "companyUrl": "https://www.linkedin.com/company/90915183/", "date": "Aug 2023 - Present", "isCurrent": true }
  ],
  "education": [
    { "school": "The Hebrew University of Jerusalem", "schoolUrl": "https://www.linkedin.com/company/41964/", "degree": "BCom, Accounting", "date": "2012 - 2015" }
  ],
  "skills": ["Product Operations", "Financial Modeling", "SQL"],
  "isPremium": false,
  "isVerified": true,
  "openToWork": false,
  "profilePictureUrl": "https://media.licdn.com/...",
  "backgroundPictureUrl": "https://media.licdn.com/...",
  "accountCreatedAt": "2016-03-14T10:22:05.000000+00:00",
  "loggedIn": false,
  "userHandle": "jane-doe-4242",
  "scrapedAt": "2026-10-15T09:00:00.000Z"
}
```

#### Key fields

| Field | Description |
|---|---|
| `firstName`, `lastName` | The display name, split at the first space. |
| `headline` | Professional headline. |
| `location` | Display location, city through country. |
| `publicIdentifier`, `profileUrl` | Profile slug and full profile URL. |
| `about` | The About section. |
| `currentCompany`, `currentCompanyUrl` | Current employer and its LinkedIn page. |
| `followerCount`, `connectionCount` | As shown on the profile. |
| `workHistory[]` | `title`, `company`, `companyUrl`, `date`, `isCurrent`. |
| `education[]` | `school`, `schoolUrl`, `degree`, `date`. |
| `skills[]` | The top three skills the profile shows. |
| `isPremium`, `isVerified`, `openToWork` | Profile badges. |
| `profilePictureUrl`, `backgroundPictureUrl` | Image URLs. |
| `accountCreatedAt` | When the LinkedIn account was created. |
| `loggedIn` | Always `false`: every row is read without a login. |

***

### Pricing

Pay per event. No monthly rental.

| Event | When it fires | Price |
|---|---|---|
| Actor start | Once per run, per GB of memory | $0.005 |
| Dataset item | Each profile written | $0.001 |
| Profile without login | Each profile written, on top of the dataset item | $0.002 |

A 1,000-profile run costs about **$3.01**.

**No profiles, no profile charges.** Both profile events fire only when a profile row is actually written. A profile that does not exist or is hidden is not billed, and an empty run costs $0.005, full stop.

***

### FAQ

**Do I need a LinkedIn account or cookie?**
No. Paste profile URLs and press Start.

**Can my account get restricted?**
Not by this actor: no account is used at all.

**Why is a profile missing from my results?**
Its owner deleted it, the URL is mistyped, or the owner hides it from logged-out visitors. Those are skipped, counted in the run's status message, and not billed.

**Why are some dates or fields empty?**
The profile does not show them publicly. The actor leaves a field empty rather than guessing a value.

**The run returned nothing — am I still charged?**
Only the $0.005 start fee. The profile charges fire per row written to your dataset, so a run with zero results can never cost you dollars.

***

### 🤖 For AI Agents & LLM Apps

**Purpose:** Extract public LinkedIn profile records — identity, headline, location, about, current company, work history, education, top skills — from profile URLs, with no LinkedIn login.

**Auth:** None.

**Minimal tested input:**

```json
{
  "startUrls": [{"url":"https://www.linkedin.com/in/williamhgates/"}],
  "maxItems": 1
}
```

**Output fields** (`loggedIn: false`): `firstName`, `lastName`, `headline`, `location`, `publicIdentifier`, `profileUrl`, `about`, `currentCompany`, `currentCompanyUrl`, `followerCount`, `connectionCount`, `workHistory[]` (`title`, `company`, `companyUrl`, `date`, `isCurrent`), `education[]` (`school`, `schoolUrl`, `degree`, `date`), `skills[]` (top 3), `isPremium`, `isVerified`, `openToWork`, `profilePictureUrl`, `backgroundPictureUrl`, `accountCreatedAt`, `userHandle`, `scrapedAt`.

**Billing:** $0.005 per run start (per GB), $0.001 per profile returned plus $0.002 (event `public-profile`), so $0.003 per profile.

**Failure modes worth handling:** a deleted, mistyped or hidden profile is skipped and not billed, and the status message counts them; fields a profile does not show come back as `""` or `[]` rather than being omitted or guessed.

***

### Additional Services

Custom fields, a full dataset, or a different LinkedIn surface — email <muhamed.didovic@gmail.com>.

***

### Support

Issues and feature requests via the actor's Issues tab, or email above.

***

### ⚠️ Disclaimer

This actor returns only what LinkedIn shows logged-out visitors. Use it on data you are entitled to access, and comply with LinkedIn's Terms of Service and applicable data-protection law — including the GDPR and CCPA — when storing or processing results. Personal data carries obligations around lawful basis, retention and subject access. You are the data controller for anything you collect; the actor's author is not. Do not use output for unlawful discrimination, harassment, or unsolicited bulk messaging.

***

### SEO Keywords

linkedin profile scraper no cookies, linkedin scraper no login, linkedin scraper, linkedin profile scraper, linkedin data extraction, scrape linkedin profiles, linkedin profile api, linkedin scraper without login, public linkedin profile data, linkedin lead generation, recruitment data, candidate sourcing, linkedin crawler, linkedin json export, linkedin csv export, professional profile data, linkedin employment history, b2b prospecting, sales navigator alternative, reliable linkedin profile scraper, best linkedin profile scraper, linkedin scraper pay per result, cheap linkedin profile scraper, linkedin profile scraper alternative, linkedin scraper transparent billing, apify linkedin actor

# Actor input Schema

## `scrapeMyConnections` (type: `boolean`):

Not shown in the form. Kept so existing tasks and API calls that export their own connections keep working; it needs your cookies. Turn this on to scrape <b>your own first-degree connections</b> instead of supplying URLs yourself. The actor reads your My Network list, then scrapes the full profile of every connection it finds. Leave Start URLs empty when using this. There is no 1,000-result limit — it walks your whole network. <b>Needs your cookies</b> (see the Cookies section below).

## `maxConnections` (type: `integer`):

Only used when 'Scrape my own connections' is on. Caps how many connections are collected before scraping starts.

## `startUrls` (type: `array`):

LinkedIn profile URLs to scrape, like https://www.linkedin.com/in/williamhgates/. No login and no cookies needed: each profile is read as LinkedIn shows it to logged-out visitors.

## `maxItems` (type: `integer`):

Maximum number of Profiles/Items to scrape per crawl.

## `language` (type: `string`):

Not shown in the form: it only applies to runs with cookies. Ask LinkedIn for profile text (headlines, job titles, school and skill names) in this locale. Members who published a translation come back in that language; everyone else keeps their original wording, so you never lose rows. Leave empty for US English. Needs cookies; public profiles read without cookies come back in their original language.

## `maxSkills` (type: `integer`):

Keep only the first N skills on each profile. LinkedIn returns them ordered by endorsement strength, so the top ones survive. Leave at 0 to keep every skill returned. Profiles read without a cookie carry at most three.

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

Maximum number of pages that can be processed at the same time.

## `minConcurrency` (type: `integer`):

Minimum number of pages that will be processed at the same time.

## `maxRequestRetries` (type: `integer`):

Number of times the crawler will retry a failed request before giving up.

## `cookies` (type: `array`):

<p>Not shown in the form: the actor reads public profiles without a login. Kept so existing tasks and API calls that pass their own LinkedIn session keep working.</p><p><b>Optional.</b> Leave this empty to scrape the Start URLs as public profiles without a LinkedIn login. Add your cookies for the fuller logged-in profile (volunteering, languages, certifications, LinkedIn IDs), and for profiles hidden from logged-out visitors. Most runs do not need them.</p><p>Cookie used to authorize actor with linkedin.com. Install <a rel="noopener noreferrer nofollow" target="_blank" href="https://chrome.google.com/webstore/detail/editthiscookie/fngmhnnpilhplaeedifhccceomclgfbg" previewlistener="true">EditThisCookie</a> chrome extension. Login to your linkedin.com account. Click on the extension and press <b>Export</b> to copy all linkedin.com cookies, then paste them here.</p><p><b>Paste the full exported list of cookie objects — not a single value.</b> Both <code>li_at</code> and <code>JSESSIONID</code> must be present: <code>li_at</code> is the session, and <code>JSESSIONID</code> is used as the CSRF token for LinkedIn's internal API. It should look like this:</p><pre>[
  {"name":"li_at","value":"AQED...","domain":".linkedin.com"},
  {"name":"JSESSIONID","value":"ajax:...","domain":".linkedin.com"}
]</pre>
## `proxy` (type: `object`):

Leave empty — the actor already routes all traffic through its own built-in residential proxy at no extra cost to you. Only set this if you want to use your own proxies.

## Actor input object example

```json
{
  "scrapeMyConnections": false,
  "maxConnections": 5000,
  "startUrls": [
    {
      "url": "https://www.linkedin.com/in/harsh-shuddhalwar/"
    }
  ],
  "maxItems": 100,
  "language": "",
  "maxSkills": 0,
  "maxConcurrency": 10,
  "minConcurrency": 1,
  "maxRequestRetries": 10,
  "cookies": []
}
```

# Actor output Schema

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

One row per profile with name, headline, location, about, current company, and the workHistory, education and skills arrays.

# 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 = {
    "startUrls": [
        {
            "url": "https://www.linkedin.com/in/harsh-shuddhalwar/"
        }
    ],
    "cookies": []
};

// Run the Actor and wait for it to finish
const run = await client.actor("memo23/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 = {
    "startUrls": [{ "url": "https://www.linkedin.com/in/harsh-shuddhalwar/" }],
    "cookies": [],
}

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

```

## MCP server setup

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