Company contact details are published, not hidden, but they are rarely where you expect them. Some sit on a contact page, some only in a privacy policy or a set of terms, some in machine-readable structured data that never appears on screen, and some are written as hello [at] acme [dot] com to defeat exactly this kind of tool.
This reads a company's website and returns the email addresses and phone numbers it publishes, each one with the page it was found on. Addresses are validated by the same engine behind the bulk validator before they are returned, so a row carries a 0 to 100 send-risk score and a plain-English reason alongside the address rather than leaving that work for a second pass. Phone numbers are parsed with Google's libphonenumber and come back in international and national form, with line type and registered locality.
The design constraint throughout is that it must not invent anything. An extractor that reads a page loosely will assemble addresses out of ordinary sentences, because English writes phrases like available at zapier.com constantly and a permissive pattern cannot tell that from a real address. Every rule here is tuned to refuse first, which costs some coverage and is the reason a returned row can be acted on.
What the data says
87.5%
Fourteen of sixteen large software companies publish an email address you can find without logging in.
Measured on the Actor's own runs across sixteen well-known software companies, not estimated. Two of the sixteen publish no address at all, and one of those has no contact form either. Companies that do publish average 2.3 addresses. Read the figure as a floor rather than a general rate: large software companies route enquiries through forms and are close to the hardest case, while a small local business tends to put its address in the site header. Five of the sixteen publish nothing on their contact page and everything on their legal pages, which is why a second pass over privacy policies and terms runs when the first pass finds nothing.
Inputs
- websitesarray
- One company website per entry. A domain or a full URL both work, and acme.com, www.acme.com and https://acme.com/ are recognised as the same company and charged once.
- maxPagesPerSiteinteger
- How many pages to read per company. Five by default: the homepage plus four chosen by likely contact value. Configurable from 0 to 10.
Outputs
- email addresses
- Every published address, each with the URL of the page it was found on and how it was published: declared in structured data, written as a mailto link, or sitting in page text.
- send-risk score
- The same 0 to 100 score and recommended action the bulk validator produces, with the reason codes behind both.
- phone numbers
- International and national format, line type such as fixed line, mobile, toll free or VoIP, and the registered locality.
- ownership flag
- Whether each address belongs to the company's own domain. Real sites publish real addresses that are not theirs, so this is a field rather than a filter.
- contact form URL
- For companies that publish no address at all. An empty row that says where the contact form is remains useful; an empty row that says nothing does not.
Delivered as Apify dataset, CSV.
What it does not do
It does not confirm that an individual mailbox exists. It removes what is provably bad, being invalid syntax, dead domains, disposable providers and unattended no-reply boxes, and says which addresses it cannot be sure about. Mailbox probing is unreliable, is treated as abusive by many providers, and Apify blocks outbound port 25 in any case, so no run on the platform can attempt it.
It never guesses an address. There is no firstname.lastname@company.com pattern generation. Every address returned was published somewhere, and the row names the page it came from.
It does not render JavaScript. On a sixteen-company sample the addresses that were missed were present in the raw HTML anyway, so the effect measured small, but it is not zero: pages that build their contact details in the browser yield nothing.
It reads five pages per company by default and digs further only when the first pass finds nothing. A company that publishes an address on its thirtieth page will be missed.
A phone number its country's numbering plan does not recognise is not returned, and premium-rate numbers are dropped on purpose rather than missed. Where a site declares no region, through neither a country domain nor a document language, only international format is accepted, because defaulting to one country silently mangles every number from another.
Addresses that are published but belong to somebody else are flagged rather than removed. A German imprint is legally required to name an arbitration body, so the correct behaviour is to report the address and say whose domain it is.
Where it is used
- Turning a list of company domains into contact rows that can be acted on, without a separate validation step afterwards.
- Checking whether a prospect list is reachable at all before committing to a campaign built on it.
- Finding the address a company actually reads, which on larger companies is frequently on a legal page rather than a contact page.
- Calling it from an agent mid-task, where the score and the source URL matter more than the raw address, because an agent cannot tell a confident wrong answer from a right one unless the tool makes the difference explicit.
From an agent
It runs as an Apify Actor, so any MCP client can call it through Apify's hosted server at mcp.apify.com. Nothing extra was built for this. It is not loaded by default, so an agent either finds it through Apify's search tool or is given the name:
salomon-dot-labs--website-email-finder
The description a model reads before deciding to call it is the same sentence that heads this page. Every input listed above is optional, so a model can start it with far less than a full configuration.
Worth knowing when you wire it up: the call returns a pointer rather than the rows. An agent gets the dataset id, the item count and the available field names, then fetches the results in a second step. That is how Apify exposes every Actor, not something particular to this one, and it means budgeting two round trips per answer.
It runs on Apify. Inputs, output schema and pricing are all on the listing, and a run can be started from the browser without writing any code.
Open on Apify