Contact Details Scraper - Emails, Phones & Socials
Pricing
from $1.25 / 1,000 results
Contact Details Scraper - Emails, Phones & Socials
Crawl any website or domain and extract clean business contact details: emails (including Cloudflare-protected and [at]/[dot]-obfuscated), validated phone numbers (E.164), and social profiles. High recall, low junk. Export JSON/CSV/Excel.
Pricing
from $1.25 / 1,000 results
Rating
0.0
(0)
Developer
Shahryar
Maintained by CommunityActor stats
0
Bookmarked
2
Total users
1
Monthly active users
2 days ago
Last modified
Categories
Share
Contact Details Scraper – Email, Phone & Social Media Scraper
A fast contact details scraper that crawls any list of websites or domains and extracts clean business contact details: email addresses, validated phone numbers, and social-media profiles — one tidy row per domain, ready to export to JSON, CSV, or Excel.
Built for lead generation, sales prospecting, recruiting, market research, and CRM enrichment. Use it as a no-code contact scraper in the Apify Console, or call it programmatically through the Apify API — no target-site API key required, because it reads the public web directly. It runs purely over HTTP (no headless browser) so it's fast and cheap, with extraction logic tuned for high recall and low junk.
Pairs perfectly with the Google Maps Scraper for end-to-end local lead generation: pull business websites from Google Maps, then feed them here to harvest emails, phones, and socials.
What it does
- 📧 Emails – from
mailto:links, page text, Cloudflare-protected elements (data-cfemail//cdn-cgi/l/email-protection), HTML-entity-encoded addresses, and[at]/[dot]-obfuscated text. - 📞 Phones – from
tel:links and page text, validated with Google's libphonenumber. Invalid numbers are dropped, so you don't get dates, prices, or zip codes masquerading as phones. Output keeps both E.164 and the raw on-page format. - 🔗 Socials – LinkedIn, Twitter/X, Facebook, Instagram, TikTok, and YouTube profile URLs.
- 🎯 Smart crawl – fetches each homepage, then prioritizes contact/about/imprint/kontakt/team/legal pages before anything else, within your page and depth caps.
- 🧹 Junk filter – removes asset filenames (
logo@2x.png), tracking/CDN/Sentry/Wix addresses,noreply@, andexample.complaceholders. - 🧱 One clean row per domain – emails and phones de-duplicated across all crawled pages.
Why this scraper
Most contact scrapers miss the addresses that matter most and pad your output with noise. This Actor specifically fixes the common complaints:
| Common pain point | How this Actor handles it |
|---|---|
Cloudflare-obfuscated emails come back as [email protected] | Decodes data-cfemail / email-protection XOR payloads natively — no browser needed. |
[at] / [dot] / entity-encoded emails are missed | De-obfuscated before matching. |
| Phone numbers are full of false positives | Validated with libphonenumber; invalid numbers are discarded. |
Output is full of noreply@, asset files, example.com | Aggressive junk filter drops them. |
| German/EU sites hide contacts on Impressum/Kontakt | Those paths are first-priority in the crawl. |
Honest limitation: this is an HTTP-first scraper (no JavaScript rendering in v1). Contact details that are injected only by client-side JavaScript after page load (e.g. a phone number rendered by a React widget with nothing in the HTML) may not be captured. Emails hidden behind Cloudflare's static obfuscation are captured, because that data is present in the HTML.
Example input
{"startUrls": [{ "url": "https://apify.com" }],"domains": ["stripe.com", "vercel.com"],"maxPagesPerDomain": 10,"maxDepth": 2,"sameDomainOnly": true,"extractEmails": true,"extractPhones": true,"extractSocials": true,"defaultPhoneCountry": "US","proxyConfiguration": { "useApifyProxy": true }}
Example output
One item per input domain:
{"type": "contact","domain": "example.com","url": "https://example.com/contact","emails": ["hello@example.com", "sales@example.com"],"phones": [{ "e164": "+14155552671", "raw": "(415) 555-2671" }],"socials": {"linkedin": "https://www.linkedin.com/company/example","twitter": "https://twitter.com/example","facebook": "https://www.facebook.com/example","instagram": "https://www.instagram.com/example","tiktok": null,"youtube": "https://www.youtube.com/@example"},"pagesScraped": 6,"scrapedAt": "2026-06-26T10:00:00.000Z"}
Output fields
Every item has type: "contact".
| Field | Type | Description |
|---|---|---|
type | string | Always "contact". |
domain | string | The registrable domain crawled (leading www. stripped). |
url | string | The most relevant source page (first contact/about page found, else the homepage). |
emails | string[] | De-duplicated, junk-filtered, lower-cased email addresses found across all crawled pages, sorted alphabetically. Empty [] if extractEmails is off. |
phones | object[] | Validated phone numbers, each { "e164": "+1...", "raw": "as shown on page" }. Empty [] if extractPhones is off. |
socials | object | Profile URLs keyed by network: linkedin, twitter, facebook, instagram, tiktok, youtube (each a URL or null). All null if extractSocials is off. |
pagesScraped | integer | How many pages were successfully fetched and parsed for this domain. |
scrapedAt | string | ISO 8601 timestamp of when the item was produced. |
Domains that could not be reached still produce a row (with empty results), so your output always has one item per input. Download the full dataset as JSON, CSV, Excel, or HTML from the Apify Console, or pull it via the Apify API.
Input reference
| Field | Type | Default | Description |
|---|---|---|---|
startUrls | array | — | Website URLs to crawl (full URLs or homepages). |
domains | array | — | Bare domains to crawl (e.g. stripe.com); merged with startUrls. |
maxPagesPerDomain | integer | 10 | Max pages to fetch per domain (contact pages first). |
maxDepth | integer | 2 | Link hops from the homepage (0 = homepage only). |
sameDomainOnly | boolean | true | Only follow links on the input domain and its subdomains. |
extractEmails | boolean | true | Extract email addresses (incl. Cloudflare + obfuscated). |
extractPhones | boolean | true | Extract and validate phone numbers. |
extractSocials | boolean | true | Extract social-profile URLs. |
defaultPhoneCountry | string | — | ISO-2 country (e.g. US) for validating national-format numbers. Blank = only +CC numbers. |
proxyConfiguration | object | Apify proxy | Proxy settings. Datacenter is default; use residential for protected sites. |
Common use cases
- Lead generation & sales prospecting – turn a list of company domains into emails, phones, and socials.
- CRM / dataset enrichment – fill missing contact fields for accounts you already have.
- Recruiting & outreach – find company contact points at scale.
- Market research – build directories of businesses in a niche.
FAQ
Does this contact scraper need an API key? No. There is no target-site API key to obtain — the Actor crawls public web pages directly through the Apify proxy. The only credential involved is your own Apify token if you call the Actor through the Apify API.
Can I run it from the API instead of the UI? Yes. Start runs and fetch results programmatically via the Apify API or the Apify client libraries (JavaScript/Python). The input is the same JSON shown above, and the dataset can be exported as JSON, CSV, or Excel.
How does it decode Cloudflare-protected emails? Cloudflare's email obfuscation is a reversible single-byte XOR cipher embedded in the page (data-cfemail / email-protection#<hex>). The first byte is the key; each following byte XORed with the key is one character of the address. The Actor decodes this directly from the HTML — no browser required.
Why are some phone numbers missing? Numbers are validated with libphonenumber and dropped if invalid. National-format numbers without a country code can only be validated if you set defaultPhoneCountry. This is intentional — it trades a little recall for far fewer false positives.
Will it find JavaScript-rendered contacts? Not in v1. This is an HTTP-only scraper for speed and cost. Statically present data (including Cloudflare-obfuscated emails) is captured; data injected only by client-side JavaScript may be missed.
Which proxy should I use? The default datacenter proxy works for most sites. For Cloudflare-challenged or geo-restricted sites, enable residential proxies in proxyConfiguration.
How many results do I get? Exactly one aggregated item per input domain, with emails/phones de-duplicated across every page crawled for that domain.
Which social networks are detected? LinkedIn, Twitter/X, Facebook, Instagram, TikTok, and YouTube profile URLs. Share, intent, and login endpoints are skipped so you only get real profile links.
Can I limit cost on large lists? Yes. Lower maxPagesPerDomain (e.g. 5) and maxDepth (e.g. 1) — contact, about, and imprint pages are crawled first, so even small caps usually find what matters while keeping runs fast and cheap.
Responsible use & GDPR
This Actor collects contact information (including personal data such as names within email addresses) from publicly available web pages. You are responsible for using the output lawfully. In particular:
- Have a valid legal basis (e.g. legitimate interest) before processing personal data, and honour data-subject rights such as access and erasure under the GDPR, CCPA, and similar laws.
- Respect marketing/opt-out rules (GDPR, ePrivacy, CAN-SPAM, PECR) before sending outreach.
- Only scrape sites you are permitted to access, and follow each website's terms.
The Actor itself extracts only what is already published publicly and applies a junk filter (dropping noreply@, placeholders, and tracking addresses); it does not bypass logins or paywalls.