Website Contact & Email Scraper avatar

Website Contact & Email Scraper

Pricing

from $3.00 / 1,000 verified contacts

Go to Apify Store
Website Contact & Email Scraper

Website Contact & Email Scraper

Extract emails, phone numbers and social profiles from any website or list of websites: MX-checked email addresses and the best inbox picked for each site. Finds an email on 76% of startup domains - and you pay only for contacts found.

Pricing

from $3.00 / 1,000 verified contacts

Rating

0.0

(0)

Developer

Rafal Sav

Rafal Sav

Maintained by Community

Actor stats

2

Bookmarked

81

Total users

46

Monthly active users

6 hours ago

Last modified

Share

What does Website Contact & Email Scraper do?

Website Contact & Email Scraper is an accurate email scraper and contact extractor: give it any list of websites and it pulls emails, phone numbers and social media profiles into clean, structured data — one record per site, with MX-validated emails and a confidence score — ready for your CRM, outreach tool or lead-generation pipeline.

It runs on the Apify platform, so you get API access, scheduling, integrations (Make, Zapier, n8n), proxy rotation and run monitoring out of the box.

Why use Website Contact & Email Scraper?

Most contact scrapers miss data that is right there on the page — social links, obfuscated emails, contacts hidden on subpages — and return lists full of junk and empty fields. This Actor is built around one thing: accuracy. Fewer garbage rows, more real hits, validated and scored.

On a random sample of 150 startup domains it found an email on 76.0% of them, against 53.3% for the category incumbent, at a lower cost per email found (September 2026) — the numbers, the method and the one sample where we do not win are below.

Use cases

  • Sales prospecting — you have a list of target companies from Crunchbase, a directory or a Google Maps scrape, and you need a reachable inbox for each. Feed the domains in, get best_email per company, push it to your CRM. No list yet? Google Maps Email Extractor finds the businesses on Google Maps and reads each one's website with this same engine.
  • Lead-list enrichment — an existing list has company names and websites but no contacts. This fills in emails, phones and social profiles without paying a per-record data-provider fee.
  • Agency and freelancer outreach — scrape the websites of a niche (dentists, law firms, e-commerce shops in one city) and get the contact page details that a Google Maps listing does not carry.
  • Recruiting — collect careers and HR contacts from a list of employer sites, including the ones that hide addresses behind Cloudflare or name [at] domain.
  • Market and competitor research — map which companies in a segment publish a phone number, which only take contact forms, and which social platforms they actually use.
  • GDPR / imprint compliance checks — verify that a list of sites publishes a reachable data-controller contact on its privacy policy or Impressum page.

How the accuracy engine works

For every site it goes deeper and recovers data other scrapers drop:

  • Deep crawl — not just the homepage, but the /contact, /about, /team and /impressum subpages where contacts actually live (bounded by maxContactPages, and it stays on the site's own domain).
  • Hidden-email recovery — decodes Cloudflare data-cfemail / email-protection links, un-obfuscates name [at] domain [dot] com, and reads mailto: links and JSON-LD / schema.org metadata.
  • Validation & scoring — checks each email against its domain's MX records, drops example/placeholder/asset noise, flags generic role inboxes (info@, sales@), and attaches a confidence score so you can pick the best_email.
  • Authorities, chambers and web agencies filtered out — legal pages must name bodies that are not the site (a data protection authority, an arbitration board, a regulator, the professional chamber or licensing office of a lawyer, dentist, tax adviser or estate agent) and print their contact details; footers credit the agency that built the site; demo pages show sample customers. Those are filtered out instead of billed as the site's, and best_email prefers the site's own domain. A service provider a privacy policy names (a payment or chat vendor, say) can still appear in the emails list.
  • Phones & socials — parses phone numbers into E.164 with Google's libphonenumber, and extracts LinkedIn / X / Facebook / Instagram / YouTube / TikTok profiles while filtering out share/intent links.

It respects robots.txt and rate-limits its requests.

How to use Website Contact & Email Scraper

  1. Add one or more URLs under Start URLs.
  2. (Optional) Set Max contact subpages, toggle Validate emails / Extract social profiles, set a Default phone region, or switch JavaScript rendering to auto for sites that need a browser (raise run memory to 2048 MB first).
  3. Click Start.
  4. Download your results as JSON, CSV, Excel or HTML from the Output tab, or pull them via the Apify API.

Input

FieldTypeDescription
startUrlsarrayWebsites to extract contacts from (one record per URL). Required.
maxContactPagesintegerHow many contact-like subpages to deep-crawl per site (0 = homepage only). Default 5.
validateEmailsbooleanValidate emails via MX records and attach a confidence score. Default true.
includeSocialsbooleanExtract LinkedIn / X / Facebook / Instagram / YouTube / TikTok profiles. Default true.
renderJsstringoff (default), auto or on — load pages in a real browser. See JavaScript rendering. Needs ≥2048 MB run memory.
phoneRegionstringISO country code (e.g. PL, US) for parsing local-format phone numbers. Empty = auto-detect from the domain's TLD, then from page signals (address country, og:locale, html lang) so local numbers are still recovered on .com/.org sites.
proxyConfigurationobjectOptional proxy; disabled by default (direct connection). Apify Proxy's datacenter IPs are included in every Apify plan, the Free plan too; residential proxies are billed separately.
proxyFallbackbooleanRetry a site that refuses the direct connection once through Apify Proxy's datacenter IPs, then once more directly. Sites that answer directly never use the proxy. Default true; no effect when proxyConfiguration is set.

JavaScript rendering (renderJs)

Some sites hand a plain HTTP client nothing useful: they block non-browser clients outright (HTTP 403), or they build their footer and contact details client-side. Set renderJs to reach them.

ModeWhat happensWhen to use it
off (default)No browser. Fastest and cheapest.Most sites — the accuracy engine already handles obfuscation, JSON-LD and Cloudflare-protected addresses.
auto (recommended)Scans without a browser first; if a site yields no contact at all, the whole site is re-crawled in a browser.Mixed lists of sites, where you don't know in advance which ones need a browser.
onAlways uses a browser.You already know your targets are browser-only.

auto is the cheap option by design: the browser starts only for sites the fast path could not read, so a list of ordinary sites costs the same as renderJs=off. On the four browser-only sites in our golden set it raises recall from about a quarter without a browser to 96% with one (September 2026), while the browser stays switched off for the other 28 sites.

Requirements: auto and on need at least 2048 MB of run memory (the browser needs roughly a gigabyte of its own, and Apify gives a run CPU in proportion to its memory). Below 1024 MB the browser is not started at all — the pages are read without it and the run's status message says so, rather than reporting sites as empty. The default 512 MB is enough for renderJs=off. Each record carries a rendered flag so you can see which sites needed a browser.

What a browser does not fix: some sites reject requests based on the IP address rather than the client, and a datacenter IP — which is what every cloud run uses — gets an HTTP 403 whether or not a browser is driving it. renderJs reaches sites whose content is built in JavaScript and sites that turn away plain HTTP clients; it does not defeat IP-reputation protection. Apify's datacenter proxy (included in every plan) sometimes gets through where the run's own address does not, and the Actor tries it by itself for every site that refuses a direct connection (proxyFallback); the rest need residential proxies (proxyConfiguration, billed separately). When this happens the run log says so explicitly (Browser got HTTP 403 for …) instead of quietly returning nothing.

Output

You can download the dataset in various formats such as JSON, HTML, CSV, or Excel.

{
"domain": "https://acme.example",
"status": "ok",
"best_email": "anna.nowak@acme.example",
"emails": [
{ "email": "anna.nowak@acme.example", "valid_mx": true, "role": false, "confidence": 0.9 },
{ "email": "info@acme.example", "valid_mx": true, "role": true, "confidence": 0.85 }
],
"phones": ["+48221234567"],
"faxes": ["+48221234568"],
"socials": {
"linkedin": ["https://linkedin.com/company/acme"],
"instagram": ["https://instagram.com/acme"]
},
"email_count": 2,
"pages_crawled": 4,
"rendered": false
}

When a site comes back unreachable

unreachable means no page was downloaded at all — the site refused the request, timed out, or forwards its visitors to a platform's front page (Facebook, a booking site, its registrar), where nothing of the site is — so it is not the same as "this company has no contact details". Nothing is charged for it. Two things are worth trying before you write such a domain off:

  • Set renderJs to auto. Sites that turn away plain HTTP clients often serve a real browser normally.
  • Add a residential proxy under proxyConfiguration. Some sites reject datacenter IP addresses no matter what client asks, and any cloud run uses one. The Actor already retries such a site through Apify's datacenter proxy, included in every plan, which gets past some of them - on 150 random German domains, 4 of the 7 that refused the cloud; residential proxies (billed separately) get past most.

A site that answered but simply has nothing to give is reported as no_contacts, with pages_crawled showing how many pages were read.

Data fields

FieldDescription
domainThe site the record is for.
statusok (contacts found), no_contacts (pages read, nothing to find) or unreachable (the site could not be fetched — see above).
best_emailHighest-confidence email on the site's own domain (a named person over a role inbox); an address on another domain only when the site has none of its own.
emailsAll emails found, each with valid_mx (null if DNS could not be asked), role and confidence (0–1).
phonesPhone numbers normalized to E.164.
faxesFax numbers, E.164 — returned but not billed: a fax is not something you can reach a person at.
socialsSocial profile URLs grouped by platform, deduplicated per account (a site linking both twitter.com/acme and x.com/acme yields one profile, not two).
email_countNumber of kept emails.
pages_crawledHow many pages were fetched for this site.
renderedWhether a browser was needed for this site (see renderJs).

How it compares

In July 2026 we benchmarked this Actor against the category incumbent (vdrmota/contact-info-scraper, 13M+ runs) on an independently hand-verified set of 28 real websites - German legal Impressum pages, US nonprofits, SaaS contact pages, PL companies - each scraping a single page, no deep crawl, no browser, so it is a like-for-like test of extraction accuracy. Ground truth was read out of each page's raw HTML by hand and both Actors were scored identically.

FieldWebsite Contact & Email ScraperIncumbent
Emails (recall)100%94%
Phone numbers (recall)100%, clean E.1640% usable
Social profiles (recall)100%98%

The biggest differences generalize to any site, not just the benchmark:

  • Phone numbers you can actually use. We return normalized E.164 numbers. The incumbent returned zero confident phone numbers across all 28 sites - it dumps raw strings into a separate "uncertain" bucket, mixing genuine numbers with garbage like 888 888 88888 and leaving the formatting to you.

  • Hidden emails other scrapers drop. We recover Cloudflare-protected addresses, HTML-entity and name at domain obfuscations, and emails that live only in JSON-LD/schema.org or a <link rel="author"> - cases where the incumbent returns nothing. And we don't invent them: prose like a heading "Advertising at PHP.net" is not turned into an email.

  • Browser rendering without the browser-sized bill. Browser-only sites are covered by renderJs (see above), and the contacts it recovers cost exactly the same as any other — a flat fee per contact. The incumbent bills browser usage as a separate paid extra on top of its per-page fee.

Head-to-head on an uncurated list

We ran this Actor and the incumbent (vdrmota/contact-info-scraper, 13M+ runs) over the same 150 randomly sampled company domains (Y Combinator startups), in the Apify cloud on the same day (September 24, 2026), at the same crawl depth — ours 3 subpages per site, theirs 4 requests:

MetricThis ActorIncumbent
Domains with an email76.0%53.3%
Emails found204123
Domains with a phone11, usable (E.164)4 confident, 36 more unnormalized
Cost for the run$0.95$1.04
Cost per email found$0.0046$0.0084

On 36 domains only we returned an address; the reverse happened twice. Full method, configuration and caveats: head_to_head_yc150.md.

On 150 random German domains, same setup, the picture is different, and we publish it too: we find an email on more of them (64.7% vs 56.7%) and a usable phone number on far more (91 vs 37), and we cost more per domain ($0.015 vs $0.006) — German legal pages publish many contacts, and we bill per contact where the incumbent bills per page. Details: head_to_head_de150.md.

What it yields on a list you didn't curate

Accuracy on hand-picked pages is one thing; what matters when you buy a run is how many domains actually give you something. In July 2026, on an earlier build that did not yet read privacy and terms pages, we scanned 300 randomly sampled Y Combinator companies (public API, seed 42 — a deliberately hard list: modern JS-heavy startup sites, often with a contact form instead of an address):

MetricValue
Yielded at least one contact81.3%
Yielded an email60.7%
Emails found247 — 47% addressed to a person, 95% MX-valid
Could not be fetched1.0%
Cost$1.33 for 300 domains (~$0.0044 per domain)

Re-running only the domains that yielded nothing, with renderJs: auto, recovered 24 of 56 (43%) for a further $0.09 — taking coverage of the list from 81.3% to 89.3%, and domains with an email from 60.7% to 66.3%.

Full write-up and reproduction steps: field_report_yc300.md.

The full per-site table is in vdrmota_comparison.md, and the labels behind it are public in golden_set.json, so any scraper's export can be scored against them. The golden set now holds 32 sites — the 28 above plus 4 browser-only ones added to prove the renderJs path (with renderJs: auto this Actor scored 100% precision and recall across emails, phones and socials in July 2026; on a September re-run precision stayed at 100%, and every miss came from the two sites that now refuse the connection outright).

Check the numbers yourself

The golden set, the 300-domain sample list and the scoring script are published as a public dataset: github.com/RafalSav/website-contact-scraper-benchmark. Every accuracy claim on this page can be audited or re-run against any scraper's export. Corrections to the labels are welcome.

Scraping German sites?

There is a variant tuned for the DACH market: Impressum Email Scraper — same engine and the same filtering, with DE phone parsing preset and more subpages per site.

How much does it cost?

You pay only for what is found — never for empty pages. This Actor uses Apify's pay-per-event pricing, and the price follows what a result is actually worth to you:

  • Verified contact — $0.003 (~$3 per 1,000): an email or a phone number, i.e. something you can reach a person at. Fax numbers are returned too, and never billed; so is an address whose domain accepts no mail (valid_mx: false, such as a typo on the page).
  • Social profile — $0.001 (~$1 per 1,000): a clean, de-duplicated profile link. A footer link is worth less than a verified inbox, so it costs a third as much, and one profile counts once however the site links it (twitter.com/acme and x.com/acme, /acme/ and /acme/about).
  • Actor start: Apify's standard ~$0.05 per 1,000 runs.
  • Free to try: the Apify Free plan includes $5 in monthly credits.

Turn off includeSocials if you only want reachable contacts — then social links are neither extracted nor billed.

Because you are billed per result and not per page, deep-crawling extra subpages to recover a hidden email never inflates your bill on sites that have nothing to give. You can also cap spend per run with the maximum cost setting — the Actor stops charging as soon as your budget is reached.

FAQ

How do I find the email address of a company from its website?

Paste the company's domain into Start URLs and run the Actor. It opens the homepage, then the contact-like subpages (/contact, /about, /team, /impressum, and privacy or terms pages as a fallback), collects every address it can prove is real, and returns the most promising one as best_email. No manual clicking through pages.

How many emails will I actually get?

On hand-picked contact pages, effectively all of them (100% recall on every page of our 32-page verified benchmark that could be fetched). On an uncurated list of company domains, expect an email on roughly two thirds to three quarters of them: on 150 random startup sites we returned an email for 76.0% (September 2026); on 150 random German domains, many of them without a website behind the name, for 64.7%. Sites that only offer a contact form are the usual reason for a miss — nobody can scrape an address that was never published.

Does it verify that the emails are valid?

Yes. Every address is checked against its domain's MX records (valid_mx), filtered against placeholder and asset noise, flagged as a role inbox (info@, sales@) or a named person, and scored with a confidence value between 0 and 1. Unlike most competitors, verification is included in the price rather than sold as a paid add-on.

What is the difference between best_email and the emails list?

emails holds everything found. best_email is the single highest-confidence pick — a named person's address outranks a general contact inbox, which outranks a technical or legal mailbox. It is the field to use when you want exactly one contact per company.

Can it scrape sites that need JavaScript?

Yes, via renderJs. Set it to auto (recommended) and a real browser is used only for sites the fast path could not read, so an ordinary list costs the same as running without a browser. Note that a browser does not defeat IP-reputation blocking — see renderJs.

Why did a site come back empty?

Check the status field. no_contacts means pages were read and there was genuinely nothing to extract (typically a contact-form-only site). unreachable means nothing could be downloaded, directly or through Apify's datacenter proxy — retry with renderJs: auto or a residential proxy. A domain that only forwards to Facebook or to its registrar stays unreachable on purpose: those pages hold the platform's contacts, not the company's. Empty results are never charged.

What if the run times out or is moved to another server?

A few minutes before its timeout the run stops taking new sites, finishes the ones in progress and says in its status message how many were left — raise the run's timeout for long lists. The same happens at the maximum cost per run you set: nothing beyond it is read or charged, and the status message says how many sites were left. A run the platform moves to another server picks up where it was: no site is read or charged twice.

How much does it cost to scrape 1,000 websites?

You pay per contact found, not per page, so the answer depends on how many contacts the sites publish. Measured in September 2026 at 3 subpages per site: $0.95 for 150 startup domains ($6.30 per 1,000) and $2.18 for 150 German domains ($14.50 per 1,000 — German legal pages list many contacts). The Apify Free plan's $5 monthly credit therefore covers roughly 800 startup-style sites or 340 German ones; domains that yield nothing cost nothing, and more subpages per site find more and cost more.

Can I get the emails of businesses listed on Google Maps?

Yes — with Google Maps Email Extractor, which runs this same engine: type what you would search for on Google Maps (dentist, plumber, Steuerberater) and a location, and it returns one record per place with the email from the business's own website. It is priced per place with an email rather than per contact. Already have the websites? Use this Actor.

Can I run it on a schedule or from my own code?

Yes. It is a standard Apify Actor: schedule it in the Console, call it from the Apify API or any of the client libraries, or connect it to Make, Zapier or n8n. The output dataset exports as JSON, CSV, Excel or HTML.

Collecting business contact details that a company publishes on its own website is generally permitted, but the responsibility for how you use them is yours: under GDPR and similar regimes you are the data controller, you need a lawful basis for outreach, and you must honour opt-outs. This Actor respects robots.txt and rate-limits its requests. See the disclaimer below.

How is this different from the other contact scrapers on Apify?

Two things: it recovers addresses others drop (Cloudflare-protected, HTML-entity and name at domain obfuscation, JSON-LD, <link rel="author">, privacy-policy pages), and it charges for results rather than pages, so a deep crawl that finds nothing is free. Every accuracy claim in this README comes from a benchmark you can re-run yourself.

Disclaimer

This Actor is a tool. You are the data controller for any personal data you collect and are responsible for using it in compliance with applicable laws (GDPR and equivalents), the target site's Terms of Service, and robots.txt. It does not build or sell contact databases.

Support

Found a site where contacts were missed? Open an issue on the Issues tab — accuracy reports directly shape the roadmap. And if the scraper saves you time, a short review helps other people find it.