# LinkedIn Company Employees API | No Login, No Cookies (`johnvc/linkedin-company-employees-api`) Actor

LinkedIn Company Employees API: give a company name or LinkedIn URL and get the people who work there, with name, title, location and profile URL. Each person is checked against their public profile. No login, no cookies. Filter by job title and location.

- **URL**: https://apify.com/johnvc/linkedin-company-employees-api.md
- **Developed by:** [John](https://apify.com/johnvc) (community)
- **Categories:** Lead generation, Social media
- **Stats:** 1 total users, 1 monthly users, 100.0% runs succeeded, 0 bookmarks
- **User rating**: No ratings yet

## Pricing

from $0.01 / 1,000 employee founds

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 Company Employees API

List the people who work at a company on LinkedIn, as clean JSON: name, job title, location and
profile URL, with each person checked against their public profile to confirm they still work
there. Give it company names or LinkedIn company URLs. No LinkedIn account, no login and no
session cookie.

Built for the two jobs that need a list of who works where: prospecting (find the engineering
leaders, the finance team or the founders at your target accounts) and recruiting (map a
competitor's team before you start sourcing).

### 🧩 Part of the Alpha OSINT LinkedIn suite: no login, no cookies

Every Actor in the suite reads only what LinkedIn shows to a signed-out visitor, so none of them
can get your LinkedIn account restricted. They chain together:

| You want to | Use |
|---|---|
| List the people who work at a company | **LinkedIn Company Employees API** (this Actor) |
| Find people by name, job title, school or location | [LinkedIn People Search API](https://apify.com/johnvc/linkedin-people-search-api?fpr=9n7kx3) |
| Turn profile URLs into full structured profiles | [LinkedIn Profile API](https://apify.com/johnvc/linkedin-profile-api?fpr=9n7kx3) |
| Enrich the company: industry, size, headquarters, specialties | [LinkedIn Company API](https://apify.com/johnvc/linkedin-company-api?fpr=9n7kx3) |
| See what the company is hiring for | [LinkedIn Jobs API](https://apify.com/johnvc/linkedin-jobs-api?fpr=9n7kx3) |
| Read what the company and its people post | [LinkedIn Posts API](https://apify.com/johnvc/linkedin-posts-api?fpr=9n7kx3) |

### What the LinkedIn Company Employees API returns

One row per person, per company:

- **Who they are:** full name, headline, location, profile URL and profile slug.
- **Their role:** current job title and employer. For a verified person, the title of the role
  at the company you asked about.
- **Whether they still work there:** `verified` plus a `matchReason` that says how it was
  decided (see below).
- **The full public profile, for verified people:** about text, every position with dates,
  education, follower and connection counts, photo and LinkedIn member id.
- **Where each person came from:** `foundBy` is the exact public search that found them, so a
  list can be audited and reproduced.

Each run also writes a `RUN_SUMMARY` record with, per company, how many people were found and
verified, LinkedIn's own employee count for the company, and the coverage ratio between the two.

### How verification works

Search results are a starting point, not proof: a person who left a company years ago still
mentions it on their profile. With `verifyEmployment` on (the default), the API opens each
person's public profile and looks for a **current** role at the company:

| `matchReason` | Meaning | `verified` |
|---|---|---|
| `current-position` | A current role on the profile links this company's LinkedIn page | `true` |
| `current-company` | The profile's current employer links this company's page | `true` |
| `company-name` | No link, but the current employer's name matches the company's closely. A weaker match | `true` |
| `profile-unavailable` | The public profile could not be opened, and the search result lists the company as the person's experience, so this is a search-level row | `null` |
| `search-experience` | Not opened, but the search result lists the company as the person's experience. Used with `verifyEmployment` off, and for the strongest leftovers when a company's open limit is reached | `null` |

Profiles are opened in order of evidence: people listed on the company page first, then people
whose search result reads "Experience: <company>", then everyone else whose result names the
company. With `verifyEmployment` off, only people whose result lists the company as their
experience are returned; weaker matches are too noisy to sell unverified and are left out, free.
A person whose profile opened but shows no current role here is never returned and never
charged: the API has proved they do not work there. The run summary counts them as
`openedNotEmployed`. A profile that has been deleted is dropped.

Some company names are also job titles or common phrases ("AI Engineer", say), and the search then
matches people who merely hold that title. Once 20 profiles have been read for a company and fewer
than 10% of them work there, the API stops opening profiles for that company, returns the verified
people plus the unopened people whose result lists the company as their experience, and records
`stoppedReason: "low match rate"`. Use the company's LinkedIn URL and `titleKeywords` for such
names. A role that links a different company page with the same name (two companies called
"Atlas", say) never counts as a match.

### Coverage: what to expect

This API finds people through public search results for `site:linkedin.com/in` pages, then checks
them against LinkedIn. A search returns only about ten people, so the number of searches scales
with the company's size on LinkedIn: about a dozen for a company of up to 500 people (the company name plus ten role slices), and about 30 slices (roles such as engineer, account executive or head of, plus office
cities) above that. Only people whose search result names the company are opened and checked. It can only find the people
search engines have indexed, so it will rarely return a company's full headcount:

- **Smaller companies get the highest coverage.** For a company with a few dozen people, most of
  the team is usually indexed.
- **Large companies return a slice.** For a company with tens of thousands of employees, expect
  hundreds, not thousands. Narrow with `titleKeywords` and `locations` to get the slice you need,
  or raise `maxSearchQueriesPerCompany`.
- **Every run reports its own coverage** against the employee count LinkedIn shows on the
  company page, in the run log and in `RUN_SUMMARY`, so you never have to guess.

There are no LinkedIn-internal filters: seniority codes, function codes, years in role and
similar Sales Navigator filters are not available to a signed-out visitor. Use `titleKeywords`
for seniority and function instead ("director", "vp", "head of", "engineer").

### Use cases

- **Account-based prospecting:** list the sales, marketing or engineering leaders at each of
  your 50 target accounts in one run, then hand the profile URLs to your outreach tool.
- **Recruiting and talent mapping:** see who is on a competitor's data team, in which cities,
  and where they worked before.
- **Org charts and market maps:** count how many engineers, designers or recruiters a company
  shows publicly, and how that changes month to month on a schedule.
- **Investment research:** check the founding team and senior hires of a startup before a call.
- **CRM hygiene:** confirm that the contacts you have at an account still work there.

### Input

| Field | Type | Default | What it does |
|---|---|---|---|
| `companies` | array, required | | LinkedIn company URLs or company names, up to 50 per run |
| `titleKeywords` | array | empty | Narrow to these job titles. Each one is also its own search. Empty searches built-in role slices, more for larger companies |
| `locations` | array | empty | Return only people in these cities, regions or countries. Every search names the place, and a person whose public profile shows a different location is left out. Use the place name as LinkedIn writes it (Dublin, London, United States). Empty searches everywhere |
| `maxResultsPerCompany` | integer | 100 | People to return per company, 1 to 1,000 |
| `verifyEmployment` | boolean | true | Open each profile and confirm a current role. Off returns a faster, search-level list |
| `maxSearchQueriesPerCompany` | integer | 40 | Cap on search slices per company (1 to 100). More slices reach more of a large company |
| `maxAgeDays` | integer | per record type | Serve results fetched within this many days from the shared cache. 0 always fetches fresh |

Example input, the engineering and recruiting teams at two companies in Dublin:

```json
{
  "companies": ["https://www.linkedin.com/company/stripe", "Intercom"],
  "titleKeywords": ["engineer", "recruiter"],
  "locations": ["Dublin"],
  "maxResultsPerCompany": 50,
  "verifyEmployment": true
}
```

### Example output

A verified row (about text and work history shortened). `positions` and a page-read `currentTitle` appear only on profiles whose experience section LinkedIn shows to signed-out visitors; for most people it hides job titles, and `headline` and `currentTitle` then come from the person's search result headline:

```json
{
  "result_type": "employee",
  "companyName": "Microsoft",
  "companySlug": "microsoft",
  "companyUrl": "https://www.linkedin.com/company/microsoft",
  "profileUrl": "https://www.linkedin.com/in/satyanadella",
  "slug": "satyanadella",
  "fullName": "Satya Nadella",
  "headline": "Chairman and CEO at Microsoft",
  "location": "Redmond, Washington, United States",
  "currentTitle": "Chairman and CEO",
  "currentCompany": "Microsoft",
  "verified": true,
  "matchReason": "current-position",
  "foundBy": "site:linkedin.com/in \"Microsoft\" founder OR ceo",
  "fromCache": false,
  "fetched_at": "2026-10-02T09:15:00Z",
  "about": "As chairman and CEO of Microsoft, I define my mission and that of my company as empowering every person...",
  "positions": [
    {
      "title": "Chairman and CEO",
      "companyName": "Microsoft",
      "companyUrl": "https://www.linkedin.com/company/microsoft",
      "startDate": "Feb 2014",
      "endDate": "Present",
      "location": "Greater Seattle Area",
      "isCurrent": true
    }
  ],
  "education": [
    {
      "organizationName": "The University of Chicago Booth School of Business",
      "organizationUrl": "https://www.linkedin.com/school/universityofchicagoboothschoolofbusiness/",
      "startDate": "1994",
      "endDate": "1996"
    }
  ],
  "followers": 12196634,
  "connections": 500,
  "memberId": "19186432"
}
```

A company that cannot be matched produces an error row. It is never charged as a person; like
every stored row, it carries only the small dataset-item event:

```json
{
  "result_type": "error",
  "error_type": "CompanyNotFound",
  "error_message": "No LinkedIn company page matches this name. Try the company's LinkedIn URL instead.",
  "requestedCompany": "Example Company That Does Not Exist"
}
```

Not available from public pages: email addresses, phone numbers, and anything LinkedIn shows only
to signed-in members. Connection counts above 500 show as 500, LinkedIn's public cap.

### Pricing: pay per person, never per search

Two pay-per-event charges, and you pay one or the other for a person, never both:

- **Employee verified:** the person's public profile confirms a current role at the company,
  with their full public profile in the row.
- **Employee found:** a person delivered from search alone, because checks were off, a
  per-company limit was reached, or the profile could not be opened. Only people whose search
  result lists the company as their experience. A person whose profile shows they work
  elsewhere is never returned or charged.

Each run also carries two small platform events: one Actor start, and one dataset item for every
row stored, error rows included. Search requests and profile page reads are never charged by
themselves, and people dropped as former employees produce no row and no charge. Current rates
are on the Pricing tab of the Store page. Set a maximum cost per run and the API stops cleanly
when it is reached.

### Freshness and the shared cache

Results may be served from a shared cache when the same profile, company page or search was
fetched recently: up to 7 days for profiles, 30 days for company pages and 1 day for searches.
Cached rows carry `fromCache: true` and the original `fetched_at`, and are charged the same as
fresh ones. Set `maxAgeDays` to 0 to always fetch fresh, or to a smaller number to tighten the
window.

Other runs add to the shared cache all the time, so two cached runs of the same company a few minutes apart can differ by a few people. A person whose own headline says they have left ("Former ...", "Retired") is not returned, even when their profile still lists the company.

### Use the LinkedIn Company Employees API from Claude with MCP

Add this API as a tool in [Claude Code](https://claude.ai/referral/uIlpa7nPLg) (free trial),
[Claude Cowork](https://claude.ai/referral/uIlpa7nPLg) (free trial), or any other MCP client
through the hosted Apify MCP server:

```
https://mcp.apify.com/?tools=actors,docs,johnvc/linkedin-company-employees-api
```

Here `actors` and `docs` are the standard tool categories, and the third entry is this API. Then
ask in plain language, for example "list the data engineers at Databricks in San Francisco and
tell me which of them worked at Google before".

Apify's MCP integration docs: https://docs.apify.com/platform/integrations/mcp

https://www.youtube.com/watch?v=jREWahDGhJM

### 💸 Pay per run with crypto (x402)

The LinkedIn Company Employees API supports agentic payments via the [x402 protocol](https://docs.apify.com/platform/integrations/x402).
AI agents and MCP clients can pay for runs in USDC (on Base) with no Apify account or API token needed:
point your agent at the [Apify MCP server](https://mcp.apify.com/?tools=actors,docs,johnvc/linkedin-company-employees-api) and it can
discover, pay for, and run this Actor autonomously. Read the
[Apify x402 announcement](https://apify.com/change-log/pay-for-apify-actors-with-x402?fpr=9n7kx3) for details.

### Integrations and API access

Start runs from the Apify API, the Python and JavaScript clients or the CLI, and send results on
with Apify integrations to Google Sheets, HubSpot via Make or Zapier, n8n, Slack, Airtable and
webhooks. Every run writes a dataset you can download as JSON, CSV or Excel. A monthly schedule
on the same input is the simple way to watch a team grow or shrink.

### How to get started

1. Open [LinkedIn Company Employees API on Apify Store](https://apify.com/johnvc/linkedin-company-employees-api?fpr=9n7kx3).
2. Add one or more companies, as LinkedIn URLs or names.
3. Optionally narrow with job titles and locations.
4. Set `maxResultsPerCompany`, and keep `verifyEmployment` on for confirmed, full rows.
5. Run it, then download the dataset or open the `Employees` view.

[View on Apify Store](https://apify.com/johnvc/linkedin-company-employees-api?fpr=9n7kx3)

### 🔗 Related Tools

- [LinkedIn Company API](https://apify.com/johnvc/linkedin-company-api?fpr=9n7kx3) - firmographics for the companies you are mapping: size, industry, headquarters and follower count.
- [LinkedIn Profile API](https://apify.com/johnvc/linkedin-profile-api?fpr=9n7kx3) - full public profiles in bulk when you already have the profile URLs.
- [LinkedIn People Search API](https://apify.com/johnvc/linkedin-people-search-api?fpr=9n7kx3) - find people by name, job title, school or location across every company.
- [LinkedIn Jobs API](https://apify.com/johnvc/linkedin-jobs-api?fpr=9n7kx3) - the roles a company is hiring for right now.

### Frequently asked questions

#### How do I get a list of employees of a company from LinkedIn?

Add the company's LinkedIn URL or name to `companies` and run. The API searches for the
company's people, opens each public profile, and returns the ones whose profile shows a current
role there, with title, location and work history.

#### Do I need a LinkedIn account or cookie?

No. The API reads only LinkedIn's public pages, the same ones a signed-out visitor sees. It never
asks for your account, password or session cookie, so it cannot get your account restricted.

#### Why did I get fewer people than the company's employee count?

The API can only find people whose public profiles appear in search results, which is a fraction
of a large company. Check `coverage` in `RUN_SUMMARY`. To reach more people at a big company, add
`titleKeywords` and `locations`: each one adds searches that surface people the plain company
search ranks too deep to reach.

#### What is the difference between verified and found?

A verified person's public profile shows a current role at the company. A found person comes
from search results without that confirmation, either because checks were off or because their
profile could not be opened, and only when the search result lists the company as their
experience. People whose profile shows they have moved on are never returned and never charged.

#### Can I filter by seniority or department like Sales Navigator?

Not with LinkedIn's internal filters, which are not public. Use `titleKeywords` instead: words
like "director", "vp", "head of", "engineer" or "recruiter" narrow the list and add searches
for those roles.

#### Does it return email addresses or phone numbers?

No. Contact details are not on LinkedIn's public pages, and this API returns only public data.

#### What does a company name do differently from a URL?

A URL is exact. A name is matched to its LinkedIn company page through a public search and a
similarity score that also weighs follower counts, which keeps "Anthropic" from matching a
same-named fund. If a name cannot be matched with confidence you get a `CompanyNotFound` error
row, with no person charge, and can retry with the URL.

#### Can I run it on a schedule?

Yes. Save the input as a task and schedule it monthly. Compare runs by `slug` to see who joined
and who left.

***

### 🌐 About Alpha OSINT

This Actor is part of [Alpha OSINT](https://www.alphaosint.com), toolset of financial and operations data sources and APIs.
For support or requests for this actor, please start a ticket [directly on our support page](https://apify.com/johnvc/linkedin-company-employees-api/issues/open?fpr=9n7kx3).

Last Updated: 2026.10.02

# Actor input Schema

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

Companies to list employees for: LinkedIn company URLs (https://www.linkedin.com/company/microsoft) or company names (Microsoft). A URL is exact; a name is matched to its LinkedIn company page first. Up to 50 per run.

## `titleKeywords` (type: `array`):

Return only people whose public page mentions one of these job titles, for example engineer, sales or head of marketing. Each keyword is also its own search, which reaches people a plain company search ranks too deep to find. Leave empty to search built-in role slices instead, more of them for larger companies.

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

Return only people in these cities, regions or countries, for example Dublin or United States. Every search names the place, and people whose public profile shows a different location are left out. Leave empty to search everywhere.

## `maxResultsPerCompany` (type: `integer`):

Stop after delivering this many people for each company. You are charged only for people actually returned. Large companies rarely return their full headcount: the list is limited to what public search results show.

## `verifyEmployment` (type: `boolean`):

Open each person's public LinkedIn profile and confirm a current role at the company, adding their title, location, work history, education and photo. Turn off for a faster, cheaper list with search-level data only (name, headline, profile URL): only people whose search result lists the company as their experience are returned, and some may have left since.

## `maxSearchQueriesPerCompany` (type: `integer`):

Cap on the public searches run per company to discover people. Each search slice (a role, a title, a location) returns about ten people, so more slices reach more of a large company. Lower it for a quicker run. The run also scales the slices down when its budget is small.

## `maxAgeDays` (type: `integer`):

Serve results fetched within this many days from the shared cache. 0 = always fetch fresh. Empty = the default for each record type.

## Actor input object example

```json
{
  "companies": [
    "https://www.linkedin.com/company/apify"
  ],
  "maxResultsPerCompany": 100,
  "verifyEmployment": true,
  "maxSearchQueriesPerCompany": 40
}
```

# Actor output Schema

## `allResults` (type: `string`):

Every dataset item from this run, including any error rows.

## `employees` (type: `string`):

Name, title, company, location, verification and profile URL for each person.

## `verification` (type: `string`):

How each person's current employment was decided and which search found them.

## `runSummary` (type: `string`):

Per company: people found and verified, LinkedIn's own employee count, the coverage ratio and the searches used.

# 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 = {
    "companies": [
        "https://www.linkedin.com/company/apify"
    ]
};

// Run the Actor and wait for it to finish
const run = await client.actor("johnvc/linkedin-company-employees-api").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 = { "companies": ["https://www.linkedin.com/company/apify"] }

# Run the Actor and wait for it to finish
run = client.actor("johnvc/linkedin-company-employees-api").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 '{
  "companies": [
    "https://www.linkedin.com/company/apify"
  ]
}' |
apify call johnvc/linkedin-company-employees-api --silent --output-dataset

```

## MCP server setup

```json
{
    "mcpServers": {
        "apify": {
            "type": "http",
            "url": "https://mcp.apify.com/?tools=fetch-actor-details,johnvc/linkedin-company-employees-api"
        }
    }
}
```

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/3LQ1xGA8sKRIBTuxz/builds/jAK2XjKnkQQR8I2Oa/openapi.json
