Website Contact Extractor: Emails, Phones & Socials avatar

Website Contact Extractor: Emails, Phones & Socials

Pricing

from $2.00 / 1,000 website with contacts

Go to Apify Store
Website Contact Extractor: Emails, Phones & Socials

Website Contact Extractor: Emails, Phones & Socials

Find emails, phone numbers and social media profiles (LinkedIn, Facebook, Instagram, X, YouTube, TikTok, WhatsApp, Telegram...) on any list of company websites. Checks the homepage and contact, about and imprint pages. Pay only for websites where contacts are found.

Pricing

from $2.00 / 1,000 website with contacts

Rating

0.0

(0)

Developer

Catalin Friptu

Catalin Friptu

Maintained by Community

Actor stats

0

Bookmarked

2

Total users

1

Monthly active users

a day ago

Last modified

Share

Give it a list of company websites and get back, for each one, every email address, phone number and social media profile published on the site: LinkedIn, Facebook, Instagram, X/Twitter, YouTube, TikTok, Pinterest, GitHub, Telegram, WhatsApp, Threads and Discord. One clean row per website, ready for a CRM, a spreadsheet or an outreach tool.

  • Pay only for results: $2 per 1,000 websites where contacts are found. Websites that are down, blocked or have no contact details cost nothing.
  • Looks where contacts actually are. It reads the homepage, then follows links to Contact, About, Team, Imprint/Impressum and Legal pages in 20+ languages (Kontakt, Contacto, Contatti, Despre noi, Контакты, Hakkımızda...).
  • Finds hidden emails too: mailto: links, plain text, info [at] company [dot] com spellings and Cloudflare-protected addresses.
  • Phone numbers in international format (E.164), from click-to-call links and page text. Only numbers that are valid for their country are kept, so dates, prices and order numbers don't sneak in. The country is taken from the domain (.de, .co.uk, .md...) or from your setting.
  • Real profiles, not share buttons. facebook.com/sharer, twitter.com/intent, YouTube videos and LinkedIn share links are dropped; profile URLs are cleaned and de-duplicated (github.com/acme/repo becomes github.com/acme).
  • The company's own email comes first (info@acme.com before acme.office@gmail.com).
  • Fast and light. Plain HTTP requests, 20 websites in parallel, no browser.

Who it's for

  • Sales and lead-generation teams enriching a list of company domains (from a CRM export, a directory or a Google Maps / OpenStreetMap scrape) with emails, phones and socials.
  • Agencies and recruiters building contact lists for outreach.
  • Data teams keeping company records up to date.

Input

FieldDefaultDescription
startUrlsWebsites or plain domains (acme.com). Several pages of one website count as one website.
maxPagesPerWebsite5Homepage + the most promising contact/about/team/imprint pages.
defaultCountryfrom domainTwo-letter code (US, GB, DE...) to read local phone numbers written without +country.
phonesFromTexttrueAlso read numbers from the page text, not only tel: links.
respectRobotsTxttrueSkip pages a website's robots.txt disallows.
maxConcurrency20Websites processed in parallel.
{
"startUrls": ["acme-dental.com", "https://www.example-bakery.co.uk/"],
"maxPagesPerWebsite": 5,
"defaultCountry": "US"
}

Output

One row per website. Lists are empty ([]) when nothing was found.

FieldDescription
input_url, url, domainWhat you gave, the homepage after redirects, and the domain without www..
title, descriptionThe homepage's title and meta description.
email, emailsThe best email (own domain first), and all of them.
phone, phonesThe first phone number and all of them, in E.164 format (+442079460958).
linkedin, facebook, instagram, twitter, youtube, tiktok, pinterest, github, telegram, whatsapp, threads, discordProfile URLs.
contact_pagesPages where something was found.
pages_crawledPages read on this website.
contacts_foundtrue if at least one email, phone or profile was found (these rows are the ones you pay for).
crawled_atUTC timestamp.
errorWhy a website could not be read (HTTP 403, ConnectError: ..., blocked by the site's robots.txt).

Example row from a real run (a restaurant website taken from OpenStreetMap):

{
"input_url": "https://www.armeniantaverna.co.uk/",
"url": "https://armenianrestaurant.co.uk/",
"domain": "armeniantaverna.co.uk",
"title": "Armenian Restaurant in Manchester, by Albert Square | Armenian Restaurant & Bar",
"description": "Armenian food in Manchester since 1968, facing the Town Hall by Albert Square. ...",
"email": "contact@armenianrestaurant.co.uk",
"emails": ["contact@armenianrestaurant.co.uk"],
"phone": "+441618349025",
"phones": ["+441618349025"],
"facebook": ["https://facebook.com/armenianrestaurantbar"],
"instagram": ["https://instagram.com/armenianrestaurantbar"],
"linkedin": [], "twitter": [], "youtube": [], "tiktok": [], "pinterest": [], "github": [],
"telegram": [], "whatsapp": [], "threads": [], "discord": [],
"contact_pages": ["https://armenianrestaurant.co.uk/"],
"pages_crawled": 1,
"contacts_found": true,
"crawled_at": "2026-10-24T03:01:45+00:00",
"error": null
}

The dataset has three views: Contacts, Leads (one email and phone per row, best for CSV/Excel) and All fields. Export to CSV, Excel or JSON, send it to Google Sheets or a CRM through Apify integrations, or read it from the API:

from apify_client import ApifyClient
client = ApifyClient("<YOUR_API_TOKEN>")
run = client.actor("malmurk/website-contact-extractor").call(run_input={
"startUrls": ["acme-dental.com", "example-bakery.co.uk"],
})
for row in client.dataset(run["defaultDatasetId"]).iterate_items():
print(row["domain"], row["email"], row["phone"], row["linkedin"])

Pricing

Pay per event:

EventPriceCharged for
website$2 per 1,000 websites ($0.002 each)A website on which at least one email, phone number or social profile was found.
Actor start$0.00005 per runOnce per run (per GB of memory).
  • Websites that fail to load, are blocked, or have no contact details are free (you still get a row with the reason).
  • The price is per website, not per page: reading 5 pages of a website costs the same as reading 1.
  • The run stops cleanly at the maximum charge you set for it.

10,000 websites with 6,000 hits cost $12.

FAQ

Why is a website missing an email I can see in my browser? The address may be drawn by JavaScript, shown as an image, or sit behind a contact form. This Actor reads the HTML the server sends (no browser), which keeps it fast and cheap. Try a higher maxPagesPerWebsite if the email is on a deeper page.

Why are there no phone numbers on my .com websites? A local number like (212) 555-0182 can only be read if the country is known. .com doesn't say which country, so set defaultCountry. Numbers with a +country prefix and click-to-call links are always read.

Does it use proxies or bypass bot protection? No. A website that blocks it gets an error row and is free. No logins, no CAPTCHA solving.

Is this legal? It reads publicly published business contact details from websites you choose, and respects robots.txt. Email addresses and phone numbers can still be personal data (GDPR, CCPA, CAN-SPAM, ePrivacy). You are responsible for having a lawful basis to store and use them, and for honouring opt-outs.

Can I feed it the output of another Actor? Yes. Pass a list of website URLs (from Google Maps, OpenStreetMap, a directory scraper or your CRM) as startUrls, or chain it with an Apify integration.

Limitations

  • No JavaScript rendering, so contacts that only appear after scripts run are missed.
  • Contact forms, images of emails and PDFs are not read.
  • Personal social profiles linked from a website (e.g. a founder's LinkedIn) are reported like company profiles.

Local development

python -m venv .venv && .venv/Scripts/pip install -r requirements-dev.txt # Linux/macOS: .venv/bin/pip
python -m pytest -q

Phone parsing uses phonenumbers (Apache-2.0), HTML parsing lxml (BSD), robots.txt Protego (BSD-3).