Website Contact Extractor - Emails, Phones & Social Links avatar

Website Contact Extractor - Emails, Phones & Social Links

Pricing

from $3.20 / 1,000 website with contacts founds

Go to Apify Store
Website Contact Extractor - Emails, Phones & Social Links

Website Contact Extractor - Emails, Phones & Social Links

Email and phone scraper for websites: turn a list of sites into emails (MX-checked), phone numbers in E.164, social profiles, company name and address from JSON-LD. One row per site, contact pages found automatically. Pay only for sites with contacts.

Pricing

from $3.20 / 1,000 website with contacts founds

Rating

0.0

(0)

Developer

Andrew Boiko

Andrew Boiko

Maintained by Community

Actor stats

0

Bookmarked

2

Total users

1

Monthly active users

2 hours ago

Last modified

Categories

Share

Paste a list of websites and get one clean row per site with everything you need to reach the company: email addresses (with a DNS MX check), phone numbers in E.164 (+14155550123, with national format, country and mobile / fixed-line type), social profiles (LinkedIn, Facebook, Instagram, X, YouTube, TikTok, WhatsApp, Telegram and more), company name, description and postal address from the site's structured data.

You only give the homepage. The extractor reads it, then finds and reads the pages where contacts live - Contact, About, Imprint / Impressum, Legal notice, Team, Support - in 30+ languages, and merges everything it finds. No browser, no proxy, no API key: plain HTML fetching, fast and cheap.

Who is it for?

  • Sales and lead generation - turn a list of company domains (from Google Maps, directories, LinkedIn, your CRM) into emails and phones you can actually use.
  • Marketing and PR agencies - collect press and partnership contacts, social handles and company descriptions in bulk.
  • Data teams and AI agents - enrich a company table with contact channels; the output is structured JSON, ready for a CRM, a spreadsheet or an LLM.
  • Recruiters and researchers - find the right channel (email, phone, LinkedIn page) for thousands of companies in one run.

What you get

One row per website:

FieldExample
website, finalUrl, domainacme.com, https://www.acme.com/, www.acme.com
companyName, descriptionAcme Inc., Acme builds rockets for small businesses.
primaryEmail, primaryPhonehello@acme.com, +14155550123
emails[]email, domain, onSiteDomain, isRoleAddress (info@, sales@ ...), foundInMailto, mxValid, sources (pages where it was found)
phones[]e164, international, national, country, type (MOBILE, FIXED_LINE, TOLL_FREE ...), foundInTelLink, sources
socialLinkslinkedin, facebook, instagram, x, youtube, tiktok, pinterest, threads, github, telegram, whatsapp, discord, vimeo, medium, snapchat, bluesky (arrays of profile URLs; share buttons are ignored)
linkedin, facebook, instagram, x, youtube, tiktokfirst profile of each network, handy for spreadsheets
addresses[], organizationpostal address and Organization / LocalBusiness data from JSON-LD (name, legal name, telephone, email, sameAs)
pagesCrawled, contactPageUrl, hasContacts, error, scrapedAtrun details per site

Emails are de-duplicated and lower-cased; obvious junk (image names, example.com, tracking addresses) is dropped. Obfuscated emails such as name [at] company [dot] com are recognized. Phone numbers are parsed with Google's libphonenumber: the country is taken from your input, otherwise from the site's domain (.de, .fr, .co.uk ...), the page language or the structured address, and numbers with a + prefix are always recognized.

Example output (shortened)

{
"website": "acme.com",
"finalUrl": "https://www.acme.com/",
"companyName": "Acme Inc.",
"primaryEmail": "hello@acme.com",
"primaryPhone": "+14155550123",
"emails": [
{ "email": "hello@acme.com", "onSiteDomain": true, "isRoleAddress": true, "foundInMailto": true, "mxValid": true, "sources": ["https://www.acme.com/contact"] },
{ "email": "jane.doe@acme.com", "onSiteDomain": true, "isRoleAddress": false, "foundInMailto": false, "mxValid": true, "sources": ["https://www.acme.com/team"] }
],
"phones": [
{ "e164": "+14155550123", "international": "+1 415 555 0123", "national": "(415) 555-0123", "country": "US", "type": "FIXED_LINE_OR_MOBILE", "foundInTelLink": true, "sources": ["https://www.acme.com/contact"] }
],
"socialLinks": { "linkedin": ["https://www.linkedin.com/company/acme"], "x": ["https://twitter.com/acme"] },
"addresses": [{ "streetAddress": "1 Market St", "addressLocality": "San Francisco", "addressRegion": "CA", "postalCode": "94105", "addressCountry": "US" }],
"pagesCrawled": 6,
"contactPageUrl": "https://www.acme.com/contact",
"hasContacts": true
}

How to use it

  1. Paste your websites - one per line, domains or URLs, up to 10,000 per run.
  2. Optionally set Max pages per site (default 8; 1 = homepage only, 30 = deep) and a default country for phone numbers.
  3. Click Start. Download the results as JSON, CSV or Excel, or read them through the API.

Tip: for a quick preview run 20-50 sites first, then the full list. Everything already found stays in the dataset even if you stop a long run early.

Pricing

You pay only for websites where at least one contact was found (an email, a phone number or a social profile):

EventPriceWhen
site-with-contacts$0.004 ($4 per 1,000 sites)one website with at least one email, phone or social link
Actor start$0.00005once per run

Sites without any contacts, unreachable sites and invalid entries are free. Platform usage (CPU, memory, requests) is included. Maximum cost per run is respected: once reached, no further sites are started and everything already processed is saved.

Compared with per-page pricing ($0.002 per page elsewhere), one site here costs the same as two pages - while up to 30 pages per site are read.

Integrations and API

Run it from the Apify Console, on a schedule, or from code (Node.js, Python, cURL) with the Apify API; export to Google Sheets, Make, Zapier, n8n, Airbyte, Slack or any webhook through Apify integrations. The dataset is available as JSON, CSV, Excel, XML and HTML.

import { ApifyClient } from 'apify-client';
const client = new ApifyClient({ token: 'YOUR_APIFY_TOKEN' });
const run = await client.actor('tiger19935/website-contact-extractor').call({ websites: ['acme.com', 'example.org'] });
const { items } = await client.dataset(run.defaultDatasetId).listItems();

FAQ

Does it need a browser or a proxy? No. Pages are fetched as plain HTML, which is fast and works for the vast majority of business websites. If a site blocks cloud IPs, enable Apify Proxy in the input.

Does it respect websites' rules? Yes. The crawler stays on each site's own domain, reads at most the number of pages you allow, follows robots.txt and only collects contact information the website publishes to its visitors.

Why is a phone number missing or wrong? Numbers without an international prefix are ambiguous. Set Default country when your sites are from one country, or rely on the automatic detection (domain, page language, structured address).

What does mxValid mean? true = the email domain has mail servers (DNS MX record), false = it cannot receive mail, null = the DNS lookup did not answer in time. It is a domain-level check, not a mailbox check.

Can I get one row per email instead of one row per site? Use the dataset's CSV export with the emails array, or flatten the JSON in your tool; each email keeps its sources.

Something missing? Open an issue in the Issues tab - new social networks, extra fields and language patterns are welcome.

More tools by the same author