# LinkedIn Profiles Scraper - $0.90/1k, No Login (`dami_studio/linkedin-profiles-scraper`) Actor

Turn a list of public LinkedIn profile URLs into clean rows: full name, public headline, description, profile image link, public identifier and the social links the profile lists. $0.90 per 1,000 profiles plus a $0.001 start fee, against $1.00-$1.99 for comparable actors. No login needed.

- **URL**: https://apify.com/dami\_studio/linkedin-profiles-scraper.md
- **Developed by:** [Dami's Studio](https://apify.com/dami_studio) (community)
- **Categories:** Lead generation, Developer tools, Automation
- **Stats:** 2 total users, 1 monthly users, 100.0% runs succeeded, 0 bookmarks
- **User rating**: No ratings yet

## Pricing

from $0.90 / 1,000 successful public profiles

This Actor is paid per event. You are not charged for the Apify platform usage, but only a fixed price for specific events.

Learn more: https://docs.apify.com/platform/actors/running/actors-in-store#pay-per-event

## What's an Apify Actor?

Actors are web data automations that power AI and operations. They run on the Apify platform to scrape websites, process data, connect APIs, and automate workflows.
In Batch mode, an Actor accepts a well-defined JSON input, performs an action which can take anything from a few seconds to a few hours,
and optionally produces a well-defined JSON output, datasets with results, or files in key-value store.
In Standby mode, an Actor provides a web server which can be used as a website, API, or an MCP server.
Actors are written with capital "A".

## How to integrate an Actor?

If asked about integration, you help developers integrate Actors into their projects.
You adapt to their stack and deliver integrations that are safe, well-documented, and production-ready.
The best way to integrate Actors is as follows.

- **AI agents and MCP clients** — the [Apify MCP server](https://docs.apify.com/integrations/mcp.md) at `https://mcp.apify.com` (remote, streamable HTTP, OAuth on first use).
- **Agentic workflows and local Actor development** — [Agent Skills](https://apify.com/.well-known/agent-skills/index.json) with the [Apify CLI](https://docs.apify.com/cli/docs.md): `npm install -g apify-cli`, then `apify login`.
- **JavaScript/TypeScript projects** — the official [JS/TS client](https://docs.apify.com/api/client/js/docs.md): `npm install apify-client`.
- **Python projects** — the official [Python client](https://docs.apify.com/api/client/python/docs.md): `pip install apify-client`.
- **Any other language** — the [REST API](https://docs.apify.com/api/v2.md).

For usage examples, see the [API](#api) section below.

For more details, see Apify documentation as [Markdown index](https://docs.apify.com/llms.txt) and [Markdown full-text](https://docs.apify.com/llms-full.txt).

# README

## LinkedIn Profiles Scraper

Extract only the data LinkedIn exposes publicly on supplied profile URLs. This actor does not request a login, cookies, hidden or private endpoints, employee/contact inference, profile search, or data behind a sign-in wall.

### Input

```json
{
  "profileUrls": [
    "https://www.linkedin.com/in/example-public-profile/"
  ],
  "maxProfiles": 10,
  "requestTimeoutSecs": 20
}
```

| Field | Type | Default | Notes |
|---|---|---|---|
| `profileUrls` | array | `[]` | Public URLs in the form `https://www.linkedin.com/in/<public-identifier>/`. Empty input returns one labelled, uncharged sample row. |
| `maxProfiles` | integer | `10` | Cap on how many valid URLs are requested in a run. Maximum 100. |
| `requestTimeoutSecs` | integer | `20` | Per-page request timeout, 1–60 seconds. |

Supply public URLs matching `https://www.linkedin.com/in/<public-identifier>/`. The actor does not resolve names, emails, or company domains into LinkedIn URLs. URLs are canonicalised before the request, so tracking parameters and trailing slashes are harmless and the same profile submitted twice is only fetched once.

### Output

Every genuine row is parsed from a matching public `Person` JSON-LD record present on the requested page:

| Field | What it is |
|---|---|
| `ok` | `true` on a real parsed profile, `false` on a diagnostic row. |
| `sourceType` | `public_linkedin_profile` on real rows, `sample` on the free sample row. |
| `profileUrl` | The canonicalised `/in/` URL that was requested. |
| `publicIdentifier` | The vanity slug from that URL, e.g. `example-public-profile`. |
| `fullName` | `Person.name` as LinkedIn publishes it. |
| `headline` | `Person.jobTitle` when present, otherwise the public description. |
| `description` | The public "about" text, when LinkedIn exposes it. |
| `profileImageUrl` | Public avatar URL, or `null`. |
| `sameAs` | The outbound links the profile itself lists (personal site, other socials). Empty array when there are none. |
| `transport` | `direct_http` — the actor never runs a browser. |
| `retrievedAt` | ISO timestamp of the fetch. |

Missing fields are `null` or empty. It does not infer contact details, work history, employers, location, email addresses, or private profile attributes.

#### Diagnostic rows

Anything that is not a parsed profile comes back as an uncharged row with `ok: false`, `_diagnostic: true` and an `errorCode`:

- `BAD_INPUT` — the URL is not a `linkedin.com/in/` profile URL.
- `NO_RESULTS` — the page loaded but carried no matching public `Person` record (private profile, or LinkedIn served an interstitial).
- Transport codes — timeout, block or network failure, with the underlying message in `details`.

You get a row explaining what happened for every URL you submitted, so a partial run is auditable rather than silently short.

### Cost and proxy policy

The actor uses direct HTTP only. It never starts residential or SERP proxy traffic. Blocks, rate limits, invalid URLs, and public pages without a matching profile record return an uncharged diagnostic row.

Only a genuine matching public profile triggers the `profile` event. The row is written to the dataset before the charge call.

### Empty input

Empty input returns exactly one clearly labeled `_sample: true` row without making a LinkedIn request. It is always uncharged.

### Pricing

**$0.90 per 1,000 profiles** ($0.0009 each), plus $0.001 each time a run starts — against the $1.00 to $1.99 per 1,000 charged by comparable URL-driven LinkedIn profile actors on the Apify Store. Flat rate: no volume tiers, no plan gates, and you are charged only for profiles actually returned.

### Billing

Two charges apply: a **$0.001 run-start fee** each time a run begins, and **$0.0009 per successfully parsed public profile**. Samples, diagnostics, duplicates, blocked look-ups and no-result runs **never incur the per-result fee** — a run that returns nothing costs only the $0.001 start fee. Because it is direct HTTP with no proxy, there is no proxy line on your bill either.

# Actor input Schema

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

Public URLs in the form https://www.linkedin.com/in/public-identifier/. Empty input returns one clearly labeled, uncharged sample row.

## `maxProfiles` (type: `integer`):

Maximum valid public profile URLs to request. Invalid or blocked URLs return free diagnostic rows.

## `requestTimeoutSecs` (type: `integer`):

Timeout for one public profile page request.

## Actor input object example

```json
{
  "profileUrls": [
    "https://www.linkedin.com/in/example-public-profile/"
  ],
  "maxProfiles": 10,
  "requestTimeoutSecs": 20
}
```

# Actor output Schema

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

One normalized row for each matching public profile. Sample and diagnostic rows are clearly labeled and never charged.

# 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 = {};

// Run the Actor and wait for it to finish
const run = await client.actor("dami_studio/linkedin-profiles-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 = {}

# Run the Actor and wait for it to finish
run = client.actor("dami_studio/linkedin-profiles-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 '{}' |
apify call dami_studio/linkedin-profiles-scraper --silent --output-dataset

```

## MCP server setup

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