Scrape Business Emails, Phones and Social Profiles from Any Website
How to extract contact information from a list of company domains at scale — emails, phone numbers, LinkedIn, X, Instagram and more — with no API key.
The actor referenced in this article. Pay only for results delivered.
Finding the contact details for a list of target companies is genuinely tedious: open each website, hunt through the footer, check the /contact page, try to find LinkedIn. For ten companies that is ten minutes. For a thousand it is a week of grunt work.
The Website Contact Finder crawls each domain automatically — homepage, /contact, /about, /team, and footer-discovered links — and extracts every email address, phone number, and social profile link it finds. No API key, no browser required.
What It Extracts Per Domain
For each domain you supply, the actor returns:
- emails — from
mailto:links, regex extraction, and inline text. Junk addresses (no-reply, image hashes, framework artifacts) are filtered automatically. - phones — from
tel:links and free-text regex, normalised and length-validated (7–15 digits, E.164 compliant). - socials — structured object with one URL per platform:
linkedin,twitter,facebook,instagram,youtube. Only company/profile URLs are captured — share buttons and intent links are excluded. - pagesScanned — how many pages were crawled before the actor found or exhausted contacts.
Crawl a Domain List in Python
import os
from apify_client import ApifyClient
apify = ApifyClient(os.environ["APIFY_TOKEN"])
domains = [
"stripe.com",
"notion.so",
"linear.app",
"vercel.com",
"cal.com",
]
run = apify.actor("themineworks/website-contact-finder").call(run_input={
"domains": domains,
"maxPagesPerSite": 5,
})
results = list(apify.dataset(run["defaultDatasetId"]).iterate_items())
for r in results:
if r.get("_type") == "summary":
continue
print(f"\n{r['domain']}")
print(f" emails: {', '.join(r.get('emails', [])[:3])}")
print(f" phones: {', '.join(r.get('phones', [])[:2])}")
socials = r.get("socials", {})
for platform, url in socials.items():
print(f" {platform}: {url}")
Wire It Into a Claude Agent
The actor is available as an MCP tool. Add it to Claude Desktop:
{
"mcpServers": {
"contact-finder": {
"command": "npx",
"args": ["-y", "@apify/mcp-client"],
"env": {
"APIFY_TOKEN": "your-token-here",
"MCP_ACTOR_URL": "https://mcp.apify.com/?tools=themineworks/website-contact-finder"
}
}
}
}
Then you can paste a list of company websites into Claude and ask it to return a structured CSV of contact details. Claude calls the actor, formats the output, and flags any domains that returned no contacts.
A practical pattern: combine Website Contact Finder with the B2B Leads Finder for the same domain list. Contact Finder gives you the generic company contact info (and the LinkedIn company page URL); B2B Leads gives you individual person-level contacts at the same company. Together they give you both channels — the public-facing address and the named decision-maker.
What It Will and Will Not Find
It will find contacts that are linked from or visible on publicly accessible pages. Most B2B company sites have at least a hello@ or info@ address, a phone number in the footer, and a LinkedIn company page in the header.
It will not find contacts on:
- Login-walled or member-only pages (the actor runs as an anonymous visitor)
- JavaScript-heavy SPAs that render content only after complex user interactions (it uses plain HTTP, not a browser)
- Cloudflare-protected sites that block non-browser user agents
For JavaScript-heavy sites pair it with RAG Crawler, which uses Playwright to render pages before extraction.
Pricing and Charging Logic
Each domain that returns at least one contact costs $0.004. Domains that crawl successfully but yield no contacts are never charged — you only pay for results you can actually use.
At scale: 1,000 domains with contacts = $4. For most sales prospecting workflows that is roughly the cost of one minute of a salesperson’s time.
Frequently Asked Questions
Why did some domains return no contacts?
Several reasons: the site may block non-browser requests (Cloudflare, Vercel’s bot protection), contact info may only appear on pages not reachable from the homepage without JavaScript, or the company genuinely does not publish contact details publicly. The domain still appears in output with empty arrays — it is not an error.
Does it follow redirects?
Yes. HTTP → HTTPS redirects and www → apex redirects are followed automatically (up to 5 hops). The crawler normalises the domain before crawling so http://www.stripe.com and stripe.com both resolve to the same root.
Can I supply full URLs instead of domains?
Yes. The actor normalises any URL string — it strips the protocol and www prefix, extracts the hostname, and crawls from there. https://www.stripe.com/enterprise becomes stripe.com internally.
Explore the scraper referenced in this article — see inputs, outputs, and pricing, then run it on Apify.
Airbnb Scraper: Listing Prices, Ratings, and Availability Without the API
Airbnb has no public listings API. Here's how to pull nightly price, rating, superhost status and coordinates from Airbnb search results using Python.
Maps Leads: Verified Email Extraction from Google Maps Business Listings
How to pull B2B leads from Google Maps with MX-verified emails, past the official API's 120-result cap, and pay only for contactable businesses.
Realtor.com Scraper: Property and Agent Data Without the MLS Paywall
Scrape Realtor.com listings in Python — price, beds, baths, county, and the listing agent + brokerage office on every record. No login, no API key.