# LinkedIn Company Employees Scraper ✅ No cookies 📧 (`scrapeforge/linkedin-company-employees`) Actor

Find the people who work at any LinkedIn company, with Sales Navigator filters, full profiles and email lookup. No cookies or account required.

- **URL**: https://apify.com/scrapeforge/linkedin-company-employees.md
- **Developed by:** [ScrapeForge](https://apify.com/scrapeforge) (community)
- **Categories:** Lead generation, Social media, Automation
- **Stats:** 2 total users, 1 monthly users, 100.0% runs succeeded, 0 bookmarks
- **User rating**: 5.00 out of 5 stars

## Pricing

from $4.00 / 1,000 short 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 Company Employees Scraper

Give it a LinkedIn company and get the people who work there — filtered the way Sales Navigator filters them, with full profiles and email lookup when you need them. No cookies, no LinkedIn account, no proxies of your own, and nothing about your session is ever involved.

It finds the whole staff, not the handful of names a public company page shows, and the people come back with their names attached rather than as the "LinkedIn Member" placeholders that a plain people-search returns.

### What it costs

| What you get | Price per 1,000 |
|---|---|
| **Search result** — name, profile URL, About text, location, current role and tenure | **$4** |
| **Full profile** — plus the whole work history, education, skills, certifications, languages, recommendations, follower counts | **$8** |
| **Full profile + likely emails** — plus every address that fits the company's mail domain, none of them confirmed | **$12** |
| **Full profile + verified email** — plus one address that was checked against the mail server and answered | **$18** |

Each search costs **$0.02** to start. One search covers up to 50 companies at once, so a run over one company and a run over fifty both pay it once — unless you ask for the companies to be searched separately, which is a search each.

You are charged for people that reach your dataset, and only for them. A person the filters exclude is never fetched. If the profile page cannot be read, the person is still stored, but as a search result and at the search-result price.

### How to use it

Paste one or more LinkedIn company URLs into **Companies** and run it:

```json
{
  "companies": ["https://www.linkedin.com/company/apify"],
  "profileScraperMode": "full",
  "maxItems": 100
}
```

Company names work too — `"Stripe"` instead of the URL. Each name is looked up first and the log reports which company it matched, so you can tell the company you meant from an agency with a similar name. That lookup is not charged.

#### Narrowing it down

Everything below is applied by LinkedIn before the results are counted, which means filtering makes a run **cheaper**, not more expensive:

```json
{
  "companies": ["https://www.linkedin.com/company/stripe"],
  "jobTitles": ["Engineering Manager", "Head of Engineering"],
  "seniorityLevelIds": ["220", "300", "310"],
  "locations": ["United Kingdom"],
  "yearsAtCurrentCompanyIds": ["1", "2"],
  "excludeCurrentJobTitles": ["Intern"],
  "profileScraperMode": "full-email-verified",
  "maxItems": 200
}
```

Locations are resolved through LinkedIn's own autocomplete, and the log says which place actually matched. This matters more than it sounds: on LinkedIn, "UK" matches **Ukraine**. Write "United Kingdom".

You can also filter by past job titles, schools, industry, job function, years of experience, company size and whether someone recently changed jobs — and exclude on most of the same.

#### Emails: the two options are different in kind

The cheaper email option returns the addresses that **fit the company's mail pattern**. For one person that is typically half a dozen candidates — `jakub@`, `jrajsky@`, `jakub.rajsky@` and so on — and not one of them has been confirmed to exist. Every row it produces is marked `emailStatus: "unverified_guess"`.

The verified option checks the mailbox and returns **the address that answered**, marked `emailStatus: "verified"` with a quality score. Usually exactly one. If nothing is found the row says `not_found` rather than quietly dropping the field.

Both are a search for an address, not a field copied off the profile — LinkedIn does not publish work emails. Neither is guaranteed to find anything.

#### Big companies

A single search hands over at most **2,500 people** — 100 pages of 25. That is LinkedIn's ceiling, not this Actor's, and no scraper gets past it in one query. For a company larger than that, run several searches split by location, job title, seniority or function, and the slices together cover the staff.

**Start from page** and **Pages to scrape** let you continue where a previous run stopped without paying again for the pages you already have.

### What you get

A full profile row, trimmed to the interesting parts:

```json
{
  "id": "ACoAAAYiG-8Bn3XJJeo_u5XmJz-PeB9oLx31YHM",
  "publicIdentifier": "jakub-rajsky-a135632a",
  "linkedinUrl": "https://www.linkedin.com/in/jakub-rajsky-a135632a",
  "firstName": "Jakub",
  "lastName": "Rajský",
  "headline": "Web and Product Analytics | MarTech | Data Engineering & Automation at Apify",
  "about": "My guilty pleasure from the time when I was a kid...",
  "email": "jakub.rajsky@apify.com",
  "emailStatus": "verified",
  "emails": [
    { "email": "jakub.rajsky@apify.com", "status": "valid", "deliverable": true, "qualityScore": 90 }
  ],
  "location": {
    "linkedinText": "Prague, Czechia",
    "countryCode": "CZ",
    "parsed": { "city": "Prague", "state": "Praha, Hlavní město", "country": "Czechia", "countryCode": "CZ" }
  },
  "verified": true,
  "openToWork": false,
  "hiring": false,
  "premium": false,
  "registeredAt": "2011-01-29T18:49:25.945Z",
  "connectionsCount": 1044,
  "followerCount": 1044,
  "currentPosition": [
    {
      "position": "Senior Web and Product Analyst",
      "companyName": "Apify",
      "companyId": "10608457",
      "companyLinkedinUrl": "https://www.linkedin.com/company/apify/",
      "employmentType": "Full-time",
      "workplaceType": "Hybrid",
      "duration": "2 yrs 7 mos",
      "startDate": { "month": "Feb", "year": 2024, "text": "Feb 2024" },
      "endDate": { "text": "Present" },
      "skills": ["SQL", "Snowflake", "Google Analytics 4"]
    }
  ],
  "experience": [ "...ten roles, each with company, dates, description and skills..." ],
  "education": [
    {
      "schoolName": "Prague University of Economics and Business",
      "degree": "Master's degree programme",
      "fieldOfStudy": "Information management",
      "period": "2012 - 2015"
    }
  ],
  "skills": [{ "name": "SQL", "positions": ["Senior Web and Product Analyst at Apify"] }],
  "languages": [{ "name": "Czech", "proficiency": "Native or bilingual proficiency" }],
  "certifications": [{ "title": "Python Programming Essentials", "issuedBy": "Coursera" }],
  "receivedRecommendations": [{ "givenBy": "Jan Vošický", "givenAt": "August 28, 2013" }],
  "moreProfiles": [{ "firstName": "Martina", "lastName": "Gelnerová", "position": "Senior Data Analyst at Apify" }],
  "searchedCompany": "https://www.linkedin.com/company/apify",
  "profileDepth": "profile"
}
```

Also on every row: `projects`, `publications`, `courses`, `patents`, `honorsAndAwards`, `volunteering`, `organizations`, `causes`, `topSkills`, `coverPhoto`, `influencer`, `creator` and `memorialized`.

A **search result** row carries the same field names with the deeper ones absent, so a short run and a full run export to the same columns. `profileDepth` tells you which of the two a row is.

Export as JSON, CSV, Excel or XML from the Storage tab, or pull it from the API.

### What to keep in mind

- **Measured against the live source, not assumed.** The 2,500-per-search ceiling, the 25-per-page rate and the shape of every field above come from real responses, not from documentation.
- **`moreProfiles` is free extra reach.** LinkedIn suggests people alongside each profile, and at a company they are usually more colleagues. They arrive with a full profile at no extra cost.
- **The dataset mirrors the search.** If the source serves the same person on two pages, you get two rows. Nothing is silently deduplicated, because the alternative is a run that quietly drops people it should have kept.
- **Set a maximum charge** on the run to cap what a single run can spend. The Actor stops when it reaches it and reports what it stored.
- **Search results carry the member-id form of the profile URL** (`/in/ACwAAA...`). It resolves in a browser and identifies the person, but it is not the readable handle; the full profile modes replace it with the real one.

### No cookies, no accounts

You do not supply a LinkedIn session, and none of your credentials are involved at any point. There is no risk to a LinkedIn account of yours, because none is used. Only data that LinkedIn shows publicly is collected.

Emails are discovered by searching for them, not read from a profile.

### Support

Something wrong, or a filter you need that is not here? Open an issue on the Issues tab and it gets read.

# Actor input Schema

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

LinkedIn company URLs, or plain company names. A URL goes straight to the search; a name is looked up first and the log reports which company it matched, so you can tell "Apify" from an agency with the same name. Company lookups are not charged.

## `profileScraperMode` (type: `string`):

The search result already gives you the name, the profile URL, the About text, the location and the current role with its tenure — enough to qualify a lead. The full profile is one extra request per person, and adds the whole work history, education, skills, certifications, languages, recommendations and follower counts. The two email options differ in kind, not degree: likely addresses are the permutations that fit the company's mail domain, none of them confirmed, and you will normally get several per person; a verified email is a single address that was checked against the mail server and answered.

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

Maximum number of people to store across the whole run. When the run covers several companies, the limit is shared between them, so no single company spends it all. Use 0 for unlimited.

## `companyBatchMode` (type: `string`):

All at once puts every company into one search: one start fee, one shared ceiling of 2,500 results, and the larger companies crowd out the smaller ones. One by one gives each company its own search, its own ceiling and its own per-company limit, and costs one start fee each. With one or two companies the choice makes no difference.

## `maxItemsPerCompany` (type: `integer`):

A ceiling for each company on its own. Only used when the companies are searched one by one. Use 0 for no per-company ceiling.

## `searchQuery` (type: `string`):

A free-text search across the people in the company — a name, a skill, a team. LinkedIn's own search operators work here.

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

Keep only people whose current title matches one of these.

## `pastJobTitles` (type: `array`):

Keep only people who held one of these titles at some point.

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

Cities, regions or countries. Each one is resolved through LinkedIn's own autocomplete and the log reports which place was matched — "UK" matches Ukraine there, not the United Kingdom, and you should know that before reading the results. Resolving a place is not charged.

## `schools` (type: `array`):

Keep only alumni of these schools. Names or LinkedIn school URLs.

## `seniorityLevelIds` (type: `array`):

LinkedIn's own seniority bands. Pick any combination.

## `functionIds` (type: `array`):

The department someone works in, as LinkedIn classifies it. Pick any combination.

## `yearsOfExperienceIds` (type: `array`):

Total working experience. Pick any combination.

## `yearsAtCurrentCompanyIds` (type: `array`):

How long they have been at this company. Useful for finding people who just joined, or the ones who have been there long enough to decide things.

## `industryIds` (type: `array`):

LinkedIn industry codes, if you know them. "4" is Software Development.

## `companyHeadcount` (type: `array`):

Only relevant when the search spans several companies, or when you filter by past companies.

## `recentlyChangedJobs` (type: `boolean`):

Only people who started a new role recently — the window when a new decision-maker is still choosing their tools.

## `excludeCurrentJobTitles` (type: `array`):

Drop people whose current title matches one of these.

## `excludePastJobTitles` (type: `array`):

Drop people who held one of these titles at some point.

## `excludeLocations` (type: `array`):

Drop people in these cities, regions or countries.

## `excludePastCompanies` (type: `array`):

LinkedIn company URLs. Drops anyone who used to work at one of them.

## `excludeSchools` (type: `array`):

Drop alumni of these schools.

## `excludeIndustryIds` (type: `array`):

Drop people working in these LinkedIn industries.

## `excludeSeniorityLevelIds` (type: `array`):

Drop these seniority bands — the quickest way to leave out interns and junior staff.

## `excludeFunctionIds` (type: `array`):

Drop these departments.

## `startPage` (type: `integer`):

The search serves 25 people per page. Start at page 3 to skip the first 50 — useful for continuing a run that stopped, without paying for the pages you already have.

## `takePages` (type: `integer`):

How many pages to take, counting from the start page. Use 0 to keep going until the search runs out or a limit stops it.

## Actor input object example

```json
{
  "companies": [
    "https://www.linkedin.com/company/apify",
    "Stripe"
  ],
  "profileScraperMode": "full",
  "maxItems": 100,
  "companyBatchMode": "all_at_once",
  "maxItemsPerCompany": 0,
  "searchQuery": "growth marketing",
  "jobTitles": [
    "Software Engineer",
    "Head of Sales"
  ],
  "pastJobTitles": [
    "Founder"
  ],
  "locations": [
    "United Kingdom",
    "New York, United States"
  ],
  "schools": [
    "Stanford University"
  ],
  "industryIds": [
    "4"
  ],
  "recentlyChangedJobs": false,
  "excludeCurrentJobTitles": [
    "Intern"
  ],
  "startPage": 1,
  "takePages": 0
}
```

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

// Run the Actor and wait for it to finish
const run = await client.actor("scrapeforge/linkedin-company-employees").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("scrapeforge/linkedin-company-employees").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 scrapeforge/linkedin-company-employees --silent --output-dataset

```

## MCP server setup

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

```

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/5wTyvVXgMjpKqChYx/builds/Kw7AVNgbvFfN4UQ8K/openapi.json
