Website Contact & Social Extractor (Emails, Phones, Socials)
Pricing
from $0.80 / 1,000 page scanneds
Website Contact & Social Extractor (Emails, Phones, Socials)
Extract emails, phone numbers and social profile links (Facebook, Instagram, LinkedIn, X, TikTok, YouTube, WhatsApp, Telegram) from any list of websites. Plain HTTP, no browser, respects robots.txt. $0.80 per 1,000 pages scanned, no per-lead fee.
Pricing
from $0.80 / 1,000 page scanneds
Rating
0.0
(0)
Developer
subimpact
Maintained by CommunityActor stats
0
Bookmarked
3
Total users
2
Monthly active users
11 hours ago
Last modified
Categories
Share
Extract contact details from a list of company websites or bare domains. For each site the actor fetches the start page and up to 5 same-domain pages (configurable), then returns emails, phone numbers and social profiles in one dataset row per site. It is plain HTTP: no headless browser, no Playwright, no Puppeteer.
What it finds
- Emails from
mailto:links and visible text, including simple obfuscations such asname [at] domain [dot] comand Cloudflaredata-cfemailvalues. Image file names, version strings and placeholder addresses such asemail@domain.com,you@email.com,name@example.com,@sentryand@wixpress.comare filtered out. - Phone numbers from
tel:links and common international or national text formats. Each phone keeps the raw string and a normalised value. - Social profiles for Facebook, Instagram, LinkedIn (company and
in/profiles), X/Twitter, TikTok, YouTube, Pinterest, Threads, WhatsApp and Telegram. Share, intent and tracking links are removed. - JSON-LD
OrganizationandLocalBusinessvalues foremail,telephoneandsameAs. - Contact pages first: links whose URL or anchor text mentions contact, about, team, support, legal, impressum, kontakt or hubungi are fetched before other same-domain pages.
Input example
{"startUrls": [{ "url": "https://apify.com" },{ "url": "https://www.hartamas.com" }],"maxPagesPerSite": 5}
Bare domains such as hartamas.com work too. An empty input ({}) runs the default example, https://apify.com, so the actor always has something to do.
| Field | Default | What it does |
|---|---|---|
startUrls | [{"url": "https://apify.com"}] | Website URLs or bare domains. One row per domain; duplicate domains are collapsed. |
maxPagesPerSite | 5 | Pages fetched and scanned per site, including the start page. Range 1 to 50. |
maxItems | 10 | Global cap on website rows. The default keeps a default run under $0.05 in page charges at 5 pages per site. Range 1 to 1,000. |
concurrency | 10 | Sites processed at the same time. Pages within one site are fetched one at a time. Range 1 to 50. |
outputPerPage | false | Also push one row per fetched page. Page rows are not charged separately. |
respectRobotsTxt | true | Check robots.txt before fetching a page and skip disallowed URLs. |
proxyConfiguration | { "useApifyProxy": false } | Direct requests by default. Enable Apify datacenter or residential proxy if target sites block Apify IP ranges. A proxy failure fails the request and never falls back to a direct request. |
Output example
This is a real site row from the example input.
{"rowType": "site","inputUrl": "https://apify.com","domain": "apify.com","pageUrl": null,"pageTitle": null,"status": "success","emails": ["hello@apify.com"],"phones": [],"socials": {"facebook": [],"instagram": [],"linkedin": ["https://linkedin.com/company/apify"],"x": ["https://x.com/apify"],"tiktok": ["https://tiktok.com/@apifytech", "https://tiktok.com/@apifyoffice"],"youtube": ["https://youtube.com/apify"],"pinterest": [],"threads": [],"whatsapp": [],"telegram": []},"pagesScanned": 5,"pagesWithContacts": ["https://apify.com/","https://apify.com/about","https://apify.com/contact","https://apify.com/contact-sales","https://apify.com/actors"],"httpStatus": null,"error": null,"scrapedAt": "2026-10-24T04:53:14.503Z"}
The same run returned a hartamas.com row with 9 emails (including info@hartamas.com and asset@hartamas.com), 12 phone entries and 7 social profiles. Phone entries have this shape:
{ "raw": "+603 7839 5617", "normalised": "+60378395617" }
Row fields
| Field | Meaning |
|---|---|
rowType | site for one website row, page for an optional per-page row. |
inputUrl | The URL or domain exactly as supplied in startUrls. |
domain | The website domain, with a leading www. removed. |
pageUrl, pageTitle | The page URL and HTML title on a page row. null on a site row. |
status | success when contacts were found, no-contacts when pages were scanned but nothing was found, error when the site could not be scanned. |
emails | Deduplicated, lowercase email addresses. Junk and placeholder addresses are removed. |
phones | Deduplicated { raw, normalised } objects. normalised keeps a leading + when the source had an international prefix, otherwise it contains national digits. |
socials | Profile URLs grouped by network. Every supported network is present, even when its array is empty. |
pagesScanned | Pages successfully fetched as HTTP 200 HTML and scanned. 1 on a page row. |
pagesWithContacts | URLs of the scanned pages that contained at least one email, phone or social profile. |
httpStatus | 200 on a page row, null on a site row. |
error | A readable failure reason on an error row, null otherwise. |
scrapedAt | ISO timestamp for the row. |
With outputPerPage: true, the dataset also gets one row per successfully fetched page. Page rows have rowType: "page", pageUrl, pageTitle, the page's own emails, phones and socials, and httpStatus: 200. They are not charged separately.
Pricing
| Event | Price | Charged when |
|---|---|---|
page-scanned | $0.0008 per page ($0.80 per 1,000 pages) | A page is successfully fetched as HTTP 200 HTML and scanned. Charged once per site row after that row is pushed, with count equal to the site's pagesScanned. |
- Error rows are never charged.
- A
no-contactsrow is a completed scan, so it is charged for the pages that were actually scanned. The row still tells you that the site published no emails, phones or supported social profiles. - There is no per-lead, per-email, per-phone or per-social-profile fee.
- Platform usage (compute, proxy, storage) is paid by you, the buyer.
- The example input (2 sites, up to 5 pages each) scans at most 10 pages, which is at most $0.008 in page charges. A default
maxItemsrun caps page charges at $0.04 (10 sites x 5 pages x $0.0008) before platform usage.
How this compares
| Actor | Base price | Extra fees | Platform usage |
|---|---|---|---|
subimpact/website-contact-extractor | $0.80 per 1,000 pages | None per lead or per profile | Paid by you |
vdrmota/contact-info-scraper | $2.00 per 1,000 pages | $0.10 per lead and $0.10 per social profile on its enrichment events | see listing |
lukaskrivka/google-maps-with-contact-details | $5.00 per 1,000 places | see listing | see listing |
vdrmota/contact-info-scraper had 3,694 users in the last 30 days at the time of checking. It is a general contact scraper. lukaskrivka/google-maps-with-contact-details starts from Google Maps search terms rather than website URLs, so its input and results are different from this actor.
Our base page price is $0.80 per 1,000 pages, below the $2.00 per 1,000 page base price of vdrmota/contact-info-scraper, and we do not add a per-lead or per-social-profile fee. Compare field coverage and result quality against those listings before choosing on price alone.
Prices are Apify Store list prices on the Free plan, checked 24 October 2026. Competitor prices can change. Check their listings.
How it works
The actor sends plain HTTP GET requests with a browser-compatible Accept header and a clear bot user agent. It follows redirects, accepts only text/html responses, caps each response at 3 MB and times out a request after 20 seconds. Transient failures (timeouts, network errors, 429 and 5xx) are retried up to three times with a fresh proxy session. A 404 is not retried. Pages are parsed without a DOM engine: links, visible text, JSON-LD blocks and data-cfemail attributes are read directly from the HTML.
Direct requests were measured to work for the example sites on Apify on 24 October 2026, so direct is the default. Enable a proxy only if a target site blocks the Apify IP ranges.
Limits and things to know
- At most 50 pages per site and 1,000 site rows per run. The defaults are 5 pages and 10 sites.
- Only HTTP 200 HTML pages are scanned. PDFs, images, JavaScript bundles and other file types are skipped.
- There is no JavaScript rendering. Contact details injected by client-side JavaScript into the page after load may be missed.
- Text phone numbers without a
+, spaces, dashes, dots or brackets are only taken fromtel:links and JSON-LD. This avoids treating order numbers, dates and coordinates as phones. - Emails and phones are capped at 100 per site. Social profiles are capped at 25 per network.
- The social extractor covers Facebook, Instagram, LinkedIn, X/Twitter, TikTok, YouTube, Pinterest, Threads, WhatsApp and Telegram. Other networks that appear in JSON-LD
sameAsare ignored. - There is no form submission, login, CAPTCHA solving or email deliverability check. An address may be stale or undeliverable.
- Only public
httpandhttpshosts are accepted. Local and private network addresses are rejected. robots.txtis respected by default. A site that disallows its start page produces an error row and is not charged.
Responsible use
Use this actor only on websites you are allowed to access. Keep respectRobotsTxt on unless you own the site or have permission to crawl it. Follow each site's terms and applicable privacy law. Contact details can be personal data, so make sure you have a lawful basis before outreach and do not use the output for spam. The actor does not verify that an email address is deliverable or that a phone number is still in service.