# LinkedIn Company Employees Scraper - No Login (`automation_craft/linkedin-company-employees-scraper`) Actor

Get a LinkedIn company's employees from public search results by company URL or name, with no login or cookies. Name, headline, job title, location and public profile URL per person, each tied to the company with its evidence, plus coverage per company. Pay per employee and per company found.

- **URL**: https://apify.com/automation_craft/linkedin-company-employees-scraper.md
- **Developed by:** [Automation Craft](https://apify.com/automation_craft) (community)
- **Categories:** Lead generation, Social media, Business
- **Stats:** 10 total users, 8 monthly users, 100.0% runs succeeded, 0 bookmarks
- **User rating**: No ratings yet

## Pricing

from $1.40 / 1,000 employees

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 Scraper - No Login

**LinkedIn Company Employees Scraper** turns a LinkedIn company URL or a company name into a list of the people who work there: full name, headline, job title, location and the public LinkedIn profile URL, with no LinkedIn login, no cookies and no Sales Navigator seat. It finds the people in public Google results for LinkedIn profiles, and it delivers a person only when the result itself ties them to the company. Every row carries that evidence, and every company gets one row that says how many people were delivered against the head count LinkedIn shows.

You pay a small start fee per run, a price per delivered employee and a small fee per company where at least one employee was found. A company that does not exist, an ambiguous name, a duplicate and a company where nobody is found add nothing to the bill.

#### Why this one

- **Every row is tied to the company, and shows why.** A person is delivered only when LinkedIn's own current employer field in the search result equals the company's name and no other employer text in the result (a second field, a text Google cut) points elsewhere (`matchedOn: employer_field`), or their public profile page lists the company by its LinkedIn URL (`profile_page`). A headline that says "at Company" is the person's own free text and never delivers a row by itself: such a person is delivered only when the profile page confirms it. The search result the match rests on is in `evidence`. People from another company with a similar name and results that only mention the company are dropped and never billed.
- **A second proof where LinkedIn allows it.** With the profile check (on by default, included in the price) each person's public profile page is opened. When it lists the company among the current employers the row says `employerConfirmed: true`; when it lists other employers only, or none, the row is dropped. How often LinkedIn serves that page to a signed out visitor depends on the hour: in our night time test runs (UTC) 42 and 56 percent of delivered rows were confirmed this way, in afternoon and evening runs none. A row whose page could not be read rests on the search result and says so (`profileCheck: page_unavailable` or `check_paused`); such a row can be a person who left recently or is on a career break while LinkedIn's employer field still names the company (see "What this Actor does not do").
- **Coverage, in numbers.** The company row carries `employeesOnLinkedIn` (the head count on the company's public page), `employeesDelivered` and `coveragePercent`, the reason the search stopped and every drop reason with its count. Public search results show a slice of a company, never the full roster, and this Actor says how large the slice is.
- **Public profile URLs.** Every row has the `linkedin.com/in/...` URL, usable in any other tool.
- **The company is identified on LinkedIn first.** A URL is read from the public company page; a name goes through LinkedIn's own company lookup and is searched only when exactly one company matches it. An ambiguous name gets a free row listing the candidates, never a guess. A company that does not exist is never searched and costs nothing.
- **Scheduled runs return only new people.** Give a memory name and each run delivers and charges only people it has not delivered before, with `firstSeenAt`.

### Quick start

1. Paste companies into **Companies (LinkedIn URLs or names)**, one per line: `https://www.linkedin.com/company/stripe`, a URL with a tab or tracking, a regional URL such as `de.linkedin.com/company/zalando`, a company name such as `Datadog`, or a numeric LinkedIn company id (searched only when a public page confirms the id; the URL or the name is the safer input).
2. Set **Maximum employees per company** (the form starts at 10; the default for API calls is 100).
3. Optional: add **Job titles** (for example `CEO`, `CTO`, `Head of Marketing`) or **Locations** (for example `Berlin`) to get only matching people.
4. Click **Start**. Employee rows appear in the Dataset tab, then one company row per company and a run summary. Export JSON, CSV or Excel, or read them through the API.

### What you get

Fill rates measured on 378 employee rows of 24 companies of mixed size (3 to 30,135 employees on LinkedIn) delivered by two test runs of the final build on 2026-10-01 with the default settings. They are what public search results show, not what the Actor chooses to return. Those runs ran in an evening hour (UTC) in which LinkedIn served no public profile page, so for the fields that come from the profile page the table gives a range: from zero (those runs) to the share measured in a night run of an earlier build (421 rows, 42 percent of the pages read).

| Field | What it is | Filled |
|---|---|---|
| `fullName` | The person's name as the search result shows it | 100% |
| `firstName`, `lastName` | A simple split of the name; `lastName` is null when the name ends in an initial ("John W.") | 100%, 94% |
| `headline` | The person's own LinkedIn headline (Google cuts long ones) | 100% |
| `jobTitle` | Current title: Google's structured line for the profile when present, else the headline up to its "at Company" | 91% |
| `seniority`, `department`, `isDecisionMaker` | Read from the title by a fixed word table: `c_level`, `vp`, `director`, `head`, `manager`, `senior`, `entry`; `engineering`, `sales`, `marketing` and ten more; null when the title does not say | 57%, 66% |
| `location` | From the profile page when it could be read, else from the search result | 98% |
| `countryCode` | Two letter country code, from the profile page only | 0 to 43% |
| `profileUrl`, `publicIdentifier` | Public profile URL (`https://www.linkedin.com/in/...`) and its last part | 100% |
| `matchedOn` | `employer_field` or `profile_page`: how the row is tied to the company | 100% (all `employer_field` in the two runs; `profile_page` rows need a readable profile page) |
| `employerOnLinkedIn` | The employer text the match rests on | 100% |
| `employerConfirmed`, `profileCheck` | true when the public profile page lists the company among the current employers; null when the page could not be read (`page_unavailable`), the check was paused because LinkedIn refused every page (`check_paused`) or the check was off. A null row rests on LinkedIn's employer field alone, which can lag behind a departure | true on 0 to 56% |
| `currentEmployersOnProfile` | Current employers the profile page lists: name and LinkedIn URL | 0 to 42% |
| `followers` | Exact from the profile page when read, else Google's rounded figure ("1.8K+") | 96% |
| `connections`, `education` | From the search result's snippet when LinkedIn's description shows them | 26%, 25% |
| `schoolsOnProfile`, `languagesOnProfile` | Schools and languages the public profile page names | 0 to 32%, 0 to 20% |
| `evidence` | `resultTitle`, `richLine` (Google's structured line: location, title, company), `snippet`, the `query` that found the person, `layout`, and with a filter `matchedLocation` and `matchedTitle` (the text that satisfied it) | 100% |
| `firstSeenAt` | With a memory name: when this Actor first delivered the person under it. Not a hire date | with a memory |
| `companyName`, `companyLinkedinUrl`, `companyId`, `companyKey`, `position`, `scrapedAt` | The company the row belongs to and where it sits in your list | 100% |

The **company row** (`type: "company"`) carries `companyName`, `companyLinkedinUrl`, `companyId`, `industry`, `companySize`, `website`, `headquarters`, `followers`, `employeesOnLinkedIn`, `employeesDelivered`, `employeesConfirmed`, `coveragePercent`, `knownSkipped`, `stopReason` and a `search` object: `queriesAsked`, `queriesAnswered`, `queriesFailed`, `unrelatedPages`, `resultsRead`, `candidates`, `droppedOtherEmployer`, `droppedMentionOnly`, `droppedHeadlineUnconfirmed`, `droppedNotAProfile`, `droppedLinkUnresolved`, `droppedContradictedByProfile`, `droppedUnconfirmed`, `droppedByTitleFilter`, `droppedByLocationFilter`, `duplicates`, `confirmedOnProfileOnly`, `lastQueries`. Its `status` is `ok` when at least one employee was delivered. When the platform restarted the run while a company was being searched (a migration), its row carries `search.resumedAfterRestart: true`: `employeesDelivered` and `employeesConfirmed` are then counted from the dataset itself and are exact, the other search counters are what was on record and may miss the round that was in flight.

**Status rows** (`type: "status"`, always free) take the place of a company that was not searched: `not_found`, `ambiguous` (with `candidates`), `unresolved` (a numeric id LinkedIn's public pages do not confirm), `duplicate`, `invalid`, `school_page`, `login_required`, `blocked`, `skipped` (the run stopped before this company), `failed`. A company that was searched without a deliverable person gets a free company row with status `no_employees_found` or `search_unavailable`. The last row of every run is a `summary` with counters and billing totals.

#### How many people per company

Google shows one page of about ten profiles per query, so the Actor asks many different queries per company (the plain forms, then job functions, then cities the results themselves show) and stops a company when further queries stop bringing new people (`stopReason: "yield"`), when your cap is reached, or when its 80 queries are used. The rule behind "yield": after the first query, a company earns one more query for every 4 people delivered, plus up to two for result pages that turned out to be about something else. The rule is the same on every plan.

Measured on 2026-10-05: with a cap of 30, all 12 larger companies of a test run (1,000 to 30,000 employees on LinkedIn) reached the cap; 12 small companies (3 to 124 employees) returned between 0 and 39 people each in two runs. Measured on 2026-10-01 with a cap of 300 (an earlier build with the same search and the same rule), Stripe (16,622 employees on LinkedIn) returned 300 people from 47 billed Google requests in 14 minutes. That is the most we have measured for one company; the cap goes to 1,000. Companies whose name is a common word ("Linear", "Notion", "Miro") return fewer people per query, because many results belong to other companies or products with that word in their name and are dropped. `coveragePercent` on the company row is the honest figure for each company; it can exceed 100 for a very small page, because `employeesOnLinkedIn` counts only the members LinkedIn links to the page.

Example employee row (from a run of the final build on 2026-10-01, shortened; the name and the profile URL are replaced by placeholders, and the profile page was not readable in that hour):

```json
{
  "type": "employee",
  "companyName": "Stripe",
  "companyLinkedinUrl": "https://www.linkedin.com/company/stripe",
  "companyId": "2135371",
  "fullName": "Jane Example",
  "firstName": "Jane",
  "lastName": "Example",
  "headline": "Sales Development @ Stripe",
  "jobTitle": "Sales Development",
  "seniority": null,
  "department": "sales",
  "isDecisionMaker": null,
  "location": "Greater Chicago Area",
  "countryCode": null,
  "profileUrl": "https://www.linkedin.com/in/jane-example",
  "publicIdentifier": "jane-example",
  "matchedOn": "employer_field",
  "employerOnLinkedIn": "Stripe",
  "employerConfirmed": null,
  "profileCheck": "page_unavailable",
  "followers": 970,
  "evidence": {
    "resultTitle": "Jane Example - Sales Development @ Stripe",
    "richLine": ["Greater Chicago Area", "Sales Development", "Stripe"],
    "query": "site:linkedin.com/in intitle:\"Stripe\" sales",
    "layout": "modern"
  },
  "scrapedAt": "2026-10-01T17:34:50.079Z"
}
```

### How much does it cost to scrape LinkedIn company employees?

Pay per event, no subscription. Prices per event by Apify plan:

| Event | Free | Bronze | Silver | Gold |
|---|---|---|---|---|
| **Employee** (one delivered person) | $0.0024 | $0.0024 | $0.0020 | $0.0014 |
| **Company** (one company with at least one employee delivered) | $0.024 | $0.024 | $0.028 | $0.035 |
| **Actor start** (once per run) | $0.012 | $0.012 | $0.012 | $0.012 |

Platinum and Diamond plans pay the Gold price. The Actor start event has no plan discount. The platform charges the Actor start event each time a run starts, so a run you resurrect after it stopped pays it once more. The Company event is higher on the plans where a person costs less: every plan gets the same search, and each company costs one Google request before its first person is known.

The Store pricing card shows these same prices per 1,000 events: "$2.40 / 1,000" on the Employee row means one employee costs 0.24 cents, and "$24.00 / 1,000" on the Company row means one company costs 2.4 cents.

Worked examples at the Free and Bronze price:

- 1 company, 10 employees: $0.012 + $0.024 + 10 x $0.0024 = **$0.060**.
- 1 company, 100 employees: $0.012 + $0.024 + 100 x $0.0024 = **$0.276**.
- 25 companies, 20 employees each: $0.012 + 25 x $0.024 + 500 x $0.0024 = **$1.812**.

Every run pays the Actor start event once ($0.012), also a run that finds nothing. Beyond that, no Employee and no Company event is charged for: companies that are not found, ambiguous names, duplicates, invalid values, companies where nobody is found, people already delivered under your memory name, duplicates of a person, rows the profile page contradicts, every status row and the run summary. The Google proxy, the datacenter proxy and the profile check are included; there is no proxy bill on top.

You can cap a run's spend with the platform's maximum charge setting: the Actor delivers only rows the limit can pay for and does not start searching a company the remaining budget cannot cover.

### Input

| Field | Type | What it does |
|---|---|---|
| `companies` | list | LinkedIn company URLs, company names or numeric ids, one per line, up to 5,000 per run. Also read from `companyUrls`, `companyNames`, `company`, `companyUrl`, `identifier`, `queries` and `startUrls`, so the common key names for a company list are accepted |
| `maxEmployeesPerCompany` | integer | Stop a company after this many delivered employees, 1 to 1,000 (default 100, the form starts at 10) |
| `maxEmployees` | integer | Stop the whole run after this many delivered employees; 0 means no run limit |
| `jobTitles` | list | Only people whose headline or job title contains one of these phrases as whole words; up to 20 |
| `locations` | list | Only people whose location (search result or profile page) contains one of these phrases as whole words; up to 20 |
| `verifyEmployer` | boolean | Check each person on their public profile page (default on). Off: only people whose search result carries LinkedIn's employer field are delivered |
| `confirmedOnly` | boolean | Deliver only people the profile page confirms (default off) |
| `memoryName` | string | Remember delivered people under this name and deliver only new ones in later runs |
| `resetMemory` | boolean | Forget the memory before this run |
| `maxConcurrency` | integer | Companies searched in parallel, 1 to 5 (default 3) |
| `proxyConfiguration` | object | Proxy for the LinkedIn pages only; the default Apify datacenter proxy is included |

Job titles and locations are real filters: the phrases go to Google as the search itself, and every row is then checked against them. A row that does not show the phrase in its own text is dropped and costs nothing. One value is one phrase, commas included ("Berlin, Germany" is a single phrase). Write a location the way LinkedIn shows it: a profile in Germany may say "Deutschland".

A run with no input at all (a literal `{}`) searches the sample company for 10 people. An explicitly empty list returns one status row without an Employee or Company charge (the run pays only its Actor start event), and so does an input that has other keys but no company list under an accepted key (a misspelled key never starts a paid search).

#### Run it from the API

```bash
curl -X POST "https://api.apify.com/v2/acts/automation_craft~linkedin-company-employees-scraper/run-sync-get-dataset-items?token=YOUR_TOKEN" \
  -H "Content-Type: application/json" \
  -d '{"companies":["https://www.linkedin.com/company/stripe"],"maxEmployeesPerCompany":10}'
```

```javascript
import { ApifyClient } from 'apify-client';
const client = new ApifyClient({ token: 'YOUR_TOKEN' });
const run = await client.actor('automation_craft/linkedin-company-employees-scraper').call({
    companies: ['https://www.linkedin.com/company/stripe', 'Datadog'],
    maxEmployeesPerCompany: 25,
    jobTitles: ['Account Executive', 'Sales Manager'],
});
const { items } = await client.dataset(run.defaultDatasetId).listItems();
const employees = items.filter((x) => x.type === 'employee');
```

```python
from apify_client import ApifyClient
client = ApifyClient("YOUR_TOKEN")
run = client.actor("automation_craft/linkedin-company-employees-scraper").call(run_input={
    "companies": ["https://www.linkedin.com/company/stripe"],
    "maxEmployeesPerCompany": 50,
    "memoryName": "weekly-watch",
})
rows = list(client.dataset(run["defaultDatasetId"]).iterate_items())
```

#### Scheduled runs and the memory

With `memoryName` the Actor keeps, in a key-value store it creates in your account, the profile of every person it delivered under that name. A later run with the same name skips those people for free and delivers only the rest, each with `firstSeenAt`. A company with nobody new gets a free company row saying so. Newly visible on Google is not the same as newly hired: the row says when this Actor first saw the person, never when they joined.

- Do not overlap runs that share one memory name: a run that finds another run's lock delivers its rows free of charge and does not remember them (two runs started in the same moment both do). Their rows still carry `firstSeenAt`, the time of that run.
- If the memory cannot be opened or saved, the run delivers its rows free of charge and says so in a status row, because "pay once per person" cannot be guaranteed without it.
- A run stops after 20 Google requests in a row that brought no deliverable person (companies with nobody on Google, or everybody already in the memory). The remaining companies get free skipped rows. Keep a watch list to companies that are active on LinkedIn.
- A person is remembered by their public profile URL. Someone who changes that URL counts as a new person: they can be delivered and charged once more under the new URL. The Actor links an old and a new URL only where it can prove it (the page read through the old URL states the new one, or a remembered person of the same name appears in the same results), so do not rely on it.
- A memory name belongs to this Actor in your account.

### What this Actor does not do

- **The full roster of a company.** Ours reads public Google results, which show a slice of a company (the company row says how large; the most we measured for one company is 300), and uses no login. Listing nearly every current employee needs LinkedIn's own people search behind a login.
- **A guarantee that every person still works there.** A row tied by the search result alone rests on LinkedIn's own current employer field as Google last saw it, and that field can lag: a person who left recently, or who is on a career break, can still show the company. In our night test runs the profile page contradicted 8 of 236 and 3 of 180 rows it could check (3.4 and 1.7 percent), and those rows were dropped. In hours when LinkedIn serves no profile page such rows are delivered and charged with `employerConfirmed: null`. Rows with `employerConfirmed: true` are proven by the profile page; use `confirmedOnly` when it matters, and expect few or no rows from it in an hour when the page is closed.
- **Join dates, tenure and the full career.** LinkedIn masks job titles and past employers on the public profile page, so ours returns the current title as the search result shows it, the schools and languages the public page names, and nothing that needs a login.
- **E-mail addresses.** Ours finds none: it needs a paid third party service, and it is a different personal data product.
- **LinkedIn's own search filters.** Ours filters by job title and location text, checked on every row, and labels seniority and department from the title; it does not filter by years at the company, industry, school, past title or "recently changed jobs".
- **Departures and title changes.** A person who disappears from Google's results has not necessarily left, so ours reports newly visible people only and never a departure.
- **Profile photos and "open to work" flags.** The photo is personal data nobody needs for a prospect list, and the flags need a login.
- **Counts without rows and alumni lists.** Ours returns current people only.
- **Subsidiaries under the parent's name.** A person whose employer on LinkedIn is "Zalando Marketing Services" is not delivered for Zalando; give the subsidiary's own LinkedIn page as a second company.
- **Two companies with exactly the same name.** A row matched by the employer field cannot tell two companies of one name apart; rows with `employerConfirmed: true` are proven by the company's own LinkedIn URL. Use `confirmedOnly` when the name is shared.
- **School pages.** LinkedIn does not serve school pages to signed out visitors; give the school's name instead of its URL.

### Personal data

The rows describe people. The Actor reads only what is public without a login: Google's search results for LinkedIn profiles and the public profile page, and it returns no e-mail address, phone number or photo. You are responsible for having a lawful basis for what you do with the rows (under the GDPR, for example, a legitimate interest you have assessed, and the duty to inform people and to honour objections). If a person asks you to remove their data, delete their row from your copies; the Actor itself keeps only the company key with the profile identifier, two timestamps and a short run tag in your own memory store, and `resetMemory` deletes that.

### FAQ

#### How do I get a list of a company's employees from LinkedIn without Sales Navigator?

Paste the company's LinkedIn URL or its name, set how many people you want and start the run. The Actor finds the people in public Google results for LinkedIn profiles, with no LinkedIn login, no cookies and no Sales Navigator seat, and returns the name, headline, job title, location and public profile URL of each.

#### Does it return every employee of the company?

No. Public search results show a slice of a company, never the full roster. The company row says how large the slice is: `employeesDelivered` against `employeesOnLinkedIn`, as `coveragePercent`, with the reason the search stopped. Listing nearly every current employee needs LinkedIn's own people search behind a login.

#### Can I filter by job title to find decision makers?

Yes. Put the titles into **Job titles** (for example CEO, CTO, Head of Marketing). The titles become the Google queries, and every row is then checked: a person is delivered only when their own headline or job title contains one of the phrases as whole words. Each row also carries `seniority` and `isDecisionMaker`, read from the title.

#### Can it tell me who was newly hired at a company?

It can tell you who is newly visible. With a memory name, a scheduled run delivers only people it has not delivered before, each with `firstSeenAt`. That is the date this Actor first saw the person in public results, not the date they joined; join dates need a LinkedIn login and are not returned.

#### What happens when a company is not found or nobody is found?

No Employee and no Company event is charged for it. A run in which no company gets an employee pays only its Actor start event ($0.012). A company that does not exist on LinkedIn gets a free `not_found` row and is never searched; a name that matches several companies gets a free `ambiguous` row listing them; a company where no result can be tied to it gets a free company row with status `no_employees_found`.

#### Why does this Actor run with limited permissions?

It follows least privilege: it reads its input, writes its own dataset and uses the Apify proxy, and it cannot see your other Actors, tasks or storages. The memory for scheduled runs is a named key-value store the Actor creates itself.

### More data tools by Automation Craft

- [LinkedIn Company Scraper - Details, No Login](https://apify.com/automation_craft/linkedin-company-scraper)
- [LinkedIn Jobs Scraper - No Login, Real Dates](https://apify.com/automation_craft/linkedin-jobs-scraper)
- [LinkedIn Ad Library Scraper: Ads by Company](https://apify.com/automation_craft/linkedin-ad-library-scraper)
- [Workday Jobs Scraper & API - Whole Career Site](https://apify.com/automation_craft/workday-jobs-scraper)
- [ATS Jobs Scraper & API - Greenhouse, Lever, Ashby](https://apify.com/automation_craft/ats-jobs-scraper)
- [Trustpilot Reviews Scraper: Coverage Per Company](https://apify.com/automation_craft/trustpilot-reviews-scraper)
- [G2 Reviews Scraper: Ratings, Pros and Cons](https://apify.com/automation_craft/g2-reviews-scraper)
- [US New Business Registrations Scraper - LLC Leads](https://apify.com/automation_craft/us-new-business-registrations-scraper)
- [Bulk WHOIS & RDAP Domain Lookup: DNS, SSL](https://apify.com/automation_craft/domain-whois-rdap-lookup)

### Changelog

See the Changelog tab. Version 0.1 (2026-10-01) is the first release.

# Changelog

This Actor's version history is a separate document: https://apify.com/automation_craft/linkedin-company-employees-scraper/changelog.md

# Actor input Schema

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

One company per line. Accepted: LinkedIn company page URLs (https://www.linkedin.com/company/stripe, any tab or regional host), company NAMES (looked up through LinkedIn's own company lookup and searched only when exactly one company matches the name; an ambiguous name gets a free row listing the candidates), numeric LinkedIn company ids (searched only when a public page confirms the id). Up to 5,000 companies per run. An input with nothing in it at all (a literal {}) searches the sample company for 10 people so the Actor can be tried with one click; an explicitly empty list, or an input without a company list under an accepted key, returns a free status row.

## `maxEmployeesPerCompany` (type: `integer`):

Stop a company after this many delivered employees (1 to 1,000). The search also stops earlier when Google has no more people for the company: public results show a slice of a company, never the full roster (see coveragePercent on the company row).

## `maxEmployees` (type: `integer`):

Stop the whole run after this many delivered employees. 0 means no run limit. Companies after the limit get a free skipped row.

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

Only people whose own headline or job title contains one of these phrases as whole words, for example CEO, CTO, Head of Marketing, Account Executive. The phrases are sent to Google as the search itself AND every row is checked against them afterwards, so a row that does not show the phrase is never delivered. Up to 20 phrases. Leave empty for everybody.

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

Only people whose location, as the search result or the public profile page shows it, contains one of these phrases as whole words, for example Berlin, London, United States. Write the location the way LinkedIn shows it (a profile in Germany may say Deutschland). Up to 20 phrases. Leave empty for everywhere.

## `verifyEmployer` (type: `boolean`):

On by default and included in the price. For every person, the public LinkedIn profile page is opened: when it lists the company among the current employers the row says employerConfirmed true and gains the profile's location, country code and follower count; when it lists other employers only, or none, the row is dropped (a stale search result) and costs nothing. LinkedIn does not serve every profile to signed out visitors, and in some hours it serves none (HTTP 999): those rows are delivered on the search result's own evidence with employerConfirmed null. Turn off for a faster run that relies on the search result only: then only people whose result carries LinkedIn's employer field are delivered.

## `confirmedOnly` (type: `boolean`):

Deliver only people whose public profile page lists the company among the current employers (employerConfirmed true). Fewer rows, each proven twice. Rows whose profile page cannot be read are dropped and cost nothing.

## `memoryName` (type: `string`):

Optional. Give any name (for example weekly-watch) and the Actor remembers every person it delivered under that name. A later run with the same name delivers and charges only people it has not delivered before, each with firstSeenAt, so a weekly schedule returns the newly visible people of a company. Newly visible on Google is not the same as newly hired: the row says when we first saw the person, never when they joined. Do not overlap runs that share one memory name: the second run delivers its rows free of charge.

## `resetMemory` (type: `boolean`):

Forget everything stored under the memory name before this run starts, so every person counts as new again.

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

How many companies are searched at the same time (1 to 5). The default 3 is fast and polite.

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

Used for the company page, the result links and the profile check. The default, Apify's datacenter proxy, is included in the price and serves these pages. The RESIDENTIAL group is replaced by the datacenter pool (the run summary says so). Google does not use this setting.

## Actor input object example

```json
{
  "companies": [
    "https://www.linkedin.com/company/stripe"
  ],
  "maxEmployeesPerCompany": 10,
  "maxEmployees": 0,
  "verifyEmployer": true,
  "confirmedOnly": false,
  "resetMemory": false,
  "maxConcurrency": 3,
  "proxyConfiguration": {
    "useApifyProxy": true
  }
}
```

# Actor output Schema

## `items` (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 = {
    "companies": [
        "https://www.linkedin.com/company/stripe"
    ],
    "maxEmployeesPerCompany": 10,
    "proxyConfiguration": {
        "useApifyProxy": true
    }
};

// Run the Actor and wait for it to finish
const run = await client.actor("automation_craft/linkedin-company-employees-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 = {
    "companies": ["https://www.linkedin.com/company/stripe"],
    "maxEmployeesPerCompany": 10,
    "proxyConfiguration": { "useApifyProxy": True },
}

# Run the Actor and wait for it to finish
run = client.actor("automation_craft/linkedin-company-employees-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 '{
  "companies": [
    "https://www.linkedin.com/company/stripe"
  ],
  "maxEmployeesPerCompany": 10,
  "proxyConfiguration": {
    "useApifyProxy": true
  }
}' |
apify call automation_craft/linkedin-company-employees-scraper --silent --output-dataset

```

## MCP server setup

```json
{
    "mcpServers": {
        "apify": {
            "type": "http",
            "url": "https://mcp.apify.com/?tools=fetch-actor-details,automation_craft/linkedin-company-employees-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/U10sdJaUclBogOqzh/builds/6IG0NnBDvmTnsLxYh/openapi.json
