Website Contact Scraper
Company emails, phones and social profiles from any website (role emails only, GDPR-friendly). From $0.003 / website, pay per result, no browser, no login.
▶ Run it on Apify · Python example · All scrapers
Turn a list of websites into a clean list of company contacts. For each website this contact scraper reads the home page and the contact / about / legal pages, then returns the company’s contact emails, phone numbers, social media profiles, postal address, logo and the technologies the site uses — as JSON, CSV or Excel. No browser, so it is fast and costs a fraction of a cent per website.
✅ Company emails (info@, contact@, sales@, reservas@…) — only the addresses a business publishes for customers
✅ Phone numbers from click-to-call links, structured data and the page text, normalized (+351213218100)
✅ Social profiles: Facebook, Instagram, LinkedIn company page, X/Twitter, YouTube, TikTok, Pinterest, GitHub
✅ Postal address, company name and logo from schema.org data
✅ Technologies: WordPress, Shopify, Wix, Squarespace, Webflow, PrestaShop, HubSpot, Google Analytics, Meta Pixel, Stripe…
✅ Contact page URL for each website
✅ Finds contact pages in any language (contact, contactos, kontakt, impressum, sobre-nós, à-propos…)
✅ Pay only for websites where contacts are found — dead or empty websites are free
🛡️ GDPR-friendly by design
This Actor collects business contact details only: role-based mailboxes (info@, sales@, support@…) of the website’s own domain, company phone numbers and company social pages. It does not collect personal email addresses (firstname.lastname@), personal LinkedIn profiles or emails of other websites quoted on the page. That keeps your lead lists cleaner and much easier to use under GDPR and similar laws.
🚀 Why this contact scraper is different
| This Actor | Typical contact scrapers | |
|---|---|---|
| Price | $0.003 per website (up to 5 pages included) | $0.002 per page (≈ $0.01 per website) |
| Charged when nothing is found | Never | Usually |
| One clean row per website | Yes, deduplicated across pages | One row per page to merge yourself |
| Address, logo and technologies | Yes | Rarely |
| Personal emails | Not collected (GDPR-friendly) | Collected |
| Fake / example numbers filtered | Yes | No |
💡 Use cases
- Lead generation: enrich a list of company websites (from Google Maps, directories, trade fairs, CRM exports) with emails, phones and social profiles.
- Agencies: find businesses on WordPress, Wix or Shopify, or without analytics, and pitch them the right service.
- Sales & CRM enrichment: fill in missing phone numbers, addresses and LinkedIn company pages.
- Market research: map the technologies and social presence of an industry.
- Partnerships & PR: get the right contact mailbox (press@, partnerships@) of each company.
🛠️ How to use it (3 steps)
- Paste websites or domains, one per line (from a spreadsheet, Google Maps results, a directory…).
- Keep 5 pages per website (home + contact + about + legal pages) or raise it.
- Click Start and download your contacts as CSV, Excel or JSON, or fetch them through the API.
📥 Input example
{
"startUrls": ["hotelavenidapalace.pt", "https://www.apify.com", "example-bakery.de"],
"maxPagesPerSite": 5,
"concurrency": 10
}
📤 Output example (real run)
{
"url": "https://hotelavenidapalace.pt/",
"domain": "hotelavenidapalace.pt",
"companyName": "Hotel Avenida Palace",
"emails": ["reservas@hotelavenidapalace.pt"],
"phones": ["+351213218100"],
"socials": {
"facebook": "https://www.facebook.com/HotelAvenidaPalaceLisboa",
"instagram": "https://www.instagram.com/hotelavenidapalace"
},
"address": { "streetAddress": "Rua 1º Dezembro, 123", "addressLocality": "Lisboa", "postalCode": "1200-359", "addressCountry": "Portugal" },
"logo": "https://www.hotelavenidapalace.pt/media/hotel-avenida-palace-hotelhotel-avenida-palace-exterior_3.webp",
"technologies": ["Google Analytics", "Google Tag Manager", "Guestcentric website builder"],
"contactPage": null,
"pagesVisited": ["https://www.hotelavenidapalace.pt/", "https://www.hotelavenidapalace.pt/about"]
}
Websites without any contact detail, and unreachable websites, are listed in the run’s RUN_SUMMARY record — and not charged.
⚙️ Input parameters
| Field | Type | Default | Description |
|---|---|---|---|
startUrls |
array | ["https://www.apify.com"] |
Company websites or domains, one per line (example.com, https://www.example.pt). One result per website, up to 5,000 per run. |
maxPagesPerSite |
integer | 5 |
Home page plus contact, about and legal pages found on it. 5 finds almost everything. |
concurrency |
integer | 10 |
How many websites are processed at the same time. |
proxyConfiguration, maxRetries |
object, integer | Apify Proxy, auto | Proxy and retries; the defaults work for most runs. |
📋 Output fields
| Field | Type | Description |
|---|---|---|
url |
string | Website as given in the input |
domain |
string | Domain without www |
finalUrl |
string | Home page after redirects |
companyName |
string | Company / site name |
title |
string | Home page title |
description |
string | Meta description |
language |
string | Page language |
emails |
array | Role emails of the company (info@, contact@, sales@…) |
phones |
array | Phone numbers, normalized |
socials |
object | Company social profiles by network |
address |
object | Postal address from structured data |
logo |
string | Logo or share image URL |
technologies |
array | CMS, e-commerce, analytics and tools detected |
contactPage |
string | Contact page URL |
pagesVisited |
array | Pages read on the website |
Export as JSON, CSV, Excel, XML or HTML, or read it through the API.
💰 Pricing — pay only for websites with contacts
| What you run | Cost (free plan) |
|---|---|
| 100 websites | $0.30 |
| 1,000 websites | $3.00 |
| 5,000 websites | $15.00 |
Higher Apify plans pay less: $0.0025 (Bronze), $0.002 (Silver), $0.0015 (Gold and above). Platform usage and proxies are included. Set a maximum cost per run and the Actor stops cleanly when it is reached.
🔌 API & integrations
Python
from apify_client import ApifyClient # pip install "apify-client>=3"
client = ApifyClient("<YOUR_APIFY_TOKEN>")
run = client.actor("victorrodi/website-contact-scraper-api").call(
run_input={"startUrls": ["hotelavenidapalace.pt", "apify.com"]}
)
for company in client.dataset(run.default_dataset_id).iterate_items():
print(company["domain"], company["emails"], company["phones"])
JavaScript / Node.js
import { ApifyClient } from 'apify-client';
const client = new ApifyClient({ token: process.env.APIFY_TOKEN });
const run = await client.actor('victorrodi/website-contact-scraper-api').call({ startUrls: ['apify.com'] });
const { items } = await client.dataset(run.defaultDatasetId).listItems();
console.log(items);
cURL
curl -X POST "https://api.apify.com/v2/acts/victorrodi~website-contact-scraper-api/run-sync-get-dataset-items" \
-H "Authorization: Bearer $APIFY_TOKEN" -H "Content-Type: application/json" \
-d '{"startUrls": ["apify.com"]}'
Works with Google Sheets, HubSpot, Make, Zapier, n8n, Clay and MCP / AI agents (Claude, ChatGPT, Cursor) through Apify integrations — e.g. “Find the contact email and phone of these 20 hotels’ websites.”
🤖 Use it from AI agents (Claude, ChatGPT, Cursor…)
This Actor is available to AI assistants through the Apify MCP server. Add the server to Claude Desktop, Claude Code, Cursor or any MCP client, then simply ask:
“Find the contact email and phone of these 20 company websites and put them in a table.”
“Use victorrodi/website-contact-scraper-api to get the LinkedIn and Instagram pages of these shops.”
The clean, flat output is designed to be read directly by LLMs.
🛡️ Reliability
- Requests are paced and retried with a new IP and exponential backoff.
- If the site keeps blocking, the Actor switches to residential IPs automatically.
- One failing item never stops the run, and you are never charged for it.
- Every run writes a
RUN_SUMMARYrecord (results, failures, retries, blocks). - Measured on 20 real websites in 24 seconds: 13 with contacts, 2 without any, 5 behind anti-bot walls (not charged).
More examples and docs for all our Actors: Vicshock/trendpulse-scrapers.
📌 Tips
- Chain it after a Google Maps scraper: export the
websitecolumn and paste it here. - Big brands often hide contacts behind forms; small and medium businesses publish them — that is where this Actor shines.
- Some websites block all bots (Cloudflare “Under attack” mode); they are listed as unreachable and not charged. We tested a real-browser fallback: big marketplaces and job sites (Glassdoor, Indeed, Etsy, G2…) block it too from cloud servers, so this Actor stays fast and cheap and focuses on what it does best: company and small-business websites.
❓ FAQ
Does it collect personal data? It is built not to: only role-based company mailboxes of the website’s own domain, company phones and company social pages. You remain responsible for how you use the data (GDPR, CAN-SPAM, ePrivacy).
Why is an email I can see on the site missing? It is either a personal address (firstname@…), an address of another domain, or it is only shown inside an image or a contact form.
How many websites per run? Up to 5,000. Split bigger lists into several runs.
💬 Support
Missing a field or found an issue? Open an issue in the Issues tab — it is answered fast.