Company Owners & Executives Finder - With Contacts
DeprecatedPricing
from $20.00 / 1,000 person founds
Company Owners & Executives Finder - With Contacts
DeprecatedMoved to leadproof/company-people-finder (https://apify.com/leadproof/company-people-finder): the same Actor with all-inclusive pricing, verified emails and LinkedIn employees. This one is no longer updated.
Pricing
from $20.00 / 1,000 person founds
Rating
0.0
(0)
Developer
Lead Proof
Maintained by CommunityActor stats
0
Bookmarked
4
Total users
3
Monthly active users
a month ago
Last modified
Categories
Security
Limited permissionsShare
Business People Enrichment - Role Holders and Contacts
Give it businesses you have already identified and the roles you care about. It finds the people who hold those roles, shows the published evidence for each role, and returns only the professional contact details a source attributes to that person.
Built for a list of businesses (from Google Maps, a supplier list, a CRM export) where you need to know who to talk to inside each one.
This is not an employee directory. It looks for the role holders you asked about. A business where nobody was found is not a business with no staff, and every row says which of the two it is.
What you get
- People in the roles you asked for - owner, executive, purchasing, operations and more - each with the title exactly as the business published it and the page that says so.
- Only attributable contacts. An email or phone is returned for a person only when the business
publishes it against that person. No guessed addresses: nothing like
first.last@domainis ever built and offered as found. - Business channels kept apart: main lines and function mailboxes (
info@,sales@) are listed as company contacts, never as somebody's direct line. - An explicit account of what was not seen: pages that could not be read, limits reached, sources not consulted. An empty result is never presented as proof that nobody holds a role.
- Ranking you can check: every person carries the comparisons that placed them. There is no opaque score.
- One output row per input business, in input order, so your export lines up with your list.
- Pay per person returned. Businesses where nobody was found are free from this Actor (see Pricing: the page reads are still billed by the reader it calls).
How to use it
- Put your businesses in
businesses. Each needs a website, or a name together with a city, region or country. - Choose
targetRoles, for example["owner", "executive", "purchasing"]. - Keep
maxPeoplePerBusinessat 5 or raise it (up to 25). - Set a maximum charge in the run options and
maxDependencyChargeUsdfor the pages and searches this Actor starts (see Pricing). - Run it on a few rows first, then read
people,candidatesandcoverage.gaps.
Input
{"businesses": [{"inputId": "acct-1", "name": "Example Accountants", "website": "https://accountants.example.co.uk/", "city": "Shrewsbury", "country": "GB"},{"inputId": "dist-1", "name": "Example Industrial Supply", "city": "Salt Lake City", "region": "UT", "country": "US"}],"targetRoles": ["owner", "executive", "purchasing"],"maxPeoplePerBusiness": 5,"renderMode": "http","maxDependencyChargeUsd": 0.5}
| Field | Meaning |
|---|---|
businesses | One object per business: inputId, name, website, city, region, country, mapsUrl, linkedinCompanyUrl. Up to 200 per run. |
targetRoles | Role families to look for. Empty means owner, founder, executive. ["all"] means every person the sources present as staff: a role family when the title names one, roleRelevance: staff otherwise; maxPeoplePerBusiness then defaults to 100. |
sources | Where people come from: ["website"] (default, the company's own pages, every person with a quoted line), ["linkedin"] (a web search for profiles that name the company plus an employee list from a Store Actor, billed to your account; weakly supported, each with a profile link), or both, merged one person per identity. Independent of targetRoles: who you want, from where. |
domains | A bare list of domains (acme.com), each becoming a row with the domain as its id and https://<domain>/ as its website. Use it with targetRoles: ["all"] for "everyone at these companies". |
maxPeoplePerBusiness | Default 5 (100 with targetRoles: ["all"]), up to 100. Supported people past the limit are listed as candidates. |
renderMode | http (default, cheapest), auto or browser. Use browser for sites whose team page is built by JavaScript. |
verifyEmails | Default off. On checks the direct addresses being returned for deliverability. |
inferEmails | Default off. On, every returned person without a published address gets a guess built from the company's own address pattern (published lisa@, paul@ on one domain say first@; otherwise the common patterns in a fixed order), checked with the Bulk Email Verifier. Only a mailbox that accepts mail is returned, as origin: inferred with the pattern in its attribution. A catch-all domain verifies everything and therefore nothing: no address comes back from it. Role mailboxes are never generated. maxEmailChecksPerBusiness (12) bounds the verifier calls. |
findProfileLinks | Default off. On, every returned person without a profile link gets one web search on linkedin.com/in; a result whose title carries the person's name is kept in profileUrls with the search evidence and a warning that it was matched by title and not read. maxProfileSearchesPerBusiness (10). |
judgePeople | Default on. A System One model (TypeSafe's Jev, through Apify's OpenRouter proxy) answers typed questions about every name the readers found: is it a person, do the pages present them as working at or owning this business, and in what role when the page only implies it. It removes testimonial authors and junk headings and names a role family for untitled staff, marked as judged. It writes no text and finds no names; the quotes stay the page's own lines. Its cost (about $0.0006 per business) is billed to your Apify account by the proxy. Set it to false to run on the readers alone. |
concurrency | Default 4, up to 8: how many businesses are enriched at the same time. Rows are still written in input order. |
searchUnresolvedRoles | Default off: a web search runs only when the company's own pages named nobody in a requested role. On: one search per unanswered role, within maxSearchesPerBusiness. |
includeFormer | Default off, so relationships a source describes as past are excluded. |
useLinkedIn | Not available in this release. Leave it off. |
linkedinStaffSearch | Default off. One web search per business for linkedin.com/in profiles that name the company (up to 20 results, $0.005). A result whose headline names the company is a weakly supported staff member with the profile link and, when the headline reads as one, a title; a result that names the company only in its snippet is a candidate, because snippets list past employers too. No profile is read. |
employeeProvider | Default none. Ask a Store Actor for the company's employees and merge them with the site's. auto asks harvestapi/linkedin-company-employees when the site links its LinkedIn company page (fresh, pinned to the exact company; $0.02 per start, $0.003 per profile) and falls back to atomus/linkedin-company-employees by domain ($0.006 per employee, database-backed) when there is no such link or HarvestAPI returned nobody. Either can also be named directly. Both run on your account at their prices. Their people are weakly supported, carry the provider's name in the evidence and the profile link, and merge with the same person from the site. maxProviderEmployees (50) caps the ask. |
maxDependencyChargeUsd | Ceiling, in dollars and cents, on what the page reads and searches this run starts may charge in total. |
Other limits you can lower: maxPagesPerBusiness (8), maxSearchesPerBusiness (1),
maxSecondsPerBusiness (180), and the same per run.
A row needs enough to identify a business. A website, a company profile URL, or a name
together with a place. A bare name is refused for that row before anything is fetched. With a
name and a place but no website, the official site is searched for; if several companies carry
that name, none is picked and the row returns them as businessCandidates with no people.
Roles it understands: owner, founder, executive, partner, purchasing,
operations, finance, marketing, sales, hr, it, clinical, advisor, and synonyms
such as procurement, buyer, supply chain, practice manager and leadership. A role name
it does not model is reported in coverage.unrecognizedRequestedRoles, not approximated.
Output
One row per input business. Main fields:
| Field | Meaning |
|---|---|
status | succeeded, partial (a limit, a timeout or an unreadable source cut it short), failed or skipped. |
outcome | Why people looks the way it does: people_found, no_supported_role_holder_published, sources_were_inaccessible, stopped_at_a_limit, business_not_identified or no_source_could_be_read. |
business | The resolved company, how sure the match is, and why. |
people[] | fullName, associations (published rawTitle, relationship type, current or former, evidence with URL and quote), contacts with attribution and deliverability, matchedRoles, rankingReasons. |
candidates[] | People found but not returned, each with the reason (a role you did not ask for, the per-business limit, a contested identity, another location). |
possibleDuplicateOf | On a person or candidate: other records with the same name and a compatible title that may be the same person. Nothing on the pages ties them together or tells them apart, so they are neither merged nor presented as different people. |
businessContacts[] | Company channels with no person attached. |
coverage | rolesFound, unresolvedRoles, limitsReached and gaps, each gap with a plain sentence saying what it means. |
billedPeople | How many person-found events this row was charged for. |
The run page offers the full JSON, an overview CSV, and a run summary with the dependency spend.
How people are chosen and ordered
- The business is resolved from what you supplied. The home page is read, then the pages it links to about its people: team, about, leadership, contact, locations.
- People come from structured data, from person cards and from plain text, in that order of
support. Only when the site named nobody in a requested role, one bounded search runs (owner OR
founder OR CEO;
searchUnresolvedRolesasks for every unanswered role instead). A search snippet is never treated as evidence of employment. - Every requested role gets one person before any role gets a second; spare places then follow
the order of your
targetRoles. - Inside a role: how directly the title names the role, then the strength of the evidence, then the seniority the title itself states (chief executive or owner, chair, other chief officers, vice presidents, directors, managers), then the name. Evidence always comes before seniority.
Seniority orders people and claims nothing more. A purchasing title is not purchase authority, and "Founder" is not read as owner or chief executive.
Contact scopes
| Scope | Meaning |
|---|---|
person_professional | The business published this address against that person, inside their own entry. A mailbox that merely looks built from their name is never this. |
branch | Published for one location. |
business_general | A function mailbox or a main line. |
unknown | Published, but not attributable: for example on a domain the business does not own. |
Attribution and deliverability are separate fields. A mailbox that accepts mail is not proof of who reads it.
Coverage gaps
| Gap | Means |
|---|---|
source_unreadable | A source was blocked, timed out or failed. Nobody being found in it is not evidence that nobody is in it. |
limit_reached | The run stopped at one of its limits before the sources were exhausted. |
people_withheld_by_charge_limit | People were found but not returned because the run's maximum charge did not cover them. They were not charged. |
page_needs_rendering | A page is built by JavaScript, so its people were not in what was read. Re-run that business with renderMode: "browser". |
page_empty_after_rendering | A page was read in a browser, finished loading and was still empty, typically a guessed address such as /team that the site does not have. |
no_page_about_the_people | The site was read and publishes no team or about page. |
names_found_without_published_titles | People were named with no title, so they are candidates, not role holders. |
no_official_site_identified | The company's own site was not found. |
search_coverage_reduced | The search returned less than was asked of it. |
profile_sources_not_used | No professional-profile source was consulted. |
coverage.absenceIsBounded is true when any gap could be hiding a role holder: on such a row,
an empty people list is not a statement that nobody holds the role.
For JavaScript sites prefer renderMode: "browser" over auto: auto has been seen reading such
a page over HTTP without switching to the browser.
Pricing
One price list, all-inclusive. The page reads, searches, email checks and LinkedIn lookups this Actor runs are on us; you pay only the events below.
| Event | Price | When |
|---|---|---|
person-found | $20 / 1,000 | Each person returned in people, with the quoted line that names their role |
email-verified | $30 / 1,000 | Add-on with inferEmails: a person's work address the mailbox confirmed. Never a generic info@-style inbox |
linkedin-employee | $10 / 1,000 | Add-on with sources: ["linkedin"]: a person an employee listing supplied, on top of person-found |
Free: businesses where nobody was found, businesses that could not be identified, candidates,
company contacts, published addresses, rows that failed. Two records that may be the same person
(possible_duplicate) are charged once.
The one exception is the people judge (judgePeople, on by default): its model call, about
$0.0006 per business, is billed to your account by Apify's OpenRouter proxy. Set it to false to
run without it.
Your run's maximum charge is respected at every step:
- A business is not started unless the remaining maximum still covers at least one more person.
- If a business has more people than the remaining maximum covers, the row returns only the people
that were charged (one per requested role first), stays in the dataset as
partialwithcharge_limitincoverage.limitsReached, and says how many were withheld. The same holds for verified addresses and LinkedIn people. The run stops after that row. - If a run is interrupted and resumed, a row is never charged twice.
What a business typically costs
| Request | Typical |
|---|---|
| Owners and executives, website only (3 people) | $0.06 |
| The same with verified emails (3 verified) | $0.15 |
| Everyone, website only (20 people) | $0.40 |
| Everyone, website and LinkedIn (25 people, 15 from LinkedIn) | $0.65 |
maxPeoplePerBusiness, maxEmailChecksPerBusiness and maxProviderEmployees cap each of these.
Start with a few rows and check the run summary.
What it will not tell you
- A decision maker for every business. Many companies publish nobody. That returns
no_supported_role_holder_published, with the gaps that bound it. - Who approves a purchase. A purchasing title names a function, not an approver.
- That an unknown recency is current. A person on a live staff page is
current; anywhere else recency staysunknown. - One person from two records by name alone. Two records merge only when something outside
the name, such as a personal mailbox or a profile address published for exactly them, ties them
together. Records whose own contacts differ are two people. The same name and title with nothing
either way is flagged
possible_duplicate: listed separately, one place, charged once. "Jane Q Smith" and "Jane Smith" follow the same rule. - A branch contact from a group page. If nothing ties a person to the location you asked
about,
branchRelevancestaysunknown.
Fair use
Only public pages are read, with no login and nothing bypassed. The output is professional information a business chose to publish about its own staff. You are responsible for how you contact the people in it and for following the privacy and marketing rules that apply to you, such as GDPR and CAN-SPAM.
Related
- Business Enrichment - company website, published emails and phones from a business name.
- Web Page Reader - direct page reads.
- Search & Read - web search discovery.
- Bulk Email Verifier - deliverability checks.
- Verified local-business lead lists: leadproof.co.
Development
Python 3.13, Apify SDK 4.0.2. python3 -m unittest discover -s test from this folder. The
person and organization model is a shared library bundled at build time. The project records
(HANDOFF.md, DEPLOYMENT.md, STORE_LISTING.md) are in this folder and are not part of the
store page.