# People Search Scraper for LinkedIn - By Job Title (`scrapesage/linkedin-people-search-scraper`) Actor

Find people on LinkedIn by job title without a company list and without a login. Searches every way a role is written, opens each profile to confirm who they are, then filters by real location, employer and seniority.

- **URL**: https://apify.com/scrapesage/linkedin-people-search-scraper.md
- **Developed by:** [Scrape Sage](https://apify.com/scrapesage) (community)
- **Categories:** Lead generation, Social media, Agents
- **Stats:** 2 total users, 1 monthly users, 100.0% runs succeeded, 0 bookmarks
- **User rating**: No ratings yet

## Pricing

$7.00 / 1,000 person founds

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

## People Search Scraper for LinkedIn - By Job Title

**Tell it a job title, get the people who hold it.** No company list, no login, no cookies. Every person is looked up on their own public profile before you get them, and the location, employer and seniority filters run on that profile - not on the search text.

### The two things that make this work

**1. One role is written four different ways, so it searches all of them.** Ask for "Head of Marketing" and it also looks for VP Marketing, Marketing Director and CMO. That is where the volume comes from: a single phrasing returns roughly 20 people, and eight variants returned **113 unique people** in testing, with almost no overlap between them. Turn `expandTitleVariants` off if you want one exact wording.

**2. Location is a filter, not a search term.** This matters more than it sounds. Putting a city into the search query looks sensible and produces junk - measured at **6% on-target** (a "Mayor of London" matches a search for growth leaders in London), because the city word matches company addresses, office lists and page furniture. So this actor searches the title only (**83% on-target**), opens each profile, and then keeps the people whose *own profile* says they are where you asked.

### Input

| Field | What it does |
|---|---|
| `jobTitles` | The roles you want. Common titles work best. |
| `expandTitleVariants` | Also search equivalent phrasings of the same role (default on) |
| `extraKeywords` | Optional context words like "SaaS" or "fintech" - more reach, less precision |
| `locations` | Keep only people whose profile says they are there |
| `companies` | Keep only people at these employers |
| `seniorityLevels` | Owner/C-Level, VP/Director, Manager, Senior, Individual Contributor, Entry |
| `verifyProfiles` | Open each profile to confirm identity and collect the filter fields (default on) |
| `includeUnverified` | Also return people whose public profile is switched off |
| `maxPerTitle` / `maxResults` | Cap per title, and the total |

### Output

```json
{
  "type": "person",
  "fullName": "Benjamin Braun",
  "firstName": "Benjamin",
  "lastName": "Braun",
  "jobTitle": "Chief Marketing Officer",
  "seniorityLevel": "Owner/C-Level",
  "department": "Executive",
  "currentCompany": "Samsung Electronics",
  "currentCompanyUrl": "https://www.linkedin.com/company/samsung-electronics",
  "headline": "CMO Samsung Europe",
  "profileUrl": "https://www.linkedin.com/in/benjaminbraun",
  "locationName": "London, England, United Kingdom",
  "city": "London",
  "country": "United Kingdom",
  "followerCount": 12480,
  "connectionCountText": "500+",
  "education": "INSEAD",
  "searchedTitle": "Head of Marketing",
  "matchedVariant": "Chief Marketing Officer",
  "titleMatchesSearch": true,
  "publicProfileAvailable": true,
  "leadScore": 84,
  "scrapedAt": "2026-08-07T06:20:00.000Z"
}
```

`matchedVariant` tells you which phrasing found the person and `titleMatchesSearch` says whether their real title actually matches what you asked for - so you can keep only the exact hits, or keep the wider net, without guessing.

### What this actor is NOT

Honesty about depth, because it decides whether this is the right tool:

- **It is a targeted search, not a database dump.** Expect tens of people per title, not thousands. Depth at source is limited: extra result pages return nothing new, which is why title variants rather than pagination supply the volume.
- **If you already know the companies, use the other one.** [Company Employees Scraper for LinkedIn](https://apify.com/scrapesage/linkedin-company-employees-scraper) is the better tool when you have an account list and want everyone inside those companies - it anchors on the company and goes far deeper per company than a title search can.
- **Some members switch their public profile off.** Their profile answers 999 to every logged-out request, permanently. They are dropped by default, or returned with `publicProfileAvailable: false` if you switch `includeUnverified` on.
- **Job titles are not always public.** LinkedIn publishes a title to logged-out visitors only when the member's headline is public - a title-anchored search naturally favours those people, which is why title coverage here is high, but it is not universal.
- **Never returned:** private profiles, connection graphs, email addresses or phone numbers.

### Pricing

Pay-per-event: **$0.005 per person**. Runs that find nobody charge nothing, and every finished run tells you what to change.

### Use with AI assistants (MCP)

Works as a tool in any MCP-compatible assistant through the [Apify MCP server](https://docs.apify.com/platform/integrations/mcp) - ask your agent to "find heads of marketing in the UK" and it can call this actor directly.

### Agent-ready: autonomous payments (x402 & Skyfire)

This actor is **agent-ready** — AI agents can discover it, run it, and **pay for it autonomously**, with no Apify account and no human in the loop. It uses [pay-per-event](https://docs.apify.com/platform/actors/publishing/monetize/pay-per-event) pricing and [limited permissions](https://docs.apify.com/platform/actors/development/permissions), so it qualifies for Apify's agentic-payment standards:

- **[x402](https://docs.apify.com/platform/integrations/x402)** — an open, HTTP-native payment protocol. Agents pay per run in USDC on the Base network directly through the [Apify MCP server](https://docs.apify.com/platform/integrations/mcp) — no account, no API key.
- **[Skyfire](https://docs.apify.com/platform/integrations/skyfire)** — agent-to-service payments for fully autonomous AI-agent workflows.

Building an AI agent, MCP tool, or autonomous data pipeline? This scraper is ready to plug in and pay as it goes.

### Legal

This actor reads only what LinkedIn publishes to logged-out visitors. It does not log in, use cookies or session tokens, or reach private profiles. Names, roles and employers are business contact information, but they relate to identifiable people: if you are in the EU or UK you are the data controller for what you do with the output, so have a lawful basis (usually legitimate interest for B2B prospecting) and honour deletion requests. Do not use this output for spam.

This actor is not affiliated with, endorsed by, or sponsored by LinkedIn Corporation. LinkedIn is a trademark of LinkedIn Corporation.

# Actor input Schema

## `jobTitles` (type: `array`):

The roles you want, e.g. "Head of Marketing", "Account Executive", "CFO". Common titles work best. Each title is searched separately.

## `expandTitleVariants` (type: `boolean`):

Also search the equivalent ways the same role is written - "Head of Marketing" additionally finds VP Marketing, Marketing Director and CMO. This is where most of the volume comes from: a single phrasing returns roughly 20 people, eight variants returned 113 in testing. Turn it off if you want that exact wording only.

## `extraKeywords` (type: `array`):

Optional words that must also appear, e.g. "SaaS", "B2B", "fintech". These add reach but are less precise than the title itself, so they are searched after the title variants.

## `locations` (type: `array`):

Keep only people whose PROFILE says they are in one of these places, e.g. "London", "United States". Matched against the person's own location field after their profile is opened - deliberately not folded into the search text, because putting a city in the query pulls in anyone whose page happens to mention it.

## `companies` (type: `array`):

Keep only people whose current employer matches one of these. Leave empty for any company. If you already know the companies and want everyone inside them, the Company Employees Scraper for LinkedIn is the better tool.

## `seniorityLevels` (type: `array`):

Keep only these seniority levels, derived from each person's job title.

## `verifyProfiles` (type: `boolean`):

Open each person's public profile to confirm who they are and to collect location, current company, followers and education. This is also what the Locations, Companies and Seniority filters run on - with it off, those filters cannot be applied.

## `requireTitleMatch` (type: `boolean`):

Only return people whose real title actually matches what you searched for - including the equivalent phrasings, so searching "Head of Marketing" still keeps a CMO. Turn it off to see everyone the search surfaced, on-title or not; each row carries titleMatchesSearch either way.

## `includeUnverified` (type: `boolean`):

Also return people whose public profile could not be opened - some members switch public profile visibility off entirely. They arrive with publicProfileAvailable false and only search-page fields.

## `maxPerTitle` (type: `integer`):

Cap per title, so one title cannot consume the whole run.

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

Total cap across every title. Set 0 for no limit (explicit opt-in).

## `searchPages` (type: `integer`):

How deep to page each query. Depth is limited at source - extra pages usually return nothing new, which is why title variants rather than pagination provide the volume.

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

How many profiles to open in parallel.

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

LinkedIn needs residential proxies for reliable logged-out access. Keep the default.

## Actor input object example

```json
{
  "jobTitles": [
    "Head of Marketing",
    "VP Sales"
  ],
  "expandTitleVariants": true,
  "extraKeywords": [
    "SaaS"
  ],
  "locations": [
    "London"
  ],
  "companies": [],
  "seniorityLevels": [],
  "verifyProfiles": true,
  "requireTitleMatch": true,
  "includeUnverified": false,
  "maxPerTitle": 50,
  "maxResults": 100,
  "searchPages": 1,
  "maxConcurrency": 6,
  "proxyConfiguration": {
    "useApifyProxy": true,
    "apifyProxyGroups": [
      "RESIDENTIAL"
    ]
  }
}
```

# Actor output Schema

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

Every person found as a JSON item in the default dataset.

# 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 = {
    "jobTitles": [
        "Head of Marketing"
    ],
    "extraKeywords": [],
    "locations": [],
    "companies": [],
    "seniorityLevels": [],
    "proxyConfiguration": {
        "useApifyProxy": true,
        "apifyProxyGroups": [
            "RESIDENTIAL"
        ]
    }
};

// Run the Actor and wait for it to finish
const run = await client.actor("scrapesage/linkedin-people-search-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 = {
    "jobTitles": ["Head of Marketing"],
    "extraKeywords": [],
    "locations": [],
    "companies": [],
    "seniorityLevels": [],
    "proxyConfiguration": {
        "useApifyProxy": True,
        "apifyProxyGroups": ["RESIDENTIAL"],
    },
}

# Run the Actor and wait for it to finish
run = client.actor("scrapesage/linkedin-people-search-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 '{
  "jobTitles": [
    "Head of Marketing"
  ],
  "extraKeywords": [],
  "locations": [],
  "companies": [],
  "seniorityLevels": [],
  "proxyConfiguration": {
    "useApifyProxy": true,
    "apifyProxyGroups": [
      "RESIDENTIAL"
    ]
  }
}' |
apify call scrapesage/linkedin-people-search-scraper --silent --output-dataset

```

## MCP server setup

```json
{
    "mcpServers": {
        "apify": {
            "type": "http",
            "url": "https://mcp.apify.com/?tools=fetch-actor-details,scrapesage/linkedin-people-search-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/Yl1XahU7eXfy0L5Vq/builds/5GzppfFI1tSutFnSu/openapi.json
