Company Employees, Founders & Leadership Team Scraper
Pricing
$4.00 / 1,000 person founds
Company Employees, Founders & Leadership Team Scraper
Find employees, founders, CEOs and the leadership team from company websites (not LinkedIn). Reads each company's own team, about, leadership and Impressum pages; returns named employees with title, seniority, site-published LinkedIn link and email. B2B; emails never guessed.
Pricing
$4.00 / 1,000 person founds
Rating
0.0
(0)
Developer
Data Gleaner
Maintained by CommunityActor stats
0
Bookmarked
17
Total users
11
Monthly active users
5 days ago
Last modified
Categories
Features
Share
Company Employees, Founders & Leadership Team Scraper: names, roles and LinkedIn links from company websites
Get a company's leadership team, team members and team page contacts from the company website. Give it company domains and it returns every named person the company publishes on its team, about, leadership, management or Impressum pages, with job title, seniority, the LinkedIn profile the site links and any non-personal email the site publishes. It answers "who works at this company", "who runs this company" and "list the team members on this company's website" for a whole list of domains at once. $0.002 per person until 3 November 2026 and $0.004 per person from then; domains with no team page are free.
It never guesses emails, and it drops personal ones. inferEmails was removed on 2026-11-01 (version 0.5): the Actor no longer builds first.last@ addresses for named people. An email is returned only when the company's own page publishes it and it is not personal: free-mail addresses, first.last@ style addresses and addresses built from the person's own name are dropped from every row, so the email column is usually empty. Shared inboxes such as info@ or sales@ are not attributed to anyone.
Try it now
The input form is filled with keencrest-guides.web.app, our own made-up team page (the company and the people on it do not exist). Click Start. It returns a few fictional people with title and seniority, about US$0.01. With an empty input ({}, as from the API) it runs the same built-in example, at most 3 people.
An example row (fictional):
{"domain": "acme.example", "companyName": "Acme", "personName": "Casey Example", "jobTitle": "Chief Executive Officer","seniority": "c-level", "linkedinUrl": null, "email": null, "emailSource": null}
What it costs, per result: one person-found event per named person with a role that the company's own site publishes: US$0.002 until 3 November 2026, US$0.004 from 3 November 2026 ($4 per 1,000 people). Domains with no team page, no named people, unreachable sites and people your seniority filter or maxPeoplePerDomain leaves out are free. 100 domains with the seniority filter set to founders, C-level and VPs (2 to 5 people each, say 350 people) cost about US$1.40.
What it does
For each domain it reads the home page, finds the links in the navigation and footer that lead to the team, about, leadership, management, founders or Impressum / legal-notice page (in English, German, French, Spanish, Dutch and Italian), and reads at most maxPagesPerDomain of them (default 4). An about page that links on to a separate team page is followed. If the home page links to none of them, it tries the usual paths (/team, /about, /leadership, /impressum and similar).
From each page it extracts the people three ways:
- Structured data: schema.org
Personin JSON-LD or microdata, and anOrganization'sfounder,memberoremployee. - Team cards: the repeated name-and-title blocks of a team grid, with the LinkedIn
/in/link and any non-personal email inside the same card. When a grid gives some people a department instead of a title ("Design", "Customer Success"), it is read from the same slot the other cards use. - Impressum / legal notice: the people named after
Geschäftsführer,Vertreten durch,Vorstand,Aufsichtsrat,Inhaber,Managing Director,Represented byand similar labels, with that label as the title.
Then it keeps out what is not the company's team: customer testimonials and quotes, blog and article bylines, investor and partner logos, menu items, people described as working elsewhere ("CTO at Initech", "former VP"), and navigation text that looks like a name.
Each person gets a seniority from the title: founder, c-level (CEO, CFO, President, Managing Director, Geschäftsführer), vp, director (including Head of), board (board members, Aufsichtsrat, advisors listed under a board heading), manager or other. Rows come out most senior first.
Use cases
- Sales prospecting: the founders, executives and department heads of every company on a target account list, with their LinkedIn profiles.
- CRM enrichment: add the leadership team to company records you already have.
- Recruiting and market mapping: who runs engineering, product or marketing at a set of competitors.
- Due diligence and investor research: the management and supervisory board named in a German, Austrian or Swiss company's Impressum.
- AI agents that need "the leadership team of company X" or "who works at company X" as a tool call, paying only when people are found.
Input
{"domains": ["acme.example", "example.org", "https://example.net/team"],"maxPeoplePerDomain": 25,"seniority": ["founder", "c-level", "vp"],"maxPagesPerDomain": 4,"maxConcurrency": 10,"delaySecs": 0.5}
domains: bare domains, full URLs, or a direct team page URL.startUrls: also accepted, in the common Apify format ([{"url": "https://example.com"}]); merged withdomains, duplicates removed.maxPeoplePerDomain: keep at most this many people per company, most senior first (default 25; 0 means no limit).seniority: return only these levels. Empty returns everyone. People filtered out are not charged.maxPagesPerDomain: pages read per domain after the home page (default 4, at most 10).inferEmails: removed (2026-11-01). An old input that sets it still runs; the run status says the setting is ignored.datasetId: optional, the ID of another Actor's dataset; its websites are added todomains.datasetUrlFieldnames the website field if it is unusual.companyNames: optional, company names instead of websites. See "Have company names, not websites?" below.maxConcurrency,delaySecs,requestTimeoutSecs,respectRobotsTxt(default on) andproxyConfiguration(default none).
Have company names, not websites?
Put the names in companyNames, one per line (add a location after a comma for same-named companies, e.g. Bosch, Germany). The Actor first runs Company Domain Finder on your account to find each company's official website, then reads those websites' team pages exactly like the ones in domains.
{"companyNames": ["Stripe", "Notion", "Basecamp"]}
- What it bills: Company Domain Finder charges its own per-website-found price (nothing when no website is found) on your account. This Actor then charges its usual price per person found, and nothing for the rest. The two charges appear as separate runs in your account.
- Output: each person row has
companyName(the name you gave) and the resolveddomain. A name with no website found, or only a low-confidence guess, gets one free row withfailureReason: "no website found for company name"and no person. - Names are merged with
domains,startUrlsanddatasetId, and a website that appears twice is read once. If the lookup fails or runs out of time, the affected names come back as free rows with afailureReason(such as "company lookup did not finish in time") and the run still succeeds.
Run it after a Google Maps scrape or any other scraper
Open the source Actor's Integrations tab, add this Actor (datagleaner/team-page-contacts) and set its input to:
{"datasetId": "{{resource.defaultDatasetId}}"}
Every time the source run succeeds, this Actor reads the websites from its results (website, url, domain, site, homepage, link, companyWebsite or web, the first one present), skips items with no website, social-media or map links, and duplicates, and returns the team of each company. Each person also carries sourceName, the title or name of the source item (for example the Google Maps place name). Billing is the same: one event per person found.
The same works from code, for one finished run:
run = client.actor("datagleaner/team-page-contacts").call(run_input={"datasetId": "SOURCE_DATASET_ID"})
The status message tells how many domains were read from the dataset and how many items had no website.
It also works as an integration without setting any input: in the source Actor's Integrations tab choose Add integration and pick this Actor, and the dataset is passed automatically.
Output
One row per person.
{"domain": "acme.example","companyName": "Acme","personName": "Casey Example","jobTitle": "Chief Executive Officer","seniority": "c-level","linkedinUrl": null,"email": null,"emailSource": null,"sourceUrl": "https://acme.example/team","input": "acme.example","scrapedAt": "2026-11-02T09:00:00+00:00"}
(Fictional person and company.)
linkedinUrlis filled only when the company's page links that person's LinkedIn/in/profile. It is never searched for elsewhere.emailandemailSource(mailto-linkorpage-text) are filled only when the page publishes a non-personal address next to the person (for example a role mailbox in that person's card). Free-mail,first.last@and name-derived addresses are always dropped.sourceUrlis the page the person was found on, so every row can be checked.
A per-domain summary (status, pages read, people found and pushed) is saved in the key-value store as DOMAIN_SUMMARY. Its status is ok, noPeople, noTeamPage, unreachable, blockedByRobots, notHtml, invalidDomain or error.
How accurate is it?
Measured on 56 real team, about, leadership and Impressum pages from SaaS companies, agencies, enterprises and German publishers, hand-labelled person by person (755 people): precision 100%, recall 98%. On the last 20 of those pages, labelled before the extractor ever saw them, it scored precision 100% and recall 82% before any tuning. Precision is held highest on purpose: a name in the output is a real person the company lists, not a customer quoting it or a menu item.
How much does it cost?
Pay per event: US$4.00 per 1,000 people (event person-found, US$0.004 each). You pay once per named person with a role, published on the company's own site. Domains with no team page, no named people, or that are unreachable are free, and people removed by your seniority filter or maxPeoplePerDomain are not charged.
Worked example: 500 company domains averaging 6 people each is 3,000 people: 3,000 x $0.002 = $6 until 3 November 2026, and 3,000 x $0.004 = $12 from then. To pay only for leaders, set seniority to ["founder", "c-level", "vp"]: a typical company then returns 2 to 5 people. Platform usage is small because the Actor makes plain HTTP requests only.
How to get the leadership team of a list of companies
- Paste the company domains into
domains, one per line. - Set
seniorityto the levels you want, or leave it empty for the whole team. - Click Start. Rows appear as each domain finishes, most senior person first.
- Export the dataset as CSV, Excel or JSON, or read it through the API.
Limits
- Only what the company publishes. A company with no team or about page that names people returns nothing (and costs nothing). It does not search LinkedIn, Crunchbase or anywhere else.
- No JavaScript rendering. Team pages that load their people with scripts after the page opens, and sites that block non-browser clients (HTTP 403 or 429), return nothing (and cost nothing). Blocks are not worked around.
- Names need a first and last name. Cards that show a first name only ("Anna, Support") are skipped.
- People named only in running prose ("our founder Jane started the company in 2015") are not extracted; titled cards, structured data and Impressum labels are.
- Up to 10 pages per domain; default 4. A domain gets no new request after 90 seconds; a very slow server is returned with what was found by then, so one slow site cannot hold the whole run open.
Use with Python
# pip install apify-clientfrom apify_client import ApifyClientclient = ApifyClient("YOUR_APIFY_TOKEN")run = client.actor("datagleaner/team-page-contacts").call(run_input={"domains": ["acme.example"], "seniority": ["founder", "c-level"]})for row in client.dataset(run.default_dataset_id).iterate_items():print(row["companyName"], row["personName"], row["jobTitle"], row["linkedinUrl"])
Use with JavaScript / Node.js
// npm install apify-clientimport { ApifyClient } from 'apify-client';const client = new ApifyClient({ token: process.env.APIFY_TOKEN });const run = await client.actor('datagleaner/team-page-contacts').call({domains: ['acme.example'],seniority: ['founder', 'c-level'],});const { items } = await client.dataset(run.defaultDatasetId).listItems();for (const row of items) console.log(row.companyName, row.personName, row.jobTitle);
Use it from n8n, Make, Zapier or an AI agent
Actor ID: datagleaner/team-page-contacts
Minimal input:
{"domains": ["acme.example"]}
Each tool below runs this Actor with your own Apify API token.
-
n8n: add the Apify node (
@apify/n8n-nodes-apify). On n8n Cloud you install it from the community node registry. Choose Run an Actor and get dataset, set Actor todatagleaner/team-page-contactsand paste the input above. -
Make: use the Apify app's Run an Actor module, then Get Dataset Items to read the results. Watch Actor Runs can trigger a scenario when a run finishes.
-
Zapier: use the Apify action Run Actor, then the search Fetch dataset items. The trigger Finished Actor run starts a Zap when a run ends.
-
AI agents (MCP): connect to
https://mcp.apify.com/?tools=datagleaner/team-page-contacts. In Claude Code:claude mcp add --transport http apify "https://mcp.apify.com/?tools=datagleaner/team-page-contacts"Then run
/mcpto sign in to Apify in your browser. Other clients can sign in with OAuth or send the headerAuthorization: Bearer YOUR_APIFY_TOKEN. Clients that run local MCP servers can use Apify's package (@apify/actors-mcp-server, run withnpx -yandAPIFY_TOKENset) instead. Then ask the agent in plain words, for example:Who is on the leadership team of acme.example and example.org? Give me a table of name, title and LinkedIn, with the page each one came from.
-
LangChain (Python):
# pip install langchain-apify, then set APIFY_TOKEN in your environmentimport jsonfrom langchain_apify import ApifyActorsTooltool = ApifyActorsTool("datagleaner/team-page-contacts")result = tool.invoke({"run_input": json.loads('{"domains": ["acme.example"]}')})
Use over plain HTTP
Agents and scripts without MCP can call it in one HTTP request and get the rows back:
curl -X POST "https://api.apify.com/v2/acts/datagleaner~team-page-contacts/run-sync-get-dataset-items?token=<APIFY_TOKEN>" \-H "Content-Type: application/json" \-d '{"domains": ["acme.example"], "seniority": ["founder", "c-level"]}'
FAQ: the three things that go wrong most
A domain returned no people. Why, and did I pay? You did not pay: only people pushed are billed. The per-domain DOMAIN_SUMMARY in the run's key-value store says why. noTeamPage means the site links no team, about, leadership or Impressum page and the usual paths do not exist; noPeople means it has such a page but names nobody with a title (many small companies list first names only, or no one). unreachable means the site refused plain HTTP (HTTP 403 or 429) or timed out; the Actor does not work around blocks. A team page drawn by JavaScript after load also comes back empty, because pages are not rendered. Try the direct team page URL (acme.com/team) in domains if you know it.
The site lists more people than I got. Check, in order: maxPeoplePerDomain (default 25, most senior first), your seniority filter, and maxPagesPerDomain (default 4 pages after the home page; raise it for companies whose team spans several pages). Beyond those, cards with a first name only and people named only in running prose are skipped on purpose. On 20 hand-labelled pages the extractor had never seen it found 82% of the listed people at 100% precision, so expect some misses on unusual layouts rather than wrong names.
The status message says some domains were "not finished before the run's timeout". The run reached its timeout before those sites answered (dead or very slow hosts take the longest). Rows already found are kept and billed; the unfinished domains are free. Run those domains again, or give the run a longer timeout in Run options. In a test of 60 domains plus 30 dead hosts at a 60-second timeout, the run ended SUCCEEDED in 36 s with 75 people and listed 41 domains as unfinished.
More questions
How do I find who works at a company from its website? Put the company's domain in domains. The Actor finds the team, about and leadership pages from the site's own navigation and returns each named person with their title, seniority and the page they appear on.
Does it find email addresses? Only non-personal ones the company itself publishes next to a person, such as a role mailbox on the team card. It never guesses an address, and free-mail, first.last@ and name-derived addresses are dropped (B174 rule).
Does it return LinkedIn profiles? Yes, when the company's page links the person's LinkedIn profile. The link is normalised to https://www.linkedin.com/in/<slug>. It does not search LinkedIn.
Will it include customers from testimonials? No. Quotes, testimonials and case-study people are removed, as are people described as working at another company. On the labelled test pages, no customer or reviewer was returned as a team member.
Does it work on German Impressum pages? Yes. Managing directors (Geschäftsführer), the executive board (Vorstand), the supervisory board (Aufsichtsrat) and owners (Inhaber) are read from the legal notice with that role as the title.
Can I get only the founders and executives? Set seniority to ["founder", "c-level"]. Everyone else is left out and not charged.
I need the company's general contact details, not people. Use Website Contact Details Scraper for emails, phones and social profiles, or Company Enrichment by Domain for a one-row company profile.
Related Actors
- Google Maps Leads Scraper: local businesses from Google Maps with their phones, website emails and the decision makers named on their team pages, in one run.
- Website Contact Details Scraper: emails, phone numbers, social profiles and contact forms from a list of websites.
- Company Enrichment by Domain: domain to company profile (name, logo, official social profiles, contacts, founding date).
- Hiring Signal Leads: companies that are hiring sales reps now, each with a decision-maker contact, when you do not yet have a list of domains.
- App Developer Email Finder: developer contacts for Google Play, App Store and Steam apps.
Responsible use
This Actor reads publicly available pages that companies publish about themselves, and returns only what those pages show. Names, titles and work emails are still personal data: you are responsible for complying with the law that applies to you, including GDPR, CCPA and anti-spam rules, when you store the results or contact the people in them. Use it for B2B contact with an organisation in a person's business role only. Do not use it to profile individuals, or to screen people for credit, employment or tenancy. Cold email and calls are lawful only where the recipient's country allows them; that check is yours.
Removal requests. If you are named in a result and want your name removed, write to the contact on this Actor's Store page; the entry is added to a removal list within 30 days. Support replies come from Crest, Keencrest's AI agent; the business is owner-operated.