Website Contact Info Scraper: Emails, Phones & Social Links avatar

Website Contact Info Scraper: Emails, Phones & Social Links

Pricing

from $3.50 / 1,000 scanned websites

Go to Apify Store
Website Contact Info Scraper: Emails, Phones & Social Links

Website Contact Info Scraper: Emails, Phones & Social Links

Get the emails, phone numbers (E.164), social profiles, address and company name that company websites publish. Reads the home page and contact pages, decodes Cloudflare-protected emails, ranks on-site contacts first. One row per website; enrich any lead dataset.

Pricing

from $3.50 / 1,000 scanned websites

Rating

0.0

(0)

Developer

Charles Markette

Charles Markette

Maintained by Community

Actor stats

0

Bookmarked

1

Total users

1

Monthly active users

a day ago

Last modified

Categories

Share

Website Contact Info Scraper visits company websites and returns the contact details each one publishes: email addresses, phone numbers (formatted as E.164), social profiles (LinkedIn, X/Twitter, Facebook, Instagram, YouTube, TikTok, GitHub, Pinterest, Threads), the postal address and the company name. It reads the home page first, then the pages most likely to hold contact details (Contact, Impressum, About, Team, Support, Legal, Locations, in several languages), up to the page budget you set. You get one row per website, with the page each email and phone was found on. Paste a list of websites, or point it at any Apify dataset of leads or companies and the contact columns are added next to each item.

Why this Actor

  • Reads more than plain text. mailto: links, plain-text addresses, Cloudflare-protected emails ([email protected] placeholders are decoded), simple obfuscations such as name [at] company [dot] com or name(at)company.com, tel: links, and the company's own schema.org JSON-LD (Organization / LocalBusiness: name, phone, email, address, social profiles).
  • Filters the junk. Image file names that look like emails (logo@2x.png), placeholders (you@example.com), error-tracking addresses (Sentry, Wix), no-reply addresses and other non-contacts are dropped. Phone numbers in page text are only taken from the home page and contact-like pages, and only when a label such as Phone, Tel, Call, Fax, Mobile, Telefon or Tél is right in front of them, so order numbers, prices and IDs aren't reported as phones. Every phone is format-checked with Google's libphonenumber (a valid number format, not proof the line works) and returned in E.164 (+14155550132).
  • Profile links, not share buttons. Share buttons, tweet intents, Facebook sharer and plugin links, posts and videos, and the platforms' bare home pages are left out. Profile URLs are cleaned (tracking parameters and trailing slashes removed) and grouped by platform.
  • Polite. It reads robots.txt and skips disallowed pages (you can turn that off), sends at most 2 requests at a time to a website, retries busy servers with backoff, and names itself in its User-Agent (ContactInfoScraper/1.0; +https://apify.com/charlesmarkette).
  • Best contacts first. Emails on the website's own domain come first, then emails seen on contact-like pages, then the rest; phones from tel: links and the site's JSON-LD come first. primaryEmail and primaryPhone give you the single best pick for each website.
  • One clear row per website. Websites that can't be read get a row too, with status: "failed" and a plain-English error, and they are free.

Use cases

  • Lead enrichment: add emails, phones and LinkedIn pages to a list of company websites from Google Maps, a directory or a CRM export.
  • Sales and partnership outreach: find the published sales, support or press address of each prospect.
  • Data cleaning: check which companies in your list publish a phone number or address, and where.
  • Market research: see which social platforms the companies in a niche are on.

How to use it

  1. Add Websites (home page URLs or bare domains such as example.com), and/or pick a Dataset to enrich and set URL field to the field that holds the website (dotted paths such as company.website work).
  2. Optionally set Max pages per website (default 6) and Default country for phone numbers (default US; used for numbers written without a + country code).
  3. Run it. Export the results as CSV, Excel or JSON, or chain the run into an integration.

Input example

{
"startUrls": ["https://www.python.org", "apify.com"],
"maxPagesPerSite": 6,
"defaultCountry": "US",
"respectRobotsTxt": true
}

Output example (illustrative)

{
"url": "acme-widgets.com",
"domain": "acme-widgets.com",
"companyName": "Acme Widgets LLC",
"primaryEmail": "sales@acme-widgets.com",
"primaryPhone": "+14155550132",
"emails": ["info@acme-widgets.com", "sales@acme-widgets.com"],
"emailsOnSiteDomain": ["info@acme-widgets.com", "sales@acme-widgets.com"],
"phones": ["+14155550132", "+442079460958"],
"socials": {
"linkedin": ["https://www.linkedin.com/company/acme-widgets"],
"x": ["https://x.com/AcmeHQ"],
"facebook": ["https://www.facebook.com/acmewidgets"],
"instagram": [],
"youtube": ["https://www.youtube.com/@acmevideos"],
"tiktok": [],
"github": [],
"pinterest": [],
"threads": []
},
"address": "1 Main St, Springfield, IL 62701, US",
"addressParts": {"streetAddress": "1 Main St", "addressLocality": "Springfield", "addressRegion": "IL", "postalCode": "62701", "addressCountry": "US"},
"contactPageUrls": ["https://acme-widgets.com/contact-us", "https://acme-widgets.com/about"],
"pagesScanned": 6,
"sources": {
"info@acme-widgets.com": "https://acme-widgets.com/",
"sales@acme-widgets.com": "https://acme-widgets.com/contact-us",
"+14155550132": "https://acme-widgets.com/contact-us",
"+442079460958": "https://acme-widgets.com/about"
},
"status": "ok",
"error": null,
"scannedAt": "2026-10-16T12:00:00Z"
}
  • emails are ranked: addresses on the website's own registered domain first (subdomains count), then addresses seen on contact-like pages, then the rest. emailsOnSiteDomain is the on-domain subset. phones are ranked the same way: tel: links and JSON-LD first, then labelled numbers on contact-like pages, then labelled numbers on the home page.
  • primaryEmail is the first on-domain email seen on a contact-like page, else the first on-domain email, else null. primaryPhone is the first tel:/JSON-LD phone, else the first labelled phone on a contact-like page, else null.
  • companyName comes from the site's JSON-LD organisation name, then its og:site_name, then the cleaned home page title.
  • address and addressParts come from the site's JSON-LD (schema.org PostalAddress); they are empty when the site doesn't publish one there.
  • contactPageUrls lists the scanned pages that looked like contact, imprint, about, team, support, legal or locations pages.
  • sources maps each email and phone to the first page it was found on.
  • A run summary (websites read and failed, emails and phones found, pages scanned, why the run stopped) is saved as OUTPUT in the key-value store.

How much does it cost?

Pay per event: $0.005 per website scanned (one output row for a website where at least one page was read), Apify platform usage included, plus $0.005 per GB of Actor memory per run start (minimum one; $0.005 at the default 256 MB). Websites that couldn't be read at all are free: DNS errors, connection failures, bot-protection or error answers (403, 429, 503…), robots.txt disallowing the site, private or internal addresses, and input that isn't a website. A website that was read but publishes no contact details is still a scanned website and is charged.

Apify Store discounts: the price above is for Apify's Free plan. Paid plans pay less per 1,000 scanned websites: $4.50 on Starter, $4.00 on Scale, $3.50 on Business. The "from" price at the top of the Store page is the Business price.

Worked examples:

Examples use the Free-plan rate. Where an example doesn't add it, each run also has its run-start charge, counted per GB of Actor memory (minimum one; one at the default memory); Apify Proxy (where used) is billed separately.

  • 1,000 company websites, all reachable: 1,000 × $0.005 = $5.00.
  • 200 leads from a Google Maps run, 20 of which have a dead website: 180 × $0.005 = $0.90.

If you set a maximum cost per run, the Actor stops cleanly at that limit, and a run that is resumed continues after the rows already stored.

FAQ and limits

What does it find, exactly?

Only what the website itself publishes on the pages it reads. It does not guess emails from name patterns, verify that inboxes exist, look anything up in third-party databases, log in, fill in forms, or bypass CAPTCHAs or bot protection.

Why did a website return few or no results?

  • JavaScript-only sites: the Actor reads pages over plain HTTP, without a browser. Sites that build their content in the browser (some single-page apps and site builders) may show little or nothing to it.
  • Contact forms only: many companies publish a form instead of an email address.
  • Page budget: with the default of 6 pages, contact-like pages are read first; raise Max pages per website (up to 30) for large sites.
  • Images: emails or phones shown as pictures can't be read.

Why is a website "failed"?

The error column says why, in plain English: for example the domain doesn't resolve, the site answered 403 (usually bot protection), or robots.txt disallows crawlers. Failed websites don't incur the website-scanned charge; a new run still has its start fee.

The results include other companies' emails or phones. Why?

Some websites show sample or customer data on their pages: demo tables, example scrapes, case studies, partner lists. The Actor reports what the pages publish, but ranks such addresses after the site's own and never uses them for primaryEmail. Turn on Only emails on the website's own domain (onlySiteDomainEmails) to drop every email that isn't on the website's registered domain (subdomains count, and so do domains of the email addresses in the site's own JSON-LD organisation data). Labelled phone numbers in page text are only taken from the home page and contact-like pages for the same reason.

Which phone numbers are kept?

Numbers in tel: links and in the site's JSON-LD telephone (from any page read), and numbers in the text of the home page and contact-like pages that follow a phone label. Each must be a valid number for its country; numbers without a + country code are read with your Default country.

Does it leave the website?

No. It reads pages of the website's own host only (www.example.com and example.com count as one). Turn off Stay on the website's own host to also read subdomains such as help.example.com. Links to other sites are not followed, except that social profile links are collected.

Use responsibly

This Actor collects business contact details that websites publish publicly. How you use them is up to you and the law where you and your contacts are: privacy and anti-spam rules such as the GDPR (EU/UK) and CAN-SPAM (US) apply to storing and emailing personal data, including work addresses of named people. Respect opt-outs, keep only what you need, and don't use the results for unsolicited bulk messaging where that's not allowed.

Other tools by the same author

ActorUse it to
Phone Number Validator & FormatterGet the type (mobile, landline), carrier, region and national format of the phones found.
Domain WHOIS & DNS LookupAdd domain age, registrar and email provider (Google Workspace, Microsoft 365…) to the same list.
Bulk URL Status CheckerCheck first which lead websites load, where they redirect and whether their SSL certificate is valid.
Merge & Deduplicate DatasetsKeep only new companies between runs before scanning them.
Dataset Join & VLOOKUPJoin the contact rows back onto your original lead list by website or domain.
Google Sheets SyncSend the contact rows to a Google Sheet.
Send Email Report & AlertsGet the results by email, Slack, Discord, Teams or Telegram when the run finishes.
Broken Link CheckerCrawl a company's whole site for broken links and redirects.
Website Tech Stack DetectorSee which store platform, CMS and marketing tools each company website uses.
Career Page Jobs ScraperSee which companies on your list are hiring, and for what.

Phone parsing: phonenumbers (Google's libphonenumber). Domain parsing: tldextract with the Public Suffix List.