Email & Contact Scraper for Websites — Emails, Phones, Socials avatar

Email & Contact Scraper for Websites — Emails, Phones, Socials

Pricing

from $1.05 / 1,000 domain with contacts

Go to Apify Store
Email & Contact Scraper for Websites — Emails, Phones, Socials

Email & Contact Scraper for Websites — Emails, Phones, Socials

Give a list of websites, get one row per domain with public emails, phone numbers, social profiles and contact form. Reads the homepage plus contact, about, impressum and team pages. $1.50 per 1,000 domains with contacts.

Pricing

from $1.05 / 1,000 domain with contacts

Rating

0.0

(0)

Developer

Dottti

Dottti

Maintained by Community

Actor stats

0

Bookmarked

2

Total users

1

Monthly active users

3 days ago

Last modified

Categories

Security

Limited permissions

Share

Website Email & Contact Scraper

Give a list of business websites. Get one row per domain with its public emails, phone numbers, social profiles and contact form.

The actor reads the homepage. Then it reads the pages most likely to list contacts: contact, about, impressum, legal notice, team and locations. It reads 5 pages per site by default.

  • Price: $1.50 per 1,000 domains where at least one contact is found ($0.0015 each) on the Apify Free plan, less on paid plans (down to $1.05). Domains without contacts and failed inputs are free. Platform usage is included.
  • First run: the form is prefilled with three company websites. Click Start and you get 3 rows of contacts in a few seconds (tested 4 November 2026).

Who it is for

  • Sales and lead generation teams who have a list of company websites and need an email and phone for each.
  • Agencies who enrich Google Maps results with emails and social profiles.
  • Marketplaces and directories who check that listed businesses are reachable.
  • Researchers who map the companies in a sector or a city.

What you get for each domain

  • Emails, deduplicated and lowercased. The actor reads mailto links, plain text, schema.org data and hidden addresses. It decodes Cloudflare email protection. It also reads written-out forms such as info [at] acme [dot] com and info(at)acme.com.
  • Best email (primaryEmail). Addresses on the site's own domain come first. Role addresses such as info@, contact@ and sales@ come next.
  • Phones in international E.164 format (+966114555555). The country comes from the country domain (.de, .sa), the Google Maps countryCode, your default country, or the international numbers on the same site. A number whose country stays unclear is returned as digits.
  • Social profiles, one column each: LinkedIn company page, Facebook, Instagram, X, YouTube, TikTok, WhatsApp and Telegram. When a site links several profiles of one network, the one linked most often is returned. Share buttons and personal LinkedIn profiles are skipped.
  • Contact form URL and contact page URL.
  • Pages checked, their URLs, and a status for every input.

Junk is removed. Image names such as logo@2x.png, error-tracker addresses, website-builder system addresses and placeholders such as you@example.com never reach your data.

Input examples

A list of websites:

{
"websites": ["https://www.hetzner.com", "buffer.com", "https://www.jarir.com/sa-en/"]
}

Google Maps results pasted as JSON. The place title, placeId and countryCode are kept, so you can join the rows back:

{
"places": [
{ "title": "Jarir Bookstore", "placeId": "p1", "countryCode": "SA", "website": "https://www.jarir.com/sa-en/" },
{ "title": "Bread Ahead", "placeId": "p2", "countryCode": "GB", "website": "https://www.breadahead.com/" }
]
}

You can also give the ID of a Google Maps run's dataset in datasetId.

Output example

A real row from a test run (shortened):

{
"domain": "hetzner.com",
"url": "https://www.hetzner.com/",
"status": "ok",
"emails": ["info@hetzner.com", "product-feedback@hetzner.com", "tco@hetzner.com"],
"primaryEmail": "info@hetzner.com",
"phones": ["+4998315050", "+49911234226100"],
"primaryPhone": "+4998315050",
"linkedin": "https://www.linkedin.com/company/hetzner-online",
"facebook": "https://www.facebook.com/hetzner.de",
"instagram": "https://www.instagram.com/hetzner.online",
"x": "https://twitter.com/Hetzner_Online",
"youtube": "https://www.youtube.com/channel/UC5GXP-_6UWl5I9pisIDohUA",
"tiktok": null,
"whatsapp": null,
"telegram": null,
"contactFormUrl": null,
"pagesChecked": 5,
"pageUrls": ["https://www.hetzner.com/", "https://www.hetzner.com/support/", "https://www.hetzner.com/legal/legal-notice/"],
"phoneCountry": "DE",
"sourceName": null,
"charged": true
}

A row from pasted Google Maps data:

{
"domain": "jarir.com",
"status": "ok",
"primaryEmail": "care@jarir.com",
"phones": ["+966920000089", "+9668003034444"],
"facebook": "https://www.facebook.com/jarirbookstore",
"phoneCountry": "SA",
"sourceName": "Jarir Bookstore",
"sourcePlaceId": "p1",
"charged": true
}

Every row has the same columns, so CSV and Excel exports line up.

Status values

StatusMeaningCharged
okAt least one email, phone or social profile foundYes
no_contactsThe site loaded but lists no contacts in its HTMLNo
blockedThe site answers with a bot check on every proxy triedNo
dns_not_foundThe domain does not resolveNo
timeout, unreachable, http_errorThe site is down or answers with an errorNo
parkedParked or for-sale domainNo
not_a_websiteThe input is a Facebook, Instagram or similar page; the link is returned in its columnNo
no_website, invalid_input, duplicate, skippedNothing to check, or the same domain was already checkedNo

The run always ends as succeeded. A run summary with counts by status is saved as RUN_SUMMARY in the key-value store.

Pricing

You pay $1.50 per 1,000 domains where at least one contact is found on the Free plan, $1.35 on Bronze, $1.20 on Silver and $1.05 on Gold. Domains without contacts and every failed or skipped input are free. Platform usage is included in the price, so pages read and proxies used do not change what you pay. Set a spending limit on the run and the actor stops before it.

How to schedule

Save your input as a task. Open Schedules, pick the task, and choose how often it runs. Each run returns fresh rows for every domain.

How it works and limits

  • Plain HTTP requests, no browser. That keeps it fast: most sites finish in 2 to 5 seconds.
  • Sites that block get a second try through a datacenter proxy, then a residential proxy.
  • Sites that build their whole page with JavaScript can return no_contacts.
  • Only public business contact data that the site itself publishes is read. No logins, no cookies, no CAPTCHA solving.
  • Up to 20,000 sites per run. Split larger lists into several runs.
  • You are responsible for using the contacts under the privacy and anti-spam laws that apply to you.