Company websites already publish their social profiles and contact details; the annoying part is collecting them for a whole list of domains. Here is a small Python script that does it through an Apify Actor billed per website ($2 per 1,000 sites, and sites that fail to load are not charged).
The script
import os, requests
TOKEN = os.environ["APIFY_TOKEN"]
URL = ("https://api.apify.com/v2/acts/siftwright~contact-details-extractor/"
"run-sync-get-dataset-items")
sites = ["https://www.python.org", "https://github.com", "https://www.mozilla.org"]
r = requests.post(URL, params={"token": TOKEN, "timeout": 90},
json={"startUrls": sites, "maxPagesPerDomain": 3}, timeout=120)
r.raise_for_status()
for row in r.json():
print(row["domain"], row["status"], row["emails"], row["phones"],
row["linkedin"], row["twitter"])
Real output
I ran exactly this on 2026-10-19. Each site returned status: "ok" with 3 pages scanned:
| domain | twitter / X | emails | phones | ||
|---|---|---|---|---|---|
| www.python.org | python-software-foundation | ThePSF | none | none | none |
| www.mozilla.org | mozilla-corporation | none | mozilla | none | none |
| github.com | github | github | github | none | none |
Note the empty email and phone columns: these three sites simply don't publish an address on the pages scanned, and the Actor does not guess. Smaller company sites with a visible contact page are where emails and phones show up. Raise maxPagesPerDomain if the contact page is deeper in the site.
Pricing and limits
- One charge per website that loads,
$0.002each; dead domains are free. - It reads public pages only: no logins, no proxies by default, so heavily protected sites may return a failed status.
- Fields per site:
emails,phones,facebook,twitter,linkedin,instagram,youtube,pagesScanned.
Try it: Contact Details Extractor on Apify. It also works from AI agents through Apify's MCP server. More tools: siftwright.com.
Top comments (0)