Bulk Website Contact Extractor – Emails, Phones & Socials
Pricing
from $5.00 / 1,000 result founds
Bulk Website Contact Extractor – Emails, Phones & Socials
Bulk-crawl a list of websites and get one lead record per domain: personal vs role emails, phones, WhatsApp links, social profiles, address and an A–D lead score. Works with Apify MCP and the API.
Pricing
from $5.00 / 1,000 result founds
Rating
0.0
(0)
Developer
Khadin Akbar
Maintained by CommunityActor stats
2
Bookmarked
197
Total users
5
Monthly active users
6 days ago
Last modified
Categories
Share
What is Bulk Website Contact Extractor – Emails, Phones & Socials?
Bulk Website Contact Extractor is an Apify Actor for users who already have a list of direct website URLs and want one structured contact record per URL. It accepts startUrls, crawls each URL independently, and returns fields such as emails, phones, whatsapp_links, social_links, company_name, lead_score, contact_page_url, and pages_crawled. The output is a CRM-ready dataset for lead enrichment, outreach preparation, and contact list review. This Actor is also usable through Apify MCP.
Best fit and connected workflows
This Actor fits workflows that begin with known websites rather than search queries. It routes naturally from spreadsheet exports, CRM domain lists, prospect lists, and other URL collections into one record per site.
It is a strong match when you want to:
- enrich company websites with public contact details,
- separate role inboxes and personal inboxes,
- collect phone numbers, WhatsApp links, and social profile URLs in one pass,
- sort records by
lead_score, - move structured records into Apify platform automations or Apify MCP workflows.
If your starting point is a direct website URL list, this Actor provides a focused crawl and one output record for each processed URL.
Which contact Actor fits? Use this Actor when you already have a list of website URLs. When you want to start from a keyword or search and find the websites first, use Contact Details Scraper instead.
Practical scenario
Maya, a sales operations specialist, has a spreadsheet of company websites from a conference list. She sends those URLs in startUrls and keeps followContactPages enabled. The Actor returns records with emails, phones, social_links.linkedin, whatsapp_links, lead_score, and contact_page_url.
Maya uses lead_score to sort the list. Records with A include both email and phone, while B and C show partial contact coverage. She then imports the dataset into her CRM and starts with the records that already include a public email address and a phone number.
Input fields
| Field | Type | Required | Purpose |
|---|---|---|---|
startUrls | array | Yes | Direct website URLs to crawl. Accepts plain URL strings or objects with a url key. |
maxPagesPerDomain | integer | No | Maximum pages to visit per input URL. The crawler prioritizes /contact, /about, /team, and /imprint before general pages. Default: 6. |
maxResults | integer | No | Maximum number of input URLs to process. Set to 0 to process all input URLs. Default: 1000. |
followContactPages | boolean | No | When enabled, the crawler follows contact, about, team, imprint, support, and equivalent multilingual pages before extracting. Default: true. |
proxyConfiguration | object | No | HTTP proxy settings. Use the default Apify datacenter proxies for most sites. |
Focused JSON input example
{"startUrls": [{ "url": "https://apify.com" },{ "url": "https://crawlee.dev" }],"maxPagesPerDomain": 3,"maxResults": 2,"followContactPages": true}
Output fields
One record is produced per input URL. The dataset schema includes the following fields.
| Field | Type | Purpose |
|---|---|---|
source_url | string | Original input URL that was crawled. |
domain | string | Cleaned hostname with www. removed. |
company_name | string or null | Business name extracted from site metadata, schema, footer copyright, or page title. |
page_title | string or null | Title of the first crawled page. |
emails | array | All unique email addresses found on the crawled pages. |
emails_personal | array | Individually owned email addresses. |
emails_generic | array | Role or team inboxes such as info@, hello@, or sales@. |
phones | array | All unique phone numbers found on the crawled pages. |
address | string or null | First physical address found on the site. |
social_links | object | Social profile URLs for supported platforms such as LinkedIn, Twitter/X, Facebook, Instagram, YouTube, TikTok, GitHub, Pinterest, Snapchat, Threads, and Telegram. |
whatsapp_links | array | Direct WhatsApp contact links found on the site. |
lead_score | string | A, B, C, or D based on the contact data found. |
contact_page_url | string or null | First crawled page that yielded contact data. |
pages_crawled | integer | Number of pages visited for the domain. |
scraped_at | string | ISO 8601 timestamp for the record. |
Illustrative output record
{"source_url": "https://acme.com","domain": "acme.com","company_name": "ACME Corp","page_title": "ACME Corp - Contact Us","emails": ["hello@acme.com", "sales@acme.com"],"emails_personal": ["john.doe@acme.com"],"emails_generic": ["hello@acme.com", "sales@acme.com"],"phones": ["+1-800-555-0100"],"address": "123 Main St, Springfield, IL 62701","social_links": {"linkedin": "https://linkedin.com/company/acme-corp","twitter": "https://x.com/acmecorp","facebook": null,"instagram": null,"youtube": null,"tiktok": null,"github": null,"pinterest": null,"snapchat": null,"threads": null,"telegram": null},"whatsapp_links": ["https://wa.me/15551234567"],"lead_score": "A","contact_page_url": "https://acme.com/contact","pages_crawled": 4,"scraped_at": "2026-03-30T12:00:00.000Z"}
How it works
The Actor processes each input URL as an independent crawl. It prioritizes contact-focused pages such as /contact, /about, /team, and /imprint, and can also follow equivalent multilingual pages when followContactPages is enabled.
It extracts public emails, phone numbers, WhatsApp links, social profile URLs, and physical address data from the crawled pages. The output schema is aligned with the dataset record structure, and the run also writes terminal data to the key-value store through runOutput and runSummary for automation and agent workflows.
The primary charged event is Result found, which is charged per domain where contact info was extracted. There is also an Actor Start event charged when the Actor begins running.
Pricing
This Actor uses Pay per event pricing plus Apify platform usage, which is billed separately according to your Apify plan. See the Pricing tab for current event prices.
Billed events:
- Actor start: once per run, one unit per GB of allocated memory (minimum one).
- Result found: once per website where contact details were extracted. Websites with no contact details are not charged this event.
For example, a run that extracts contacts from ten websites bills one Actor start event and ten Result found events, plus Apify platform usage.
Use with AI agents (MCP)
This Actor is an Apify Actor usable through Apify MCP. It accepts a list of website URLs, crawls each URL independently, and returns structured contact records that AI agents can parse for outreach, enrichment, or routing tasks.
The exact Actor identity is khadinakbar/bulk-website-contact-extractor.
Extract contact details from this list of company websites. Return emails, phone numbers, WhatsApp links, social profiles, lead scores, and the source URL for each record. Keep the output grouped one record per input URL.
The output can be interpreted record by record. source_url identifies the website that was processed, contact_page_url shows the page that yielded contact data when available, and pages_crawled shows how much of the site was visited for that record. The output is scoped to the submitted URLs, so an AI agent can map each record back to the original input list. Pagination is reflected in the dataset output when the input list is large enough to span multiple result pages. Cost guidance is event-based: each extracted domain contributes a Result found event, and the Actor Start event also applies.
Apify API example
JavaScript
import { ApifyClient } from 'apify-client';const client = new ApifyClient({token: process.env.APIFY_TOKEN,});const run = await client.actor('khadinakbar/bulk-website-contact-extractor').call({startUrls: [{ url: 'https://apify.com' },{ url: 'https://crawlee.dev' }],maxPagesPerDomain: 3,maxResults: 2,followContactPages: true});const { items } = await client.dataset(run.defaultDatasetId).listItems();console.log(items);
Python
from apify_client import ApifyClientimport osclient = ApifyClient(os.environ["APIFY_TOKEN"])run = client.actor("khadinakbar/bulk-website-contact-extractor").call(run_input={"startUrls": [{"url": "https://apify.com"},{"url": "https://crawlee.dev"},],"maxPagesPerDomain": 3,"maxResults": 2,"followContactPages": True,})items = list(client.dataset(run["defaultDatasetId"]).iterate_items())for item in items:print(item["domain"], item["lead_score"], item["emails"])
Best results and outcome guidance
Use direct website URLs in startUrls. This Actor is designed for lists of domains and website URLs, not search queries.
Keep followContactPages enabled when the goal is email and phone discovery. The crawl order prioritizes contact-oriented pages before broader site pages, which fits most enrichment workflows.
Use maxPagesPerDomain to shape coverage. A value of 1 focuses on the homepage, while higher values let the Actor visit more pages per domain.
Use maxResults when you want to process only part of a larger URL list. Set it to 0 when the full list should be processed.
Review lead_score alongside emails, phones, and contact_page_url to decide which records move first into outreach or CRM import.
Continue the workflow
- Start with Clutch Agencies Scraper — Ratings, Services & Pricing to build a list of agency websites, then pass those URLs to this Actor for contact details.
- Start with BizBuySell Scraper — Business Listings & Financials when your prospect list comes from business-for-sale listings, then enrich the listed websites here.
Design note
I found that most contact pages mix shared role inboxes such as info@ with named personal addresses, and buyers treat the two very differently. I designed the record to keep them apart in emails_personal and emails_generic, and to add a simple lead_score so a long list can be sorted by contact coverage before import.
FAQ
What kind of input fits this workflow?
A list of direct website URLs in startUrls. Each URL is crawled independently and becomes one output record.
How many records does one input URL produce?
One record per input URL.
Which pages does the crawl prioritize?
The crawler prioritizes /contact, /about, /team, and /imprint, and it can also follow equivalent contact-oriented pages when followContactPages is enabled.
How should I read the lead score?
A means email and phone were found, B means email only, C means phone only, and D means no public contact info was found in the crawled pages.
Can this Actor be used from Apify MCP?
Yes. It is an Apify Actor usable through Apify MCP, and the output is structured for agent-driven workflows.
What should I use if I need only part of a large URL list?
Use maxResults to cap the number of input URLs processed in the run.
Responsible use
Use this Actor on publicly accessible websites and follow applicable site terms, privacy requirements, and internal data handling policies. Review the extracted contact data before sending outreach, and store or route it according to your organization’s compliance rules.