# Company Employees & Leadership Team Finder - Names & Titles (`tidytools/company-team-leadership`) Actor

Find the people a company publishes on its own website and investor site: team, executives, founders and board, each with job title, role and source page. No LinkedIn login. $3 per 1,000 people; companies without people are free.

- **URL**: https://apify.com/tidytools/company-team-leadership.md
- **Developed by:** [Yukai Lin](https://apify.com/tidytools) (community)
- **Categories:** Lead generation, Business, AI
- **Stats:** 2 total users, 1 monthly users, 100.0% runs succeeded, 0 bookmarks
- **User rating**: No ratings yet

## Pricing

from $2.40 / 1,000 people

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

### What does Company Employees & Leadership Team Finder do?

Give it company websites; it returns **the people each company publishes about itself**: the leadership team, executives, founders, board members and, if you want, advisors and the wider team. One row per person with **full name, job title, role (employee / founder / board / advisor) and the page it came from**.

It reads the company's own public pages (team, people, leadership, management, board, about and press-kit pages, including the ones it links to and common addresses such as `/team` or `/company/leadership`) and, when the executives are not there, its **investor relations site** (`investors.*`, `ir.*` or the one it links to). No LinkedIn, no login, no guessing.

- **Lists, cards and embedded data**: card grids, JSON-LD and the JSON that modern sites embed (Next.js and similar) are read directly.
- **JavaScript team pages**: a team, leadership or board page drawn by JavaScript is opened in a real browser.
- **Prose pages**: when an about page names its people in sentences ("founded by Jane Doe and John Smith"), an AI model reads the text, and every name and title it returns must appear on the page.
- **Clean output**: duplicates across pages are merged (one row per person, every source page kept), customer quotes and people of other companies are dropped, menu items and product tiles are not mistaken for people.

### Use cases

- **Account-based sales**: the decision makers of your target accounts (CEO, VP Sales, Head of Marketing) with the page that proves it, ready for an email finder.
- **Lead enrichment**: add "company → people" to a list of domains from Google Maps, a CRM export or another Actor's dataset.
- **Market and competitor research**: who runs a company, who sits on its board, how big its public team is.
- **Recruiting and partnerships**: find the right person to contact by title.

### How much does it cost?

**$3 per 1,000 people** ($0.003 per person row; Silver plan $0.0027, Gold and above $0.0024). No start fee.

Free (not charged): companies where no people were found, sites that cannot be read or block us, duplicate people, people without a job title, roles you did not ask for and input lines without a website. A company without people, an unreadable site and an input line without a website each get one free row with `errorType`. Duplicates, people without a job title and people outside your roles or title filter get no row; the run's `SUMMARY` counts them (`duplicatesDropped`, `notReturned`).

Small companies often do not list their team on their website; these get a free row (`errorType: no_people`).

#### Control your cost

- **Max people per company** (default 50) caps the rows of a big team page.
- **Roles to return** and **Job title contains** (e.g. `CEO, VP, Head`) return and charge only the people you want.
- The run's **maximum charge** is respected: people over it are not saved or charged (`SUMMARY.notProcessed`).

#### Price comparison (checked October 2026)

| Actor | Price | Source |
|---|---|---|
| **This Actor** | $0.003 per person, no start fee | the company's own site and investor site |
| harvestapi/linkedin-company-employees | $0.003 per person + $0.02 per run | LinkedIn |
| apt_marble/linkedin-company-employees-scraper | $0.002 per row | LinkedIn |
| b2bsearch/company-employees | $0.0015 per row | LinkedIn |
| datagleaner/team-page-contacts | $0.004 per person | team pages |

LinkedIn-based Actors cover more people per company; this Actor returns what the company itself publishes, with a source page for every row and no LinkedIn account risk.

### How to use it

1. Paste company websites into **Company websites**, one per line (`acme.com`, `https://www.acme.com/team`, or a spreadsheet row such as `Acme Inc, acme.com, Berlin`), or pick another Actor's dataset in **Dataset ID**.
2. Choose the **Roles to return** (employees, founders and board by default).
3. Run. Each person is one row; open the **People (overview)** view.

#### Input example

```json
{
    "companies": ["apify.com", "gitlab.com", "Acme Inc, acme.com, Berlin"],
    "roles": ["employee", "founder", "board"],
    "maxPeoplePerCompany": 50,
    "titleContains": []
}
```

#### Output example (October 2026: a real row from apify.com, and the free row a company without a people list gets)

```json
[
    {
        "input": "apify.com",
        "company": "Apify",
        "domain": "apify.com",
        "personName": "Jan Curn",
        "jobTitle": "Founder & CEO",
        "role": "founder",
        "sourceUrl": "https://apify.com/about",
        "sources": ["https://apify.com/about"],
        "via": "card",
        "confidence": "high",
        "investorSite": null,
        "observedAt": "2026-10-23T08:10:00.000Z"
    },
    {
        "input": "example-bakery.com",
        "company": "Example Bakery",
        "domain": "example-bakery.com",
        "personName": null,
        "jobTitle": null,
        "role": null,
        "sourceUrl": null,
        "errorType": "no_people",
        "error": "No people for example-bakery.com: no team, leadership or board list found on 3 page(s) read (not charged)",
        "charged": false,
        "observedAt": "2026-10-23T08:10:00.000Z"
    }
]
```

| Field | Meaning |
|---|---|
| `personName`, `jobTitle` | as written on the company's page (title "at our company" suffixes removed) |
| `role` | `employee` (staff and executives), `founder`, `board`, `advisor` |
| `sourceUrl`, `sources` | the page the row is based on, and every page the person appeared on |
| `via` | how it was found: `jsonld`, `embedded` (page data), `card` (list layout), `text` (sentence rules), `ai` (AI read of a prose page, checked against the text) |
| `confidence` | `high` for structured lists and data, `medium` for sentences and AI |
| `investorSite` | the investor relations site read for this company, if any |
| `errorType`, `error`, `charged` | only on free rows (`charged: false`). Every row without `errorType` is one person, charged as one `person-row`; if Apify's charge call fails for a saved person, the row stays free and the run's `SUMMARY` counts it (`peopleSavedNotCharged`, and the `billing` block lists what was actually charged) |

The run's **SUMMARY** record lists companies with people and with 3 or more, people per role, duplicates merged, people not returned and why (no title, other role, title filter, over the maximum, another company in the title), pages read and how many needed the browser or the AI.

### Use with AI agents (MCP)

Add the Actor to an agent through the [Apify MCP server](https://mcp.apify.com) and ask, for example, "list the leadership team of gitlab.com with titles". The agent gets one row per person with the source page.

### Use it from code

```bash
curl -X POST "https://api.apify.com/v2/acts/tidytools~company-team-leadership/run-sync-get-dataset-items?token=$APIFY_TOKEN" \
  -H "Content-Type: application/json" \
  -d '{"companies": ["apify.com", "buffer.com"], "roles": ["employee", "founder"]}'
```

### Advanced settings

- **Read prose pages with AI** (default on): only for about and team pages where the list rules find fewer than 3 people; at most 2 pages per company. Paid Apify plans use a more accurate model chain (Gemini, then Claude Haiku, then Workers AI); the free plan uses Workers AI only, so results on prose pages can be weaker there. No extra charge either way.
- **Browser for JavaScript lists** (`auto` / `off`): at most 2 browser pages per company.
- **Read the investor relations site** (default on): used when fewer than 3 executives or founders were found on the main site.
- **Max pages per company** (default 15), **Companies at the same time** (default 4), **Network** (`auto`: Apify's network first, then our servers).
- **Respect robots.txt** (default off): turn it on to skip pages robots.txt disallows.

### Limitations

- Only what the company publishes. Many small companies name only their founders, and some list first names only ("Robert – Product engineer"); first-name-only people are not returned. Large companies often publish only their executives and board.
- In our October 2026 test of 15 companies (10 SaaS companies from 2 to 10,000+ employees and 5 more from Germany, France, Australia, the Netherlands and the US), plain reading found 3 or more people with titles at 10 of 15; two more need the browser (a JavaScript people page) or our servers (a site that rate-limited one network). The 3 that publish fewer than 3 full names with titles cannot reach 3. In a manual check of the rows against the source pages the same day, no wrong name–title pairs were found in the rows returned with the default roles (checked: every row of the 13 smaller results, and the first 60 rows of the two 70+ person lists).
- People can change jobs before a company updates its site; `observedAt` tells when the page was read.
- No email addresses or phone numbers. To find work emails for these people, use an email finder; to read a company's public contact details, use [Website Email Extractor for Google Maps Leads & Domain Lists](https://apify.com/tidytools/website-contact-extractor).

### Responsible use

- The Actor reads only pages a company publishes about itself on its public website and investor site. It does not log in anywhere, does not use LinkedIn or other social networks, and does not guess, generate or verify personal email addresses.
- Pages behind a login are never logged into, and bot checks and CAPTCHAs are never solved: such sites get a free `blocked` or `login_required` row. robots.txt is not used to refuse a company you asked for unless you turn on **Respect robots.txt**.
- Names and job titles of employees are personal data in many countries even when published by their employer. You are responsible for how you use the results: have a lawful basis (for example legitimate interest for B2B outreach under GDPR in the EU/UK), follow the anti-spam laws that apply to you and to the people you contact (CAN-SPAM, CASL, PECR), keep only what you need and honour opt-out and deletion requests.
- Do not use the results to profile, harass or discriminate against individuals.

### FAQ

**Does it scrape LinkedIn?** No. Only the company's own website and investor relations site. That means fewer people for large companies than a LinkedIn scraper, but no login, no account risk and a source page for every row.

**Why did a company return no people?** It publishes no team, leadership or board list (common for small companies), names people only by first name, or its site could not be read. The free row's `error` says which, and `SUMMARY` lists the pages read.

**Are board members and advisors employees?** No, so they have their own `role`. Board members are returned by default (useful for company research); advisors only when you add them to **Roles to return**, because they usually work for other companies.

**Does the Actor collect usage data?** It sends one anonymous usage counter per run (input type, item count range, outcome) to improve the tool; no URLs, content or account data.

### Support

Open an issue in the **Issues** tab with the company website. Issues are checked regularly.

# Actor input Schema

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

Company domains or website addresses, one per line (acme.com, https://www.acme.com/team). A spreadsheet row also works ("Acme Inc, acme.com, Berlin": the first website-like cell is used), and so does an e-mail at the company's domain. Up to 1,000 companies per run; duplicates are merged. Lines without a website become a free row with errorType "invalid_input".

## `roles` (type: `array`):

Which people to return (and charge): employees and executives, founders, board members, advisors. Advisors are off by default because they usually work for other companies.

## `maxPeoplePerCompany` (type: `integer`):

At most this many people (rows) per company, in page order (executives and founders usually come first). Charged per row.

## `titleContains` (type: `array`):

Only people whose job title contains one of these words (any language, not case sensitive), e.g. CEO, VP, Head, Marketing. Empty = everyone.

## `datasetId` (type: `string`):

Read the company websites from another Actor run's dataset, e.g. the website field of a lead list or a Google Maps export.

## `datasetField` (type: `string`):

Field with the website, domain or e-mail, e.g. "website" (dot paths work). Empty = the first URL field found.

## `useAi` (type: `boolean`):

When an about or team page names its people in sentences instead of a list, an AI model reads the text; every name and title it returns must appear on the page. Paid plans use a more accurate model (Gemini, then Claude Haiku, then Workers AI); the free plan uses Workers AI only. No extra charge.

## `browserMode` (type: `string`):

auto: a team, leadership or board page that is drawn by JavaScript is opened in a real browser. off: plain HTTP only (faster, finds fewer people on such sites).

## `includeInvestorSite` (type: `boolean`):

When the company's own site does not show its executives, read its investor relations site (investors.*, ir.*, or the one it links to) for the management and board pages.

## `maxPagesPerCompany` (type: `integer`):

Pages read per company: home page, linked team / leadership / board / about pages, common addresses (/team, /about, /leadership...) and investor pages.

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

How many company websites are processed in parallel. Lower it if sites rate-limit you.

## `httpVia` (type: `string`):

auto: Apify's network first, then our servers (cf, us) when a site refuses. backend: our servers only. direct: Apify's network only.

## `respectRobots` (type: `boolean`):

Off (default): public pages are read even where robots.txt asks crawlers to stay away. On: such pages are skipped.

## Actor input object example

```json
{
  "companies": [
    "apify.com"
  ],
  "roles": [
    "employee",
    "founder",
    "board"
  ],
  "maxPeoplePerCompany": 50,
  "useAi": true,
  "browserMode": "auto",
  "includeInvestorSite": true,
  "maxPagesPerCompany": 15,
  "maxConcurrency": 4,
  "httpVia": "auto",
  "respectRobots": false
}
```

# Actor output Schema

## `people` (type: `string`):

No description

## `full` (type: `string`):

No description

## `summary` (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": [
        "apify.com"
    ]
};

// Run the Actor and wait for it to finish
const run = await client.actor("tidytools/company-team-leadership").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": ["apify.com"] }

# Run the Actor and wait for it to finish
run = client.actor("tidytools/company-team-leadership").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": [
    "apify.com"
  ]
}' |
apify call tidytools/company-team-leadership --silent --output-dataset

```

## MCP server setup

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

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/vW2U4JzEwUgDgFcxU/builds/TKoLTX5XqrKZJsu0a/openapi.json
