Contact Details Scraper - Emails, Phones & Socials avatar

Contact Details Scraper - Emails, Phones & Socials

Pricing

from $1.44 / 1,000 websites

Go to Apify Store
Contact Details Scraper - Emails, Phones & Socials

Contact Details Scraper - Emails, Phones & Socials

Get emails, phone numbers, addresses and social profiles from a list of websites. It reads the contact, about, team and imprint pages, not just the home page, and returns contact forms too. Each finding names its source page. $1.50 per 1,000 websites, less on paid plans.

Pricing

from $1.44 / 1,000 websites

Rating

0.0

(0)

Developer

Dami's Studio

Dami's Studio

Maintained by Community

Actor stats

0

Bookmarked

10

Total users

4

Monthly active users

a day ago

Last modified

Share

Paste a list of websites and get the emails, phone numbers, addresses and social profiles each one publishes: one row per site, plus its contact forms down to the field names each form expects, and every finding tagged with the page it came from.

It does not stop at the home page, because contact details rarely live there. Each site gets a short crawl weighted towards contact, about, team, legal and the German imprint page. And plenty of businesses publish no email address at all any more, so a row with social links, a form and emails: [] is a normal result rather than a failure.

InputDomains or website URLs, one per line
OutputOne row per website: emails, phones, postal addresses, social profiles, contact forms, structured company and people data, each with its source pages
Ceiling20 pages crawled per site
Account neededNone
Price$1.50 per 1,000 websites on the free plan, down to $1.44 on Business. The free plan's $5 a month covers about 3,300

🔍 What Contact Details Scraper does

For each site it fetches the home page, picks the links most likely to carry contact details, and reads up to maxPagesPerSite of them. Everything it finds is merged into one record for that domain, deduplicated, with the source page recorded against each item.

Ten social platforms are recognised by name: LinkedIn, Facebook, Instagram, X, YouTube, TikTok, Pinterest, GitHub, Threads and Bluesky. Anything else stays a plain link.

📋 What data you get from each website

What you getField
Email addresses, each with the pages it appeared onemails
Phone numbers as written, plus the international form and countryphones
Postal addressesaddresses
Profiles on ten social platformssocialLinks
Contact forms: where they post, the method and the field namescontactForms
Companies and named people from the site's own structured datajsonLdOrganizations, jsonLdPeople
The site's title and descriptiontitle, description
Every page read, with its status and how many findings it gavecrawledPages, pagesCrawled, pageErrors
Counts, for sorting a long listemailCount, phoneCount, socialLinkCount, addressCount, contactFormCount

▶️ How to scrape contact details from websites

  1. Open Contact Details Scraper and click Try for free.
  2. Paste your domains into Websites, one per line.
  3. Set Default phone country if your list is mostly one country. It makes the phone numbers usable.
  4. Raise Maximum pages per site if you want a deeper look, then click Start.
  5. Download the dataset as JSON, CSV or Excel, or read it from the Apify API.

Start it with an empty list and you get one labelled sample row showing the shape. It is not charged.

💰 How much does it cost to scrape contact details?

$1.50 per 1,000 websites on the free plan. Paid plans pay a little less: $1.48 on Starter, $1.46 on Scale and $1.44 on Business. The free plan's $5 a month covers about 3,300 sites.

You pay per website, not per page. A site where 20 pages get read costs exactly the same as one where a single page does, so raising maxPagesPerSite buys you more findings for the same money.

A site is charged only when it turned up something. Sites that failed to load, sites with nothing to find, duplicate entries that collapsed into one row and the sample row are all free.

Each site's charge is set aside before it is crawled, so a run never goes past the maximum cost you set. If that maximum cannot pay for a single site, the run stops before crawling, with a CHARGE_LIMIT row.

📥 What you give it

{
"websites": ["apify.com", "https://stripe.com", "example.co.uk"],
"maxPagesPerSite": 8,
"defaultCountry": "US"
}
FieldDefaultWhat it is
websitesnoneDomains or full URLs, one per line. A value with no scheme is treated as HTTPS. The Console box starts with one example; an API call has to send its own.
startUrlsnoneThe Apify request-list format, if that is what you already have. Combine it with websites freely.
maxPagesPerSite61 to 20. More pages finds more and takes longer, and it does not change what you pay.
defaultCountrynoneA two-letter code like US, GB or CA, used to read phone numbers written without a country code. Without it, a local number such as (512) 653-1187 is not picked up at all.
maxConcurrency51 to 20 sites at once. Each site is still crawled one page at a time.
respectRobotsTxttrueSkips pages the site asks crawlers not to read.
requestTimeoutSecs123 to 45 seconds per page, body included.
maxResponseSizeKb1536128 to 5120. A page bigger than this is skipped.
proxyConfigurationoffOptional network settings, off by default.

startUrls wants actual URL entries. A requestsFromUrl pointing at a text file of links is not picked up, so paste those URLs in rather than linking them.

📤 What you get back

A real row from a run on 30 September 2026. The site published twelve addresses; the list is cut to three, and the page lists are trimmed.

{
"ok": true,
"siteUrl": "https://www.w3.org/about/positive-work-environment/",
"requestedUrl": "https://w3.org/",
"domain": "w3.org",
"title": "W3C",
"description": "The World Wide Web Consortium (W3C) develops standards and guidelines to help everyone build a web based on the principles of accessibility, internationalization, privacy and security.",
"emails": [
{ "email": "contact@w3.org", "sourcePages": ["https://www.w3.org/contact/", "https://www.w3.org/zh-hans/contact/", "https://www.w3.org/ja/contact/"] },
{ "email": "membership@w3.org", "sourcePages": ["https://www.w3.org/contact/", "..."] },
{ "email": "invoicing@w3.org", "sourcePages": ["https://www.w3.org/contact/", "..."] }
],
"phones": [
{ "phone": "+1 339 273 2711", "e164": "+13392732711", "country": "US", "sourcePages": ["https://www.w3.org/contact/", "..."] },
{ "phone": "+86 10 8231 6341", "e164": "+861082316341", "country": "CN", "sourcePages": ["https://www.w3.org/contact/", "..."] }
],
"socialLinks": [
{ "platform": "github", "url": "https://github.com/w3c/", "sourcePages": ["https://www.w3.org/", "..."] }
],
"addresses": [],
"contactForms": [],
"jsonLdOrganizations": [],
"jsonLdPeople": [],
"crawledPages": [
{ "url": "https://www.w3.org/", "status": 200, "title": "W3C", "contactsFound": 1 },
{ "url": "https://www.w3.org/contact/", "status": 200, "title": "Contact | W3C", "contactsFound": 14 }
],
"pagesCrawled": 6,
"pagesAttempted": 6,
"emailCount": 12,
"phoneCount": 2,
"socialLinkCount": 2,
"addressCount": 0,
"contactFormCount": 0,
"robotsTxtRespected": true,
"pageErrors": []
}
FieldHow to read it
sourcePagesOn every finding. When someone asks where an address came from, you point at the page instead of checking it again by hand.
phonesThe number as written, plus e164 and country once it has been read. That reading leans on defaultCountry for locally written numbers.
contactFormsThe form's action URL, method and field names, and whether it has message, email and phone fields. Worth reading when a site publishes no address at all.
jsonLdOrganizations, jsonLdPeoplePulled from the site's own structured data, exactly as the site describes itself.
pageErrorsPages that could not be read, each with its own code, such as ROBOTS_DENIED for a page the site asked crawlers to skip.
domainThe site key, without www. Two inputs that resolve to the same site collapse into one row.

The preview table shows the counts rather than the addresses themselves. Download the JSON or CSV to get the actual emails, phones and links.

🧾 Reading the output

Three kinds of row can land in your dataset.

RowHow to spot itCharged
A siteok: true and a domainyes
The sample row_sample: trueno
A diagnosticok: false and an errorCodeno
CodeWhat it means
BAD_INPUTNothing usable in websites or startUrls, or one entry that is not a website.
NO_CONTACTSThe site loaded fine and published nothing this actor recognises.
NO_RESULTSNothing on that site could be read. Often a domain that redirects somewhere else, or a site that asks crawlers to stay out.
UNSAFE_URLThe hostname resolves to a private address, so it was not fetched.
TIMEOUT, NETWORK and other page codes`Nothing on the site loaded, and the code says why the first page failed: too slow, refused, unreachable.
NOT_SERVEDThis website was not served this run. Re-run it later. Until 12 October 2026 this code was called BLOCKED.
CHARGE_LIMITYour maximum cost could not pay for one site, so nothing was crawled.
INTERNAL_ERRORSomething went wrong in the run itself. Send us the run ID.

One bad site never stops the others. If the run reaches its time limit or your maximum cost with sites still waiting, it stops starting new ones, says how many it did not reach in its status, and lists them in the log.

💡 What people use it for

  • Turning a list of company domains into a contact sheet, with the source page beside each finding so nothing has to be checked again.
  • Finding the contact form when a company publishes no email address.
  • Pulling the social profiles for a set of brands in one pass, instead of hunting through footers.
  • Checking a supplier list still has working, published contact details on it.

From a trade and a city to a checked contact sheet, in three runs:

  1. Run Yellow Pages US Scraper for a trade and a city, and copy the website column. Some listings have none.
  2. Paste those sites into websites here with defaultCountry set to US.

🚧 What it does not do

  • No JavaScript. Details a script adds after the page loads are not seen. Most business sites publish them in the HTML, but a footer fetched from an API is a genuine miss.
  • No logins. Public pages only, nothing behind a sign-in, a paywall or a form.
  • No emails inside images.
  • Same site only. Subdomains and a domain that redirects somewhere else are not followed.
  • 20 pages per site is the ceiling. This is a targeted crawl of the likely pages, not a full spider.
  • It respects robots.txt by default, so a site that asks crawlers to stay out returns little. That is deliberate.
  • It finds what is published, not what is true. A stale address on an old page still comes back.
  • No verification. It does not check whether an address accepts mail.
  • It is not an official tool of any platform or company named on this page. Dami's Studio is independent and is not affiliated with or endorsed by any of them.

🧭 Which contact scraper do you need?

If you wantUse
Emails, phones and socials from a list of websitesThis one
Local businesses with phone, address and website, to feed in hereYellow Pages US Scraper
Local businesses on Google MapsGoogle Maps Scraper
Contact details off a Facebook PageFacebook Page Contact Info Scraper
Contacts and tech stack for Shopify stores onlyShopify Store Leads
Social profiles from a name or domain, when the site lists noneSocial Profile Finder

❓ Questions people ask

Does reading more pages cost more?

No. The charge is per website. Deeper crawls cost time, not money.

A site came back with no emails. Is that a bug?

Usually not. A lot of companies publish a form instead of an address now. Check contactForms and socialLinks on that row.

Why is one of my phone numbers missing or formatted oddly?

A locally written number needs defaultCountry to be read. Set it to match your list.

Do I need an account on the sites I scrape?

No, and it cannot use one. It sees what any visitor sees, so a page behind a login is out of reach.

Can I call it from code or connect it to an AI assistant?

Yes. The API tab has ready-made code for Python, JavaScript and the command line. For Claude, ChatGPT or another MCP client, connect https://mcp.apify.com/?tools=fetch-actor-details,dami_studio/contact-details-scraper. Either way the run happens on your Apify account at the same price.

These are details each site chose to publish, read the way a signed-out visitor sees them: no account, nothing private. An address or number that belongs to a person is still personal data under GDPR, Canada's PIPEDA and similar laws, so keep only what you have a reason to keep. Anti-spam laws, such as CASL in Canada, the EU's e-privacy rules and CAN-SPAM in the US, decide how you may contact anyone on your list, and some of them ask for consent before a marketing email. Each site's own terms still apply to what you do with it. Apify's write-up on the legality of web scraping is a good starting point, and we are not lawyers.

🆘 If something breaks

Open the Issues tab on the actor page. Send the website and the run ID. The errorCode on the diagnostic row, and pageErrors on a real row, usually name the problem between them.