Website Contacts & Decision Makers Scraper
Pricing
from $6.00 / 1,000 website scanneds
Website Contacts & Decision Makers Scraper
Turn a list of company websites into contact rows: emails, phone numbers (validated, typed), social profiles, address, VAT ID, plus the owners and managers named on the site. Works on any country's websites, pairs with Google Maps Scraper output.
Pricing
from $6.00 / 1,000 website scanneds
Rating
0.0
(0)
Developer
Benjamin Zsigri
Maintained by CommunityActor stats
0
Bookmarked
2
Total users
1
Monthly active users
a day ago
Last modified
Categories
Share
Turn a list of company websites into a clean contact sheet. For every website you get one row with:
- Emails, labelled as role mailbox (
info@,sales@), personal (jane.smith@), generic or freemail, with the page each one was found on - Phone numbers, validated and formatted in international E.164 (
+441614960123), typed as landline, mobile or service number, with fax numbers kept apart - Decision makers: owners, founders, managing directors, executives, board members and department heads named on the website, with their role, a role category and, when the site publishes it, their email
- Social profiles: LinkedIn, Facebook, Instagram, X/Twitter, YouTube, TikTok, Pinterest, XING, GitHub
- Company name, postal address, VAT ID, website language and description
It works on websites from any country (English, German, French, Spanish, Italian, Dutch, Portuguese, Polish, Nordic, Hungarian and Czech pages are understood) and it is built to take the output of Google Maps Scraper or any other dataset with a website column.
Who it is for
- Sales and lead generation: you have a list of businesses (from Google Maps, a directory, a trade fair, your CRM) and need a phone number, an email and the name of the person in charge.
- Agencies building prospect lists for clients.
- CRM enrichment: fill in missing emails, phones, social profiles and VAT IDs for accounts you already have.
- Market research: who owns and runs the companies in a niche.
How it works
- Each website is visited starting from its homepage.
- The crawler picks the pages most likely to hold contact details first: contact, imprint / legal notice (Impressum, mentions légales, aviso legal), team / leadership, about. It never opens login, basket, blog, shop or privacy pages.
- Every page is read for emails, phone numbers, social links, structured data (schema.org) and people with a role.
- Everything found is merged into one row per website, ranked (the company's own domain first, role mailboxes before personal ones, the main phone number first, the most senior person first).
A typical small or mid-size business website needs 4 to 8 pages. You set the maximum with Max pages per website.
What the Actor does NOT do
- It does not log in anywhere and it does not solve or bypass CAPTCHAs.
- It respects robots.txt. A website that disallows crawling is reported as
robots_blockedand is not charged. - It does not decode email protection scripts (such as Cloudflare's): the row is flagged with
email_hidden_by_protection: trueinstead. Emails written asname [at] company [dot] comare plain text shown to every visitor and are read. - It does not guess emails (no
firstname.lastname@invention) and it does not use LinkedIn. Only what the company publishes on its own website is returned. - Customer testimonials and reviews are kept apart from the company's people: names right under a quote or in a "what our customers say" section are skipped.
Input
The simplest input is a list of websites:
{"websites": ["https://www.example-plumbing.co.uk", "example-dental.com"],"findDecisionMakers": true,"maxDecisionMakersPerWebsite": 3}
Or point the Actor at a dataset, for example the output of a Google Maps Scraper run:
{"datasetId": "YOUR_DATASET_ID","maxPagesPerWebsite": 8}
The website field is detected automatically (website, url, domain, companyWebsite, …) or you can name it in Website field in the dataset. A Google Maps listing link is never taken for the website; items without a website are skipped. Fields such as title, placeId, address, city, countryCode and categoryName are copied into source_item, so you can join the results back to your list.
| Field | What it does |
|---|---|
websites | Company websites, one per line. Duplicates are scanned once. |
datasetId | Import websites from a dataset (e.g. Google Maps Scraper output). |
findDecisionMakers | Recognise owners, executives and managers named on the site. |
maxDecisionMakersPerWebsite | Most senior first. Caps the cost per website. |
includeOtherPeople | Other named people with a role (staff, contact persons). Free. |
defaultCountry | Country for local phone numbers written without a prefix. Without it, the dataset's countryCode or the website's country domain is used. |
maxPagesPerWebsite | Requests per website, homepage included (default 8). |
maxConcurrency | Websites scanned in parallel (default 20). |
proxyConfiguration | Optional. Most company websites answer direct requests. |
Output
One row per website. Overview columns (primary_email, primary_phone, decision_maker_name, decision_maker_role, decision_maker_email, linkedin, …) make the CSV and Excel export usable without unpacking arrays; the full lists are in the JSON.
{"input_url": "example-plumbing.co.uk","domain": "example-plumbing.co.uk","website": "https://www.example-plumbing.co.uk/","status": "ok","company_name": "Example Plumbing Ltd","language": "en","emails": [{ "email": "hello@example-plumbing.co.uk", "type": "role", "same_domain": true, "source_url": "https://www.example-plumbing.co.uk/contact/" },{ "email": "jane.smith@example-plumbing.co.uk", "type": "named", "same_domain": true, "source_url": "https://www.example-plumbing.co.uk/meet-the-team/" }],"phones": [{ "number": "+441614960123", "type": "landline", "country": "GB", "source_url": "https://www.example-plumbing.co.uk/" },{ "number": "+447911123456", "type": "mobile", "country": "GB", "source_url": "https://www.example-plumbing.co.uk/contact/" }],"fax_numbers": [],"socials": { "facebook": "https://facebook.com/exampleplumbing", "linkedin": "https://linkedin.com/company/example-plumbing" },"address": { "street": "12 Mill Lane", "postal_code": "M1 2AB", "city": "Manchester", "region": null, "country": "GB" },"vat_ids": [{ "id": "GB123456789", "country": "GB" }],"decision_makers": [{"name": "Jane Smith","first_name": "Jane","last_name": "Smith","salutation": null,"role": "Founder & Managing Director","role_category": "owner","is_decision_maker": true,"email": "jane.smith@example-plumbing.co.uk","source_url": "https://www.example-plumbing.co.uk/meet-the-team/","extraction_method": "name_above_role"}],"other_people": [{ "name": "Tom Baker", "role": "Gas Safe Engineer", "role_category": "staff", "is_decision_maker": false }],"email_hidden_by_protection": false,"primary_email": "hello@example-plumbing.co.uk","primary_phone": "+441614960123","decision_maker_name": "Jane Smith","decision_maker_role": "Founder & Managing Director","decision_maker_email": "jane.smith@example-plumbing.co.uk","pages_crawled": 4,"scraped_at": "2026-10-01T09:00:00.000Z"}
Role categories
role_category | Examples | Decision maker |
|---|---|---|
owner | Owner, Founder, Co-founder, Managing Partner, Inhaber, Gründer, Fondateur | yes |
executive | CEO, Managing Director, General Manager, Geschäftsführer, Directeur général | yes |
board | Chairman, Board member, Non-Executive Director, Verwaltungsrat | yes |
authorized_representative | Legal representative named in the legal notice | yes |
department_head | Head of Sales, Sales Director, Director of Marketing, Office Manager, Vertriebsleiter | yes |
content_responsible, contact | Responsible for content, contact person | no |
staff | Engineer, Consultant, Plumber, Account Manager | no |
Status values
status | Meaning | Charged |
|---|---|---|
ok | The website answered and was read | yes |
robots_blocked | robots.txt disallows crawling | no |
blocked | The site refuses automated requests (HTTP 401/403/429) or redirects elsewhere | no |
not_a_company_website | A social profile, directory or marketplace page, not the company's own site | no |
unreachable / http_error / not_html / invalid_url / error | The website could not be read | no |
Pricing
This Actor uses pay per event pricing: you pay for results, not for compute time.
- Website scanned: charged once per website that answered (
status: ok), whatever was found on it. - Decision maker found: charged per decision maker returned. Set Max decision makers per website to cap it, or switch decision makers off.
Websites that could not be read are listed in the results with the reason, free of charge. Other named people (other_people) are free. The current prices are on the Pricing tab.
The Actor respects your maximum cost per run: when the limit is reached it stops before starting another website, and it never returns a decision maker it could not charge for.
Use it with Google Maps Scraper
- Run Google Maps Scraper for your niche and area (e.g. "plumbers in Manchester").
- Copy the run's dataset ID.
- Start this Actor with
datasetIdset to it.
Each row keeps the place's title, placeId, address and countryCode in source_item, so you get the place, its website contacts and its owner in one table. You can chain both Actors automatically with an Apify integration (run this Actor when the Maps run succeeds).
Where your list can come from
- Google Maps Scraper: set
datasetIdto its run's dataset. This Actor never searches Google Maps itself; it works on the dataset you bring. - A CSV file or spreadsheet: paste the website column into
websites, one per line. - Your CRM: export the accounts and paste the website column, or push the rows into an Apify dataset with the API and set
datasetIdto it.datasetUrlFieldnames the column when it is not one of the usual names. - Make, n8n, Zapier or Clay: start the Actor through the Apify API (Apify also offers ready-made modules for some of these tools), pass
websitesin the input and read the run's dataset as the output.
Tips
- Speed and cost: 6 to 8 pages per website find contact details on the vast majority of small business websites. Raise it for large corporate sites with deep team sections.
- Local phone numbers written without a country prefix are only returned when the country is known (from
defaultCountry, the dataset'scountryCodeor the country domain such as.deor.co.uk). A number is never guessed into the wrong country. - Blocked websites: if many of your websites end as
blocked, try a proxy in the input. - Resuming: if a run is migrated by the platform, it continues where it stopped without scanning or charging the finished websites again.
Is it legal to scrape contact details?
This Actor reads only pages that the company publishes openly on its own website, respects robots.txt and does not bypass any login, CAPTCHA or email protection. Business contact details of companies are generally public information. However, names and personal work emails of people are personal data under the GDPR (EU/UK) and similar laws. If you store or use them, you need a lawful basis (for B2B outreach usually legitimate interest), you must tell people where you got their data, and you must respect opt-outs and local direct-marketing rules (e.g. PECR in the UK). If you are unsure, ask a lawyer. You are responsible for how you use the data.
Limitations
- Websites that render all content with JavaScript only (no server-side HTML) may return few results.
- People are recognised from their name and role as written on the page. A person introduced only in a paragraph of prose, or only in an image, is not found.
- The postal address comes from schema.org structured data when the site provides it.
Feedback
Found a website where the result is wrong or incomplete? Open an issue on the Issues tab with the URL. Real examples are the fastest way to improve the extraction.
Need it done for you?
Want this connected to your CRM or workflow, or adapted to your market? Tribloc, the team behind this Actor, builds these setups. Get in touch at tribloc.co.uk.