Website Email & Phone Scraper - Contact Details Extractor
Pricing
$15.00 / 1,000 site with contacts founds
Website Email & Phone Scraper - Contact Details Extractor
Finds emails, phone numbers and social profiles on any website. Decodes obfuscated addresses, refuses to invent ones that are not there, and tells you when a site blocked it instead of returning a blank row. Charges only when contacts are actually found.
Pricing
$15.00 / 1,000 site with contacts founds
Rating
0.0
(0)
Developer
NeverEmpty
Maintained by CommunityActor stats
0
Bookmarked
2
Total users
1
Monthly active users
7 hours ago
Last modified
Share
Give it a list of websites. Get back the emails, phone numbers and social profiles that are actually published on them — one row per site, in the order you gave them.
The problem with contact scrapers
Most of them will hand you an address that does not exist.
Here is a real example, produced by this Actor's own first version and then fixed. A page said:
Contact the team at dealer.com for details
A naive "decode obfuscated emails" step turns at into @ and produces team@dealer.com — an address nobody wrote, on a domain that has nothing to do with the site. Send an outreach campaign to a list built that way and you are mailing strangers.
This Actor only decodes what is unambiguously obfuscation — info [at] acme [dot] com, @ entities, Cloudflare's data-cfemail protection — and leaves ordinary English prose alone.
It also drops, before you ever see them:
no-reply@,donotreply@,postmaster@,abuse@,bounce@@example.com,@test.com,@yourdomain.comand other placeholders- image filenames that look like addresses (
logo@2x.png) - Sentry keys and other long hex strings that happen to contain
@
What you get
One row per website:
| Field | Example |
|---|---|
domain | www.debian.org |
ok | true — false only when nothing could be read at all |
emails | ["press@debian.org", "events@debian.org", ...] |
phones | ["+4998315050"] — E.164, international form |
phonesLocal | ["8887334281"] — numbers the site declared in a tel: link or schema.org without a country code. Kept exactly as written rather than guessed at, or dropped |
socials | {"linkedin": [...], "twitter": [...], "github": [...]} |
emailCount / phoneCount / phoneLocalCount | 15 / 2 / 0 |
pagesScanned | 4 |
sourcePages | The exact URLs the contacts came from — so you can verify every one |
reason | Why a row is empty, when it is |
sourcePages matters. Every contact can be traced back to the page it came from. If you doubt a result, you can open the page and look.
It tells you which kind of empty it is
A blank row can mean three completely different things, and most scrapers give you the same blank for all of them:
- The site blocked us →
ok: false,reason: "The site blocked us: blocked by the site (HTTP 403)", and you are not charged - The pages loaded but publish no contact details →
ok: true,reasonsays exactly that, and you are not charged - We found contacts → the arrays are filled, and only then does it cost anything
It does not invent phone numbers
Phone validation is not something to hand-write. This Actor uses Google's libphonenumber — the same library your phone uses — to decide what is a phone number and what is not.
A digit sequence on a page is usually not a phone number. Measured against live pages, a naive regex turns all of these into "phone numbers":
| What it really is | Seen on | Naive result |
|---|---|---|
A float in a code sample — 5.666666666666667 | python.org | +1 666 666 666 6667 |
The Fibonacci sequence — 55 89 144 233 | python.org | +1 558 914 4233 |
A copyright range — 2001-2026 | python.org | +1 200 120 26 |
A VAT number — DE811128135 | bosch.com, hetzner.com | +49 811 128 135 |
A ZIP+4 postal code — 10504-1722 | ibm.com | +1 105 041 722 |
A template placeholder — tel:111-111-1110 | docker.com | +1 111 111 1110 |
A fiction-reserved number — +1 415 555 0132 | anywhere | libphonenumber calls this valid; we still drop it |
This Actor returns none of them.
It never guesses which country a number belongs to
There is no "default country code" option, and that is deliberate.
suse.com lists its offices with local numbers and no country codes. Stamp one country onto all of them and you get numbers that reach nobody:
| On the page | What a default country code produces | Reality |
|---|---|---|
Brussels, Belgium Tel: 31-23-8080010 | +49 31 238 080 010 | The number is Dutch |
Budapest, Hungary Tel: 361-489-4600 | +49 361 489 4600 — and libphonenumber calls it a valid German landline | The number is Hungarian |
Auckland Tel: 0800 569 047 | +49 800 569 047 | New Zealand freephone |
That last one is the dangerous kind: a fabricated number that passes validation, so the buyer cannot tell it is wrong.
So numbers are split into two columns:
phones— the number carried its own country code. Returned in E.164, ready to dial.phonesLocal— the site published it without one. Returned exactly as written, never with a country guessed onto it.
Nothing is thrown away, and nothing is made up. Measured on 2026-08-27 across suse.com, bbva.com, huawei.com, ionos.de, chiyoda.lg.jp and others: 27 numbers in phones, every one of which libphonenumber confirms is valid, and 0 invented.
Two more things it gets right, each found on a real page:
+is a plus sign. ibm.com writes+65-6418-1000. Decode it and you have Singapore. Don't, and the+65is lost.+49 (0)9831 505-0— the German(0)must be dropped when dialling internationally, and(+33) 01 45 66 22 22keeps its French trunk0. Both are handled.
It respects robots.txt
On by default. It reads each site's robots.txt, applies only the rules addressed to * or to this bot (not rules meant for someone else's crawler), honours * and $ patterns, and lets a more specific Allow override a broader Disallow — the standard interpretation.
Where it looks
The page you give it, plus the contact pages it finds from there: contact, about, company, support, and — importantly — impressum, kontakt, imprint, mentions-légales. In German-speaking countries an Impressum is legally required to carry a real address, phone number and email, which makes it the single richest page on a European site. Scrapers that only look for the English word "contact" walk straight past it.
If no such link exists, it tries the common paths directly instead of giving up.
Input
{"websites": ["acme.com", "https://example-corp.de", "https://another.co.uk"],"maxPagesPerSite": 5,"respectRobots": true}
| Field | Default | Meaning |
|---|---|---|
websites | 3 sample sites | Domains or URLs. One row out per row in |
maxPagesPerSite | 5 | Pages read per site (1–20) |
respectRobots | true | Read and honour robots.txt |
timeoutSecs | 20 | Per-page timeout |
Pricing
You are charged per site where at least one contact was actually found (the current rate is shown on this page).
Sites that block you, and sites that simply publish no contact details, cost nothing. Compare that with per-row pricing that charges for blanks: the number that matters is the price per usable lead, not the price per row.
Typical uses
- Building outreach lists from a set of company domains
- Enriching a CRM with published contact details
- Finding the right inbox for partnership, press or support enquiries
- Compliance and due-diligence checks that need a company's published contact information
FAQ
Does it need a proxy? No. It reads ordinary company websites over plain HTTP.
Will it get blocked? Some sites block automated requests. When that happens you are told so explicitly — and not charged.
Can it find personal emails of employees?
It reports what a site publishes. It does not guess address patterns, and it does not invent firstname.lastname@ combinations.
How fast is it? Roughly 5 pages per site. Three sites with five pages each took well under a minute when measured.
Other tools by NeverEmpty
Every NeverEmpty Actor follows the same rule: it never returns an empty result to mean two different things, and it only charges for rows that actually carry an answer.
- domain-lookup - WHOIS, DNS, MX, SPF, DMARC and SSL expiry for a list of domains
- ats-board-finder - a company domain to the ATS and board name it uses
- seo-site-audit - technical SEO audit: meta, canonical, robots, headings
Support
Found a wrong address, or a site where a contact exists but was missed? Open an issue on the Issues tab with the domain. sourcePages in the output tells me where to look.