Contact Details Scraper - Emails, Phones & Socials
Pricing
from $1.44 / 1,000 websites
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
Maintained by CommunityActor stats
0
Bookmarked
10
Total users
4
Monthly active users
a day ago
Last modified
Categories
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.
| Input | Domains or website URLs, one per line |
| Output | One row per website: emails, phones, postal addresses, social profiles, contact forms, structured company and people data, each with its source pages |
| Ceiling | 20 pages crawled per site |
| Account needed | None |
| 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 get | Field |
|---|---|
| Email addresses, each with the pages it appeared on | emails |
| Phone numbers as written, plus the international form and country | phones |
| Postal addresses | addresses |
| Profiles on ten social platforms | socialLinks |
| Contact forms: where they post, the method and the field names | contactForms |
| Companies and named people from the site's own structured data | jsonLdOrganizations, jsonLdPeople |
| The site's title and description | title, description |
| Every page read, with its status and how many findings it gave | crawledPages, pagesCrawled, pageErrors |
| Counts, for sorting a long list | emailCount, phoneCount, socialLinkCount, addressCount, contactFormCount |
▶️ How to scrape contact details from websites
- Open Contact Details Scraper and click Try for free.
- Paste your domains into Websites, one per line.
- Set Default phone country if your list is mostly one country. It makes the phone numbers usable.
- Raise Maximum pages per site if you want a deeper look, then click Start.
- 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"}
| Field | Default | What it is |
|---|---|---|
websites | none | Domains 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. |
startUrls | none | The Apify request-list format, if that is what you already have. Combine it with websites freely. |
maxPagesPerSite | 6 | 1 to 20. More pages finds more and takes longer, and it does not change what you pay. |
defaultCountry | none | A 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. |
maxConcurrency | 5 | 1 to 20 sites at once. Each site is still crawled one page at a time. |
respectRobotsTxt | true | Skips pages the site asks crawlers not to read. |
requestTimeoutSecs | 12 | 3 to 45 seconds per page, body included. |
maxResponseSizeKb | 1536 | 128 to 5120. A page bigger than this is skipped. |
proxyConfiguration | off | Optional 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": []}
| Field | How to read it |
|---|---|
sourcePages | On every finding. When someone asks where an address came from, you point at the page instead of checking it again by hand. |
phones | The number as written, plus e164 and country once it has been read. That reading leans on defaultCountry for locally written numbers. |
contactForms | The 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, jsonLdPeople | Pulled from the site's own structured data, exactly as the site describes itself. |
pageErrors | Pages that could not be read, each with its own code, such as ROBOTS_DENIED for a page the site asked crawlers to skip. |
domain | The 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.
| Row | How to spot it | Charged |
|---|---|---|
| A site | ok: true and a domain | yes |
| The sample row | _sample: true | no |
| A diagnostic | ok: false and an errorCode | no |
| Code | What it means |
|---|---|
BAD_INPUT | Nothing usable in websites or startUrls, or one entry that is not a website. |
NO_CONTACTS | The site loaded fine and published nothing this actor recognises. |
NO_RESULTS | Nothing on that site could be read. Often a domain that redirects somewhere else, or a site that asks crawlers to stay out. |
UNSAFE_URL | The 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_SERVED | This website was not served this run. Re-run it later. Until 12 October 2026 this code was called BLOCKED. |
CHARGE_LIMIT | Your maximum cost could not pay for one site, so nothing was crawled. |
INTERNAL_ERROR | Something 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:
- Run Yellow Pages US Scraper for a trade and a city, and copy the
websitecolumn. Some listings have none. - Paste those sites into
websiteshere withdefaultCountryset toUS.
🚧 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 want | Use |
|---|---|
| Emails, phones and socials from a list of websites | This one |
| Local businesses with phone, address and website, to feed in here | Yellow Pages US Scraper |
| Local businesses on Google Maps | Google Maps Scraper |
| Contact details off a Facebook Page | Facebook Page Contact Info Scraper |
| Contacts and tech stack for Shopify stores only | Shopify Store Leads |
| Social profiles from a name or domain, when the site lists none | Social 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.
Is collecting contact details from websites legal?
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.