Website Contact Details Scraper
Pricing
Pay per event
Website Contact Details Scraper
Extract emails, phone numbers, addresses, contact pages, and social links from public business websites.
Pricing
Pay per event
Rating
0.0
(0)
Developer
Stas Persiianenko
Maintained by CommunityActor stats
0
Bookmarked
2
Total users
1
Monthly active users
2 days ago
Last modified
Categories
Share
Turn a list of public business websites into structured website contact details for lead enrichment, CRM cleanup, research, and scheduled data pipelines.
The Actor visits each supplied site, follows a bounded set of likely contact and company pages, and returns one aggregated record per website. Records can include public emails, phone numbers, address text, contact and about page URLs, social-profile links, crawl evidence, and failures.
What does Website Contact Details Scraper do?
The Actor:
- accepts one or many public website URLs;
- normalizes domain-only inputs to HTTPS;
- follows redirects;
- discovers likely contact, support, about, company, team, and legal pages;
- extracts emails from visible text and
mailto:links; - extracts phone numbers from labeled text and
tel:links; - reads postal-address text from semantic HTML and JSON-LD;
- groups social links by network;
- aggregates every result into one website-level record;
- records both successful and failed page URLs.
It uses direct HTTP by default. Optional Apify Proxy settings are available for websites that reject requests from the default route.
Who is this website contact extractor for?
Use it when you are:
- enriching company records before sales outreach;
- cleaning missing or stale CRM contact fields;
- researching vendors, members, exhibitors, or partners;
- building a public-business contact spreadsheet;
- checking where a company publishes its support channels;
- preparing website-level records for another automation;
- scheduling repeat collection to compare public details over time.
The Actor extracts what a website publicly publishes. It does not guess private email addresses or validate mailbox deliverability.
Why use this Actor?
Many contact scrapers emit a separate row for every page or link. This Actor instead returns one predictable record for each supplied website, which makes joins against a CRM or company list straightforward.
The crawl is deliberately bounded. It prioritizes high-signal pages rather than exploring an entire site, limits retries, and avoids browser rendering unless the product is changed in a future release.
Useful operational fields such as pagesCrawled, pagesFailed, and foundContactDetails make partial coverage visible instead of silently treating every failure as an empty result.
What website contact data can it extract?
| Field | Description |
|---|---|
websiteUrl | Normalized supplied URL |
finalUrl | Homepage URL after redirects |
domain | Final website hostname |
websiteName | Name inferred from metadata or title |
emails | Unique public email addresses |
phoneNumbers | Unique public phone-number strings |
contactPageUrls | Contact, support, help, or reach-us links |
aboutPageUrls | About, company, team, or who-we-are links |
addresses | Address text from semantic HTML or JSON-LD |
socialProfiles | Links grouped by Facebook, Instagram, LinkedIn, X, YouTube, TikTok, Pinterest, or GitHub |
pagesCrawled | Pages successfully used for the record |
pagesFailed | Pages that failed with concise reasons |
foundContactDetails | Whether any useful detail or contact link was found |
scrapedAt | Completion time in ISO 8601 format |
Arrays are empty when no matching public value is found. websiteName can be null when a page exposes no usable title.
How to get started
- Open the Actor input.
- Add public business websites under Business website URLs.
- Keep the default five pages per website for an economical first run.
- Increase crawl depth only when relevant contact pages are nested.
- Optionally enable Apify Proxy for a site that blocks direct requests.
- Click Start.
- Open the dataset and export JSON, CSV, Excel, XML, or RSS.
A full URL such as https://company.com/contact is accepted, as is a domain-like value such as company.com.
Input parameters
startUrls
Required. One or more website URLs. Each unique input produces at most one result record.
maxItems
Maximum input websites to process. Default: 10. Range: 1 to 10,000.
maxPagesPerWebsite
Maximum pages fetched for each website. Default: 5. Range: 1 to 20.
maxDepth
Number of same-site contact-link levels to follow. Default: 1. Range: 0 to 2.
Set it to 0 to inspect only each supplied URL.
includeSubdomains
Whether contact-related subdomain links may enter the crawl. Default: false.
proxyConfiguration
Optional Apify Proxy configuration. Direct requests are the default. The Actor does not automatically switch to paid residential traffic.
Example input
{"startUrls": [{ "url": "https://apify.com" },{ "url": "https://www.w3.org/Consortium/contact" }],"maxItems": 2,"maxPagesPerWebsite": 5,"maxDepth": 1,"includeSubdomains": false}
Example output
The shape below is anonymized from the verified local output contract:
{"websiteUrl": "https://sample-business.test/","finalUrl": "https://www.sample-business.test/","domain": "www.sample-business.test","websiteName": "Sample Business","emails": ["hello@sample-business.test"],"phoneNumbers": ["+1 555 010 2040"],"contactPageUrls": ["https://sample-business.test/contact"],"aboutPageUrls": ["https://sample-business.test/about"],"addresses": ["123 Sample Street, Example City, CA 90000, US"],"socialProfiles": {"linkedin": ["https://linkedin.com/company/samplebusiness"]},"pagesCrawled": ["https://sample-business.test/","https://sample-business.test/contact"],"pagesFailed": [],"foundContactDetails": true,"scrapedAt": "2026-08-05T12:00:00.000Z"}
How much does it cost to extract contact details from websites?
The Actor uses pay-per-event pricing:
- a one-time Start event per run;
- one Item processed event for each website record saved.
The run starts at $0.005. The per-item price is tiered by Apify plan; the BRONZE tier is $0.0036 per website record, with lower rates on higher plans.
At those rates, excluding optional proxy traffic:
- 1 website is about
$0.0086on BRONZE; - 25 websites are about
$0.095on BRONZE; - 100 websites are about
$0.365on BRONZE.
The live Console pricing table is authoritative. Final cost can also be limited with Apify's maximum-charge setting.
CRM enrichment workflow
Export domains or website URLs from your CRM, run them as startUrls, and join the dataset back on domain or websiteUrl.
Useful follow-up steps include:
- retain only records where
foundContactDetailsis true; - explode email or phone arrays when your CRM expects one value per row;
- route
pagesFailedrecords to a retry queue; - preserve
scrapedAtto compare scheduled runs; - review public-contact purpose and consent before outreach.
Scheduled monitoring and change detection
Apify Tasks can run this Actor on a schedule. Store each run's dataset externally, then compare fields such as emails, phoneNumbers, contactPageUrls, and socialProfiles.
The Actor itself returns a current snapshot. It does not maintain history, send alerts, or label changes between runs.
Export and integrations
Dataset results work with:
- JSON, JSONL, CSV, Excel, XML, and RSS exports;
- Apify webhooks;
- Zapier and Make;
- Google Sheets workflows;
- cloud warehouses and object storage;
- CRM enrichment jobs;
- custom Node.js or Python pipelines.
Because each row represents one website, downstream deduplication is typically based on domain.
Use the API with cURL
curl "https://api.apify.com/v2/acts/automation-lab~website-contact-details-extractor/runs?token=$APIFY_TOKEN" \-X POST \-H 'Content-Type: application/json' \-d '{"startUrls": [{"url": "https://www.w3.org/Consortium/contact"}],"maxPagesPerWebsite": 5,"maxDepth": 1}'
Use the returned run ID to read status and the default dataset.
Use the API with JavaScript
import { ApifyClient } from 'apify-client';const client = new ApifyClient({ token: process.env.APIFY_TOKEN });const run = await client.actor('automation-lab/website-contact-details-extractor').call({startUrls: [{ url: 'https://www.w3.org/Consortium/contact' }],maxPagesPerWebsite: 5,maxDepth: 1,});const { items } = await client.dataset(run.defaultDatasetId).listItems();console.log(items);
Use the API with Python
import osfrom apify_client import ApifyClientclient = ApifyClient(os.environ['APIFY_TOKEN'])run = client.actor('automation-lab/website-contact-details-extractor').call(run_input={'startUrls': [{'url': 'https://www.w3.org/Consortium/contact'}],'maxPagesPerWebsite': 5,'maxDepth': 1,})items = client.dataset(run['defaultDatasetId']).list_items().itemsprint(items)
Use with Apify MCP
Add the Actor to Claude Code:
claude mcp add --transport http apify \"https://mcp.apify.com?tools=automation-lab/website-contact-details-extractor"
Claude Desktop, Cursor, and VS Code can use the same HTTP MCP server configuration:
{"mcpServers": {"apify": {"url": "https://mcp.apify.com?tools=automation-lab/website-contact-details-extractor"}}}
- Claude Desktop: add the JSON under
mcpServersin the desktop configuration. - Cursor: add the same server in Cursor MCP settings.
- VS Code: add the same server to your MCP configuration.
Example prompts:
- “Extract public contact details from these supplier websites and return one row per domain.”
- “Find the public support page and social profiles for each URL in this CRM export.”
- “Run contact enrichment for these websites and summarize pages that failed.”
Accuracy tips
- Supply the canonical company homepage or a known contact page.
- Increase
maxPagesPerWebsitewhen navigation contains several relevant branches. - Use depth
2only when contact pages are nested. - Enable subdomains when support or company pages live on a corporate subdomain.
- Review phone and address strings before using them in automated outreach.
- Use a proxy only after a direct run shows a site-specific access failure.
Limits and failure behavior
The Actor does not render JavaScript. A JavaScript-only site can expose fewer values than a server-rendered site.
Authenticated pages, forms behind login, CAPTCHA challenges, and private intranets are outside scope. Local and private-network targets are rejected.
A related page failure is added to pagesFailed; details from successful pages are retained. A website that loads but publishes no matching values still produces a record with empty arrays and foundContactDetails: false.
The Actor discovers contact-form URLs but does not submit forms.
Responsible use and legality
Only process public websites you are allowed to access. Follow applicable website terms, robots policies, privacy law, anti-spam law, and contractual obligations.
Public availability does not automatically authorize unsolicited outreach or unlimited reuse. Establish a lawful purpose, minimize collected data, secure exports, honor deletion and opt-out requests, and avoid collecting sensitive personal information.
The user is responsible for how extracted contact details are stored and used.
Troubleshooting
Why are the arrays empty?
The site may not publish contact details in server-rendered HTML, or the details may be behind a form, script, login, or image. Check pagesCrawled, increase the page limit, and verify the public page manually.
Why does pagesFailed contain HTTP 403 or 429?
The website rejected or rate-limited the request. Reduce repeated runs or enable an appropriate Apify Proxy configuration if your access is permitted.
Why did one website return only social links?
That can be valid. Some sites publish social profiles but no email, phone, or semantic address.
Does the Actor verify emails or phone numbers?
No. It extracts public values as written. Use a separate verification workflow when deliverability or normalization matters.
Can it submit website contact forms?
No. It discovers contact-form pages but does not fill or submit forms.
Related automation-lab Actors
- Social Media Profile Finder for focused social-profile discovery.
- SMTP Email Verifier for a separate email-verification workflow.
- Phone Number Validator for normalization and validation after extraction.
These are optional downstream tools. Their pricing and output contracts are separate from this Actor.
FAQ
Does one page equal one charged item?
No. One saved website-level record equals one item event, even when several pages contributed to it.
Can I provide a contact page directly?
Yes. The supplied URL is fetched first, and related same-site links can still be discovered within the configured bounds.
Are duplicate websites removed?
Exact normalized input strings are deduplicated. Different URLs on the same domain can still produce separate records when supplied separately.
Does it crawl an entire website?
No. It follows only high-signal links and stops at the configured page and depth limits.
Can I use the result in a spreadsheet?
Yes. Export the default dataset as CSV or Excel, or connect it to a scheduled integration.
Is browser rendering available?
Not in this release. The HTTP-first route keeps runs economical and transparent; JavaScript-only content is a documented limitation.