Company Email Finder — Published Emails & Phones by Name avatar

Company Email Finder — Published Emails & Phones by Name

Pricing

from $3.00 / 1,000 company with contacts

Go to Apify Store
Company Email Finder — Published Emails & Phones by Name

Company Email Finder — Published Emails & Phones by Name

Give it company names, get back each company's verified website and its business emails, phone numbers, LinkedIn and social profiles, contact page and postal address — one row per company. HTTP only, no browser, no API key. Unresolved names are free.

Pricing

from $3.00 / 1,000 company with contacts

Rating

0.0

(0)

Developer

Insight Solutions

Insight Solutions

Maintained by Community

Actor stats

0

Bookmarked

2

Total users

1

Monthly active users

a day ago

Last modified

Security

Limited permissions

Share

Find business emails and phone numbers from a list of company names. Give this Actor the names — a conference exhibitor list, a directory, a CRM export, a trade register — and get back one row per company: its verified website, and the business email addresses, phone numbers, LinkedIn and social profiles, contact-page URL and postal address published on it. JSON, CSV or Excel.

It is the Website Contact Extractor with a name-resolution front end. Each name is first resolved to its website — and a website counts only when its own home page names the company — then that website goes through the Website Contact Extractor's own extraction code, unchanged: same pages, same rules, same privacy defaults, same row. HTTP only: no browser, no login, no API key, no email verification pings.

You pay only for what resolves. A name that cannot be verified, or that two different websites both claim, comes back as a free row with the reason. $6.00 per 1,000 companies with contacts on the FREE tier.

Try it in 30 seconds

This is the Store prefill; paste it and run:

{ "companies": ["Apify", "Mozilla", "Basecamp", "Stripe", "Zapier", "Notion", "Vercel", "Cloudflare"] }

Eight well-known names that between them exercise the resolver's rungs (SEC's ticker index, the YC directory, candidate domains, web search). In our offline test against captured copies of these sites it finishes in about two seconds, resolves six of the eight and finds contacts for four. On the live web the outcome depends on the sites and the search engines on the day.

A list of smaller companies, with a country to bias the search:

{
"companies": ["Acme Plumbing & Heating", "Riverside Dental Group", "Northwind Traders Ltd"],
"country": "GB",
"industryHint": "",
"maxPagesPerDomain": 6
}

Lines that are already a domain, URL or email address (stripe.com, https://acme.example/contact, press@stripe.com) skip resolution and go straight to extraction, so a mixed column from a spreadsheet works as it is.

From code — client.actor("insight.solutions/company-contact-finder").call(run_input={"companies": ["Stripe", "Basecamp"]}) with apify-client, or POST https://api.apify.com/v2/acts/insight.solutions~company-contact-finder/run-sync-get-dataset-items.

What comes back

One row per input line, always — including the ones that could not be resolved. The fields you will use most:

  • status — resolved, ambiguous or unresolved.
  • companyName, domain, resolvedUrl — who the company is by its own website's account, and where that website is.
  • resolvedBy and confidence — which rung found the website (input, sec, yc, slug, search) and which signal confirmed it.
  • emails[], phones[], socials, contactPageUrl, addressText, hasContactForm — exactly the Website Contact Extractor's fields, filled the same way.
  • found — at least one usable contact route. This and status are what decide the charge.
  • candidates[] — on an ambiguous row, every website that passed the identity check, so you can pick.
  • reason — on an ambiguous or unresolved row, one sentence saying why, with the candidate domains that were tried.

Full list under Output reference.

We extract role-based and generic business addresses (info@, sales@, kontakt@, owner@, bookings@ …), published business phone numbers normalised to E.164, company social profiles (LinkedIn, X/Twitter, Facebook, Instagram, YouTube, GitHub), the contact page, the postal address and whether there is a contact form.

We do not extract, by default, addresses shaped like a named individual (jane.doe@) — opt in with includePersonalEmails — and never contact details a page's structured data attributes to a Person, and never names, in any field.

Use cases

  • Turn a conference exhibitor list into a lead list — paste the company names, get websites, role addresses, phones and LinkedIn pages back.
  • Enrich a CRM export that has company names but no domains — one row per company, with a machine-readable reason wherever a name did not resolve.
  • Work a directory or trade register — names and a country in (country: "DE" puts .de candidates first and regionalises the search), contacts out.
  • Find the official website for a list of companies — domain, resolvedUrl, resolvedBy and confidence are useful on their own, and a name whose site was found but publishes nothing costs only the resolution fee.
  • Clean a mixed column — names, domains, URLs and email addresses in one list; the domain-shaped lines skip resolution.

How it compares

  • A guessed domain is never an answer. Many tools turn Acme into acme.com and scrape whatever is there. Here a candidate website is accepted only when its own page names the company — its JSON-LD Organization, its og:site_name, its title or its footer copyright — and parked pages, placeholder pages and pages naming someone else are refused. When two different websites both pass, you get an ambiguous row listing both, free, instead of a coin toss.
  • You pay per resolved company, not per input line. Unresolved and ambiguous names, unreachable sites and invalid lines are rows in your dataset at $0.00.
  • The extraction is the one with the paying users. The contact fields are produced by the Website Contact Extractor's own code, vendored byte-for-byte; a test compares this Actor's rows with the extractor's own run on the same captured pages, field for field.
  • Organisations, not people. The resolver looks for an organisation's official website and drops social networks, people directories and data brokers before anything is fetched. There is no person search, and no names in the output.
  • No browser, no API key, no proxy bill for site fetches. Company websites are fetched directly; only the web search and the YC directory lookup go through the datacenter proxy.

How a name is resolved

Five rungs, cheapest first, stopping at the first verified hit:

RungresolvedBySourceRequestsVerified byconfidence
0inputthe line is already a domain, URL or email addressnone— it is your own answer1.0
1secSEC's company_tickers.json — the US public filer this line names, by its registered name, its ticker in capitals (NET) or its CIK — then candidate domains from the filer's name1 per run (cached a week) + 1–4the home page names the filer0.9
2ycthe Y Combinator directory's public search index — the website a YC company keeps on file2 per run (the search key, then one search for up to 25 names)the directory itself0.9
3slug<name>.com, .io, .ai, .co — your country's domain ending first (.de, .co.uk)1–4the home page names the company0.8 / 0.6
4searchone web search, "<name>" <industryHint> official website: DuckDuckGo, Bing as the fallback; the top 8 organic results, about 160 aggregator sites dropped (encyclopedias, social networks, review and job sites, business-data directories, app stores, marketplaces, news sites, company registries)1 search + at most 3 candidatesthe home page names the company0.8 / 0.6
  • The identity check reads the home page's own name — JSON-LD Organization.name, then og:site_name, then the <title>, then the footer copyright — and compares it with the name you gave, ignoring legal forms (Stripe matches Stripe, Inc.). A match in JSON-LD scores 0.8; a match anywhere else 0.6. These are not probabilities; they record which signal matched, which is the thing you can check.
  • SEC matches narrowly: a registered name equal to yours once the legal form is stripped, a ticker typed in capitals, or a CIK — never a prefix (Apple is not Apple Hospitality REIT). YC matches narrowly: the directory's company must have exactly your name (or a former name). A rung that matches nothing simply passes the name on.
  • Search candidates are ranked by how well the domain's own label matches the name, then by your country's domain ending, then by position. A candidate whose label is the name and whose page says so is accepted at once; otherwise up to three are probed, and two different survivors make the row ambiguous.
  • A common short name resolves to whoever owns the obvious domain. Acme will be acme.com if that site calls itself Acme. If your list is full of common names, add the domain to the line, or a country.
  • The search engines may refuse. DuckDuckGo either answers or challenges with an image CAPTCHA; Bing is asked directly, because through datacenter proxies it answers with unrelated pages. A challenge or a block marks that engine off for the rest of the run, so it costs a few requests once (at most three per search already in flight), not three per company; with both engines off, names that needed the search get a free search_blocked row while rungs 0–3 keep working. Pass the domain for those lines.
  • News search is deliberately not a rung: a news item's source is the publisher's website, never the subject company's.
  • Names in non-Latin scripts do not resolve yet. The identity check compares the Latin letters and digits of the two names, so 株式会社サンプル or Пример comes back unresolved, free. Pass the domain for those lines.

Input reference

FieldTypeDefaultWhat it does
companiesarray of strings— (required)Company names, one per line, up to 2,000 per run. A domain, URL or email address on a line skips resolution. Empty lines are ignored; IP addresses, non-http URLs and consumer mailbox addresses (@gmail.com) get a free diagnostic row
countrystring""Optional two-letter code (DE, GB, US). Puts that country's domain ending first among the candidate domains and regionalises the web search
industryHintstring""Optional words added to the web search to tell apart companies with the same name (software, plumbing). Used by the search rung only
maxPagesPerDomaininteger 1–104Pages fetched per resolved website, home page included — the Website Contact Extractor's setting. Costs nothing extra
contactPathHintsarray of strings/contact, /contact-us, /about, /imprint, /impressum, /legalPaths preferred when following contact links
includePersonalEmailsbooleanfalseAlso return person-shaped addresses. Read the data-protection notes before enabling
extractPhonesbooleantrueParse tel: links, JSON-LD telephone and visible text; normalise to E.164
extractSocialsbooleantrueDetect the six social platforms, normalised to the profile root
requestTimeoutSecsinteger 5–12020Timeout for each resolved website's home page during extraction; candidate websites checked during resolution get at most 12 s each
maxRunSecsinteger 30–3600240Wall-clock budget. When reached, no further companies are started; the status message says how many were skipped, and skipped companies are never charged
proxyConfigurationobject{ "useApifyProxy": true }Used for the web search (DuckDuckGo) and the YC directory. Company websites, SEC and Bing are fetched directly
secUserAgentContactstring""Optional. SEC asks automated clients to name themselves and a contact (Acme Research data@acme.com); left empty, the Actor names itself and its Store page. If SEC refuses, rung 1 is skipped for the run, free

Output reference

One row per input line — always. The dataset is never empty.

{
"inputName": "Alpha Robotics",
"inputKind": "name",
"companyName": "Alpha Robotics",
"domain": "alpha-robotics.example",
"resolvedUrl": "https://www.alpha-robotics.example/",
"resolvedBy": "slug",
"confidence": 0.8,
"candidates": [],
"inputUrl": "alpha-robotics.example",
"redirectChain": ["https://www.alpha-robotics.example/"],
"httpStatus": 200,
"pageTitle": "Alpha Robotics — Industrial automation",
"emails": [
{ "address": "info@alpha-robotics.example", "type": "role", "foundOn": "https://www.alpha-robotics.example/" }
],
"phones": [{ "raw": "+44 20 7946 0958", "e164": "+442079460958", "foundOn": "https://www.alpha-robotics.example/" }],
"socials": {
"linkedin": "https://linkedin.com/company/alpha-robotics", "twitter": null,
"facebook": null, "instagram": null, "youtube": null, "github": "https://github.com/alpha-robotics"
},
"contactPageUrl": "https://www.alpha-robotics.example/contact",
"contactPageConfirmed": true,
"addressText": "12 Kingsway, London, WC2B 6UN, GB",
"hasContactForm": true,
"pagesFetched": ["https://www.alpha-robotics.example/", "https://www.alpha-robotics.example/contact"],
"source": "www.alpha-robotics.example",
"sourceUrl": "https://www.alpha-robotics.example/",
"found": true,
"error": null,
"status": "resolved",
"reason": null,
"duplicateOf": null,
"scrapedAt": "2026-10-22T09:14:02.117Z"
}

Field notes

  • inputKind — name (resolved through the ladder), or domain / url / email (used as given — rung 0).
  • companyName — the name the resolved website gives itself; else the brand in its page title; else the directory's name for it (YC, SEC); else your line. null when unresolved.
  • resolvedBy / confidence — see How a name is resolved. null when unresolved or ambiguous.
  • candidates — on an ambiguous row only: domain, url, companyName, matchedOn, confidence and searchPosition for every website that passed the identity check. Empty otherwise.
  • The extractor's fields (inputUrl to sourceUrl, found) — exactly as the Website Contact Extractor documents them: role addresses sorted first, phones[].e164 null when a number could not be validated, all six socials keys always present, and only a contact page that was actually fetched counts towards found. On ambiguous and unresolved rows every one of them is null: there was no website to read.
  • error — null on success. On a resolved row, the extractor's code: no_contacts, blocked, robots_disallowed, dns, timeout, tls, connection, not_html, too_large or http_<status>. Otherwise ambiguous, not_found (no rung verified a website), search_blocked, timeout (the time budget ran out mid-resolution), invalid_input, freemail, or connection if an unexpected error stopped that one line.
  • duplicateOf — set when an earlier line of the same run already reached this website (the same name twice, or a name and its domain): the row repeats that line's contacts and is not charged.

Pricing

EventFreeBronzeSilverGold
actor-start — once per run, only after the first paid row is delivered$0.001$0.001$0.001$0.001
company-resolved — per name resolved to a website whose home page was read$0.001$0.001$0.0008$0.0006
company-with-contacts — per company where contacts were found$0.005$0.005$0.004$0.003

A fully resolved company with contacts bills both: $6.00 per 1,000 companies with contacts on the Free and Bronze tiers. A company whose website was found but publishes nothing bills company-resolved only. A line that was already a domain, URL or email address was never resolved, so it bills company-with-contacts only, when contacts are found — and if your whole list is domains, the Website Contact Extractor is the cheaper tool for it.

Worked example. 1,000 company names on the Free tier; 820 resolve, 650 of those publish contacts, 180 are unresolved or ambiguous:

actor-start 1 × $0.001 = $0.001
company-resolved 820 × $0.001 = $0.820
company-with-contacts 650 × $0.005 = $3.250
──────
$4.071

The 180 unresolved and ambiguous names are in your dataset with the reason, and cost $0.00.

You are not charged for a name that did not resolve (not_found, search_blocked, timeout), a name two websites both claim (ambiguous), a resolved name whose website then could not be read (blocked, dns, robots_disallowed, …), an invalid line, a second line for a website the run already delivered, or anything the run did not reach before maxRunSecs or your run-cost limit. The one flat charge, actor-start, is billed once per run and only after the first paid row is in your dataset — a run that resolves nothing costs nothing at all. No charge is ever made that your run's maximum cost cannot cover.

Limits

Limit
Companies per run2,000
Companies in parallel10; the extraction step never has more than one request in flight per website
Search legs in parallel3, each from its own proxy session
One candidate website2 requests at most (https:// apex, then www.), 12 s each
One name's resolution60 s, every rung included
One search request20 s; at most one search leg per company
Extractionthe Website Contact Extractor's limits: robots.txt honoured, maxPagesPerDomain pages, 4 MB per page, 60 s of network time per website (or 3 × requestTimeoutSecs if higher)
The whole runmaxRunSecs [240 s]: no company starts after it; one already running finishes

Run speed. A name that resolves on the slug rung costs the extractor's own work on its domain plus one home-page read; one that needs the web search adds a results page (≈ 30–60 KB through the proxy) and up to three home-page reads. The extraction step is the Website Contact Extractor's, which measured 40–100 live domains a minute at the default 512 MB; resolution comes on top of that, so plan on fewer names a minute than that, and raise maxRunSecs for lists of more than a couple of hundred names. Companies a run does not reach are never charged.

Websites change, and so do search engines. Extraction reads each site's current markup; a redesign can move or remove what a previous run found, and a search engine that answers today may challenge tomorrow.

Use it from an AI agent, or from code

One JSON object in, one flat array out — the shape agent runtimes want. The Actor runs with limited permissions and pay-per-event pricing, so it works over the Apify MCP server (mcp.apify.com) and with prepaid agentic (x402) tokens. The Integrations tab pushes results to Slack, a webhook, Zapier, Make, Google Sheets, Snowflake or BigQuery, and Apify Schedules run it unattended.

curl -X POST "https://api.apify.com/v2/acts/insight.solutions~company-contact-finder/run-sync-get-dataset-items?token=$APIFY_TOKEN" \
-H "Content-Type: application/json" \
-d '{"companies":["Stripe","Basecamp","Notion"]}'
# pip install apify-client
from apify_client import ApifyClient
client = ApifyClient("<APIFY_TOKEN>")
run = client.actor("insight.solutions/company-contact-finder").call(run_input={
"companies": ["Stripe", "Basecamp", "Notion", "Acme Plumbing & Heating"],
"country": "US",
})
for row in client.dataset(run["defaultDatasetId"]).iterate_items():
if row["status"] == "resolved" and row["found"]:
emails = ", ".join(e["address"] for e in row["emails"])
print(row["companyName"], row["domain"], emails, row["socials"]["linkedin"], sep=" | ")
else:
print(row["inputName"], row["status"], row["reason"], sep=" | ")

Building an app with Lovable? Apify's Lovable connector runs any Actor from inside a Lovable project with your Apify token. Connect Apify in Lovable once, then ask it: "Use Apify to run insight.solutions/company-contact-finder on a list of company names I paste in and build a lead list around the results, with each company's website, emails, phone numbers and social profiles, and a list of the names that did not resolve." A list of a few dozen names finishes well inside Lovable's 300-second synchronous limit, and every result is one JSON object per row, so the generated app needs no extra parsing. Usage bills to the Apify account whose token is connected.

FAQ

Why did a well-known company come back unresolved? No rung verified a website: SEC and YC did not list it under that exact name, none of the candidate domains served a page that names it, and the search results either did not include its site or the engines refused this run (search_blocked). The reason lists the domains tried. Add the domain to the line, or a country or industryHint, and run it again — the free row cost you nothing.

What does ambiguous mean? Two or more different websites each call themselves the company you named. Rather than pick one, the row lists them in candidates and is free. Pass the domain you meant.

Can I look up a person? No. This Actor resolves organisations. A line that is a person's name comes back unresolved unless an organisation's website names itself that way; there is no person search, social networks and people directories are never fetched, and no names appear in the output.

Why is companyName different from what I typed? It is the name the company's own website uses (Vercel Inc. for Vercel), which is usually what you want in a CRM. Your line is kept in inputName.

Do you check whether the email address actually works? No, and we will not add it — the same policy as the Website Contact Extractor. We report exactly what the website publishes.

I already have the domains. Then use the Website Contact Extractor: same extraction, $0.004 per domain with contacts, nothing for the rest. Domain lines work here too, at this Actor's prices.

Why are company websites fetched without a proxy? That is how the Website Contact Extractor fetches them, and it keeps the cost down. Only the web search goes through the proxy, because the search engines are the ones that look at the exit IP.

  • Public pages and public directories only. Everything this Actor reads is served to any anonymous visitor: company websites, SEC's public ticker file, the YC directory's public search index, and search result pages. It never logs in, never supplies cookies or session tokens, and never accepts credentials as input.
  • robots.txt is honoured on every website the extraction step reads, and a refusal is reported (robots_disallowed) rather than worked around. No SMTP probing, no verification APIs.
  • The default output is business contact data. Role-based addresses like info@ and sales@ identify a function, not a person. includePersonalEmails changes that: jane.doe@company.com identifies a natural person and is personal data under the GDPR and the CCPA/CPRA, whether or not it was published. If you enable it, you are the controller — you need a lawful basis, you owe the Article 13/14 notice at first contact, and you must honour access, rectification, erasure and objection requests. Marketing to these addresses is a separate question governed by ePrivacy, national law and CAN-SPAM.
  • No names, by construction. Contact details a page's structured data attributes to a Person are never read, even with includePersonalEmails on; the YC directory is read through its search index only, never the company pages where founder records live; and the name a refused candidate page gives itself is never written to a row.
  • We are not a data broker. This Actor holds no database and sells no list. It reads pages on demand and writes the result to your dataset on your account. The only thing kept between runs is a week-long cache of SEC's public ticker file, in a key-value store on your account.
  • Not affiliated with, endorsed by or sponsored by any company you look up, nor by SEC, Y Combinator, DuckDuckGo, Microsoft (Bing), LinkedIn, X/Twitter, Meta, Google, YouTube or GitHub. Names are used descriptively, to say which source was read or which link was detected.
  • You are responsible for how you use the output. Compliance with the GDPR, the CCPA, ePrivacy, CAN-SPAM and applicable marketing law sits with you as the operator. Nothing here is legal advice.

Our other Actors

Every Insight Solutions Actor is pay-per-result with no browser, no login and no API key, and every one of them returns free diagnostic rows instead of billing for failures. Prices are per 1,000 results.

Video, audio & social

News, documents & the web

Business, finance & jobs

Apps & games