Contact Info Scraper & Email Extractor for Websites
Pricing
$5.00 / 1,000 website with contacts
Contact Info Scraper & Email Extractor for Websites
Contact info scraper and email extractor: give it company domains, get one row per website with emails, phone numbers, social profiles, company name and address. $5 per 1,000 websites with contacts found. Websites with nothing found and failed websites are free.
Pricing
$5.00 / 1,000 website with contacts
Rating
0.0
(0)
Developer
Michael Lip
Maintained by CommunityActor stats
0
Bookmarked
2
Total users
1
Monthly active users
2 days ago
Last modified
Categories
Features
Share
Give it a list of company websites and get one row per website with the emails, phone numbers, social profiles, company name and postal address the site publishes. The price is $5 per 1,000 websites where contacts were found ($0.005 each). Websites with nothing found and websites that fail are free, and the number of pages read per website does not change the price.
It reads the home page first, then the pages that usually hold contact details: contact, about, team, impressum, legal and support pages, and matching sitemap.xml entries. It uses plain HTTP requests with no browser, so a run of 1,000 websites finishes in minutes.
What you get for each website
| Field | What it holds |
|---|---|
domain, finalUrl | The domain you gave and the home page after redirects |
status | ok (at least one email or phone, the only charged status), no-contacts, blocked, dns-error, timeout, error or skipped |
emails | Each address with its type (role such as info@ or sales@, personal, or generic), the source page, and mx (the domain has mail servers: true, false, or null when unknown) |
phones | Each number in E.164 format (+4930...) when the country is clear from the number or the site's country domain, otherwise as written, with the source page |
socials | Profile links for LinkedIn, X (Twitter), Facebook, Instagram, YouTube, TikTok, GitHub, Threads, Telegram and WhatsApp |
companyName | From og:site_name, the schema.org Organization, or the page title |
address | The schema.org PostalAddress, when the site publishes one |
pagesFetched, errorCode, error, httpStatus | What the crawl did, and why a website failed |
An example row (made-up company):
{"domain": "litware-example.de","finalUrl": "https://www.litware-example.de/","status": "ok","companyName": "Litware GmbH","emails": [{ "email": "info@litware-example.de", "type": "role", "source": "https://www.litware-example.de/kontakt", "mx": true }],"phones": [{ "phone": "+49301234567", "format": "e164", "source": "https://www.litware-example.de/impressum" }],"socials": { "linkedin": ["https://www.linkedin.com/company/litware-example"], "x": [], "facebook": [], "instagram": [], "youtube": [], "tiktok": [], "github": [], "threads": [], "telegram": [], "whatsapp": [] },"address": { "street": "Beispielstr. 1", "locality": "Berlin", "postalCode": "10115", "country": "DE", "formatted": "Beispielstr. 1, 10115 Berlin, DE" },"pagesFetched": 6,"errorCode": null}
Price
- $0.005 per website that returned at least one email or phone number. That is $5 per 1,000 websites with contacts.
- Free: websites where nothing was found, blocked websites, DNS errors, timeouts and bad input lines. Each one still comes back as a row with a reason.
- One price per website, whatever the number of pages read (1 to 30).
- Set a maximum charge for the run, and the Actor stops starting new websites when it is reached. Websites it skipped come back as free
SKIPPED_MAX_CHARGErows.
Example: 1,000 websites where 650 have contacts cost $3.25. A per-page price of $0.002 on the same 1,000 websites at 8 pages each would be $16.
How it finds contacts
- Emails from
mailto:links, the visible text and JSON-LD. It decodes common hiding tricks:name [at] site [dot] com,(at), HTML entities and Cloudflare email protection. - It drops things that only look like emails: image names such as
logo@2x.png, placeholders such asyou@example.com, and tracking keys from error-reporting tools. - Phones from
tel:links first, then from text right after a phone label (Phone, Tel, Telefon, Call). Fax numbers, dates, prices and loose digit runs are skipped. - Social profiles from links only. Share buttons, intent links and single posts are dropped, and profile URLs are cleaned up.
- The MX check runs once per email domain per run. It is a DNS lookup, and no email is sent.
- robots.txt is read for each website, and disallowed paths are skipped. A website that disallows its home page comes back as
blockedwithROBOTS_DISALLOWED.
Input
| Field | Default | Notes |
|---|---|---|
domains | two examples | Websites, one per line: acme.com, www.acme.com or https://acme.com/contact. Up to 1,000 per run, duplicates are crawled once |
startUrls | empty | Same as domains, for lists from a file or another Actor |
maxPagesPerDomain | 8 | 1 to 30, home page included |
sameDomainOnly | true | Follow only links on the same domain and its subdomains |
includePhones, includeSocials, checkMx | true | Turn off what you do not need |
maxConcurrency | 10 | Websites crawled in parallel, 1 to 50 |
timeoutSecs | 20 | Per page, 5 to 60 |
Use it from code
With curl, run it and get the rows back in one call:
curl -X POST "https://api.apify.com/v2/acts/zovo-one~contact-info-email-extractor/run-sync-get-dataset-items?token=$APIFY_TOKEN" \-H "Content-Type: application/json" \-d '{"domains": ["apify.com", "python.org"], "maxPagesPerDomain": 8}'
With Python (pip install apify-client):
from apify_client import ApifyClientclient = ApifyClient("YOUR_APIFY_TOKEN")run = client.actor("zovo-one/contact-info-email-extractor").call(run_input={"domains": ["apify.com", "python.org"], "maxPagesPerDomain": 8})for row in client.dataset(run["defaultDatasetId"]).iterate_items():print(row["domain"], row["status"], [e["email"] for e in row["emails"]])
The run also writes an OUTPUT record with counts: websites with contacts, without contacts, failed, and charged.
Price examples, a sample output row, the limits and common questions are also on the Zovo page for this Actor.
What it does not do
- No login pages and no pages behind a login.
- No LinkedIn or other social network scraping. Social profile links are read from the company's own website only.
- No guessing of email patterns (such as first.last@) and no email sending or verification beyond the MX lookup.
- No browser. Websites that need JavaScript to show their contacts, or that block plain HTTP clients with a bot check, come back as
no-contactsorblocked, and you are not charged. - No proxies in this version. Requests come from Apify's servers.
Lawful use
This Actor collects business contact details that companies publish on their own websites. You are responsible for how you use them: data protection laws such as the GDPR, and email rules such as CAN-SPAM, may apply to storing the data and to contacting people. Personal addresses of named employees can be personal data. Keep only what you need, and honour opt-outs.
FAQ
Why does a big website come back as blocked?
Some large websites block any client that is not a full browser. The row says BLOCKED_BY_SITE and is free. Most small and mid-size company websites answer plain HTTP.
Why are the rows in a different order than my list?
Websites are crawled in parallel and rows land as they finish. Match them on input or domain.
Can I run it on a schedule?
Yes. Use an Apify schedule or task with a fixed list. Each run is priced the same way.
Open-source parts
HTTP comes from undici (MIT). The HTTP, address-guard and charset modules are shared with the Zovo URL to Markdown web fetch Actor. This Actor's own code is MIT licensed.
Support Zovo
Zovo builds and maintains this Actor. If it saves you time, you can support the work on GitHub Sponsors. Sponsorship is optional, and the tool works the same without it.
You can also use PayPal.
Zovo is made by theluckystrike on GitHub.
Need your format supported?
Open a format request with a sample file, and I reply there whether it can be done. For USD 299 once, through this GitHub Sponsors tier, I add your file format or a missing feature to a Zovo VS Code viewer, with tests, within 7 days.
More tools by Zovo
- App Store and Google Play Reviews. Gets App Store and Google Play reviews in one run, with one schema.
- Website Screenshot API. Saves full-page screenshots and PDFs of public web pages.
- YouTube Transcript Scraper. Gets YouTube transcripts and captions from videos, playlists and channels.
- Google Trends Scraper. Gets Google Trends interest over time, by region and related queries, with no browser.
Free VS Code extensions by Zovo for the files you export:
- Large JSON Viewer, JSON Browser & JSON Tree. Shows large JSON files as a searchable tree, copies JSONPath and turns arrays of objects into a table.
- XLSX Viewer, Excel Viewer, CSV Viewer & Parquet Viewer (XLS, CSV Preview). Opens CSV, TSV, Excel and Parquet files as a sortable, filterable table.
- JSONL Viewer, Large JSONL Table & NDJSON Viewer. Opens JSONL and NDJSON files as a table, as records or as a chat view.
Zovo tools: all Zovo Actors on Apify, price examples for each Actor and the free Zovo VS Code extensions.