# Website Contact Scraper – Emails, Phones, Socials (`joseph_cloud/website-contact-scraper`) Actor

Turn a list of websites into contact rows: emails, phones in E.164, people with job titles, company name, and LinkedIn, Instagram, Facebook, X, TikTok +9 networks. Real browser when needed and email domain check included. Pay only for sites with contacts: $6 per 1,000.

- **URL**: https://apify.com/joseph_cloud/website-contact-scraper.md
- **Developed by:** [Jay Gatsby](https://apify.com/joseph_cloud) (community)
- **Categories:** Lead generation, Social media, Automation
- **Stats:** 4 total users, 3 monthly users, 100.0% runs succeeded, 0 bookmarks
- **User rating**: No ratings yet

## Pricing

$6.00 / 1,000 website with contacts

This Actor is paid per event. You are not charged for the Apify platform usage, but only a fixed price for specific events.

Learn more: https://docs.apify.com/actors/running/actors-in-store.md#pay-per-event

## What's an Apify Actor?

An Actor is a serverless cloud program that runs on the Apify platform. It has two run modes.
In Batch mode, an Actor accepts a well-defined JSON input, performs an action which can take anything from a few seconds to a few hours,
and optionally produces a well-defined JSON output, datasets with results, or files in key-value store.
In Standby mode, an Actor provides a web server which can be used as a website, API, or an MCP server.

Apify vocabulary and the platform model are defined once, in the agent quickstart at https://apify.com/agents.md.

## How to integrate an Actor?

If asked about integration, you help developers integrate Actors into their projects.
You adapt to their stack and deliver integrations that are safe, well-documented, and production-ready.

Do not guess an integration path. Every one of them is in the agent quickstart at https://apify.com/agents.md: the Apify MCP server, Agent Skills with the Apify CLI, the JavaScript and Python clients, the REST API, and the account-free path for an agent with no human to sign in. It also carries the rule on stating cost before the first paid run.

For examples already wired to this Actor's own input schema, see the [API](#api) section below.

Each client library has reference documentation the quickstart does not restate: [JavaScript/TypeScript](https://docs.apify.com/api/client/js/docs.md) (`npm install apify-client`) and [Python](https://docs.apify.com/api/client/python/docs.md) (`pip install apify-client`).

# README

## Website Contact Scraper – Emails, Phones, Socials

**Website Contact Scraper turns a list of websites into contact rows.** For every site it returns the email addresses, phone numbers (validated, in E.164 format) and social media profiles on **14 networks** — LinkedIn, Facebook, Instagram, X (Twitter), YouTube, TikTok, Pinterest, XING, Telegram, WhatsApp, Threads, GitHub, Snapchat and Discord — plus one **primary email** and **primary phone** ready for your CRM, the **people** named on the site with their **job titles**, and a **mail-server check** for every email.

Paste a list of domains, click **Start**, and get **one clean row per website**. The Actor finds the contact, imprint, about and team pages by itself, reads them over fast plain HTTP and switches to a **real Chrome browser only when a site needs it**. You pay **$6 per 1,000 websites** — only for websites where contacts were found. People, job titles, email checks and browser pages are **included in that price**.

### What can Website Contact Scraper do?

- 📧 **Email extractor**: `mailto:` links, plain text, Cloudflare-protected addresses, `info [at] example [dot] com` spellings and schema.org data; placeholders like `max@muster.de` or `name@example.com` are dropped
- 📞 **Phone numbers you can dial**: every number is validated with Google's libphonenumber and returned as E.164 (`+493080951000`); fax numbers, dates, prices and order numbers are left out
- 🔗 **Social profiles on 14 networks**: company pages and profiles only — share buttons, video embeds and duplicate spellings are filtered out and URLs are normalised
- 👤 **People and job titles**: managing directors and owners from the imprint, team-page cards ("Jane Doe – Head of Sales") and schema.org data, linked to their personal email and LinkedIn profile when the site shows them; customer quotes and menu text are filtered out
- ✅ **Email check**: for every address, whether its domain accepts mail (MX record), which provider runs it (Google Workspace, Microsoft 365, IONOS …), free mailbox or company domain, generic or personal
- 🌐 **Real browser when needed**: sites that build their content with JavaScript or turn away simple requests are opened again in Chrome, automatically, at no extra cost
- 🏢 **Company name**: the legal name with its legal form (GmbH, Ltd, Inc …) from the imprint
- ⭐ **Primary email and phone**: the site's own general address (info@, contact@, kontakt@ …) and main number in two simple columns
- 🧭 **Finds the right pages**: reads the homepage, then the Contact, Impressum / Imprint / Legal notice and About pages in English, German, French, Italian, Spanish and Dutch, and tries `/contact` or `/kontakt` when the menu is built with JavaScript
- 📋 **One row per website**: everything merged and de-duplicated per domain — no page-by-page rows to clean up
- 💸 **Fair pricing**: one price per website, all features included; unreachable sites, blocked sites and sites without any contact data are free
- 🤖 **Ready for automation**: Apify API, scheduling, webhooks, integrations (Make, Zapier, n8n, Google Sheets) and the Apify MCP server for AI agents

### What data does Website Contact Scraper return?

| Field | Example | Meaning |
|---|---|---|
| `domain` | `ellaskitchen.co.uk` | Registrable domain of the website |
| `companyName` | `easybell GmbH` | Legal name from the imprint (only when it carries a legal form) |
| `primaryEmail` | `shop@ellaskitchen.co.uk` | Best general address on the site's own domain whose domain accepts mail |
| `primaryPhone` | `+443300165221` | Number mentioned most often (E.164) |
| `emails` | `["shop@…", "pr@…"]` | All addresses, own domain first, up to 25 |
| `phones` | `["+443300165221", "+441491629120"]` | All valid phone numbers in E.164, up to 10 |
| `people` | `[{"name": "Steffen Hensche", "title": "Managing Director", "email": null, "linkedin": null, "source": "imprint"}]` | People named on the site, up to 25, with title, personal email and LinkedIn when found; `source` is `imprint`, `team-page` or `schema.org` |
| `emailDetails` | `[{"email": "info@…", "type": "generic", "ownDomain": true, "freeMail": false, "domainAcceptsMail": true, "mailProvider": "Google Workspace", "note": null}]` | Mail-server check per email |
| `linkedin`, `facebook`, `instagram`, `twitter`, `youtube`, `tiktok`, `pinterest`, `xing`, `telegram`, `whatsapp`, `threads`, `github`, `snapchat`, `discord` | `["https://www.linkedin.com/company/…"]` | Profile URLs per network, normalised |
| `contactPageUrl` | `https://www.ellaskitchen.co.uk/contact-us` | Contact or imprint page that gave the data |
| `pagesCrawled` | `["https://…/", "https://…/contact-us"]` | Pages read for this website |
| `finalUrl` | `https://www.ellaskitchen.co.uk/` | Homepage after redirects |
| `renderedWithBrowser` | `false` | `true` when the site was opened in Chrome |
| `error` | `No emails, phones or social profiles found, not charged` | Why a website gave no data |

Download the results as JSON, CSV, Excel or HTML, or read them through the API.

### How to scrape contact details from a list of websites

1. Click **Try for free** (an Apify account is free).
2. Paste your domains or URLs into **Websites**, one per line. `https://` is optional, duplicates are removed.
3. Keep **Max pages per website** at 5 (enough for most sites) or raise it for large sites. Leave **Real browser** on *Auto*, **Find people** and **Check email domains** on.
4. Click **Start**. Results appear in the **Output** tab while the run is going.
5. Export the table to your CRM or spreadsheet, or connect it to Google Sheets, Make or Zapier.

### Input example

```json
{
  "urls": ["fastly.com", "https://www.ellaskitchen.co.uk", "adac.de"],
  "maxPagesPerSite": 5,
  "defaultCountry": "",
  "browser": "auto",
  "findPeople": true,
  "verifyEmails": true
}
```

`defaultCountry` is optional: a two-letter code (`DE`, `US`, `GB` …) for phone numbers written without a country prefix. When it is empty, the country comes from the domain ending (`.de`, `.co.uk` …) or the page language.

`browser`: `auto` (default) reads every site over plain HTTP and opens it in Chrome only when the site blocks simple requests, builds its content with JavaScript, or shows no email and no phone without it. `off` never uses the browser (fastest), `always` uses it for every site (slowest). The price is the same in every mode.

### Output example

Real output for `ellaskitchen.co.uk`:

```json
{
  "url": "https://ellaskitchen.co.uk/",
  "domain": "ellaskitchen.co.uk",
  "finalUrl": "https://www.ellaskitchen.co.uk/",
  "companyName": null,
  "primaryEmail": "shop@ellaskitchen.co.uk",
  "primaryPhone": "+443300165221",
  "emails": ["shop@ellaskitchen.co.uk", "pr@ellaskitchen.co.uk"],
  "phones": ["+443300165221", "+441491629120"],
  "people": [],
  "linkedin": ["https://www.linkedin.com/company/ella's-kitchen"],
  "facebook": ["https://www.facebook.com/ellaskitchen"],
  "instagram": ["https://www.instagram.com/ellaskitchenuk"],
  "twitter": ["https://x.com/EllasKitchenUK"],
  "youtube": ["https://www.youtube.com/channel/UC45fApllSht23XjSrcbRvIw"],
  "tiktok": [], "pinterest": [], "xing": [], "telegram": [], "whatsapp": [],
  "threads": [], "github": [], "snapchat": [], "discord": [],
  "emailDetails": [
    { "email": "shop@ellaskitchen.co.uk", "type": "generic", "ownDomain": true, "freeMail": false, "domainAcceptsMail": true, "mailProvider": "Microsoft 365", "note": null },
    { "email": "pr@ellaskitchen.co.uk", "type": "generic", "ownDomain": true, "freeMail": false, "domainAcceptsMail": true, "mailProvider": "Microsoft 365", "note": null }
  ],
  "contactPageUrl": "https://www.ellaskitchen.co.uk/contact-us",
  "pagesCrawled": [
    "https://www.ellaskitchen.co.uk/",
    "https://www.ellaskitchen.co.uk/contact-us",
    "https://www.ellaskitchen.co.uk/about-us",
    "https://www.ellaskitchen.co.uk/about"
  ],
  "renderedWithBrowser": false,
  "error": null
}
```

And the `people` field for `fastly.com` (first 4 of 17, taken from its company page):

```json
"people": [
  { "name": "Kip Compton", "title": "Chief Executive Officer and Director", "email": null, "linkedin": null, "source": "team-page" },
  { "name": "Artur Bergman", "title": "Founder and Chief Technology Officer", "email": null, "linkedin": null, "source": "team-page" },
  { "name": "Richard Wong", "title": "Chief Financial Officer", "email": null, "linkedin": null, "source": "team-page" },
  { "name": "Joan Jenkins", "title": "Chief Marketing Officer", "email": null, "linkedin": null, "source": "team-page" }
]
```

### Use cases

- **Lead generation:** turn a list of company domains (from Google Maps, a trade fair, a directory or your CRM) into emails, phones and LinkedIn pages.
- **CRM enrichment:** fill empty email, phone and social columns for accounts you already have.
- **Influencer and partner outreach:** find the Instagram, TikTok and YouTube accounts behind a list of brands or shops.
- **Agencies and freelancers:** build prospect lists for local businesses in minutes.
- **AI agents:** use it as a tool through the Apify MCP server — give it domains, get structured JSON back.

### Measured results

We ran the Actor on **100 websites picked at random from the Tranco top-300,000 ranking that it had never seen during development** (a real-world mix: companies, shops, universities, news sites, forums, parked and dead domains). 71 could be reached; **52 gave contact data and would have been charged** — 37 with at least one email, 26 with a phone number and 38 with social profiles, and 11 with named people (41 people in total, each checked by hand: no menu text, product names or customer quotes). The other 48 were dead, behind a captcha, or showed no contact data at all (free). 35 sites were opened in the browser automatically; the 100 sites took about 4 minutes.

What the automatic browser adds, measured on the same 100 sites:

| | Browser off | Browser auto (default) |
|---|---|---|
| Sites reached | 64 | 71 |
| Sites with an email | 28 | 37 |
| Sites with a phone | 21 | 26 |
| Sites with contacts (charged) | 43 | 52 |
| Run time | 44 s | 4 min |

We also ran 30 of these sites side by side with the most popular page-based contact scraper in the Store (10 pages per site, its default settings otherwise):

| | Website Contact Scraper | Page-based scraper |
|---|---|---|
| Sites with an email found | **19 of 30** | 13 of 30 |
| Email addresses found | **72** | 59 |
| Valid phone numbers | **45** (all E.164) | 42, plus 267 "uncertain" values — mostly dates, prices and order numbers |
| Social profile links | 72 | **78** |
| People with job title | **18** (included) | 0 (a paid add-on) |
| Run time | **71 s** | 108 s |
| Price for the 30 sites | **$0.15** (25 sites with contacts) | $0.45 (222 pages + start fee) |

The page-based scraper reads more pages per site, so it returns a few more social links; the browser fallback is why we find email on more sites.

### How much does it cost to scrape contacts from websites?

Pay per event: **$6 per 1,000 websites with contacts** ($0.006 per website). The price is per website, not per page, so reading 5 or 20 pages of a site costs the same. People, job titles, email checks and pages opened in the browser are included. No subscription, no monthly fee, no add-ons, no extra charge per run or per GB of memory.

| Websites with contacts | Price |
|---|---|
| 100 | $0.60 |
| 1,000 | $6 |
| 10,000 | $60 |

Apify's free plan includes $5 of monthly credit, which covers about **830 websites with contacts a month** at no cost.

You are **not charged** when a website does not exist or cannot be reached, blocks automated requests, shows a bot-protection page, disallows bots in robots.txt, or has no email, phone or social profile on the pages read. Such items are still returned, with the reason in `error`.

### How it works, and its limits

The Actor loads the homepage, ranks its links (Contact, Impressum / Imprint, About, Team, Support …), reads up to **Max pages per website** pages of the same domain, and merges everything into one row.

Please know the limits before you buy:

- **Contact forms and images are not read.** An address shown only as an image or hidden behind a contact form is missed (you are not charged when nothing is found).
- **Captchas stop us.** The Actor visits like a normal browser and waits out automatic "checking your browser" pages, but it does not solve captchas, use proxies to get around blocks, or ignore robots.txt. Those sites are returned free.
- **It reads contact pages, not the whole site.** It is built for "what are this company's contacts?", not for collecting every address mentioned in a blog. Raise **Max pages per website** for big sites.
- **The email check is on the domain level.** It tells you whether the domain can receive mail and who hosts it; it does not contact the mail server to test one single mailbox. You get the addresses the site publishes; the own-domain ones come first.
- **People come from the website itself.** Only people the site names with a job title are returned — no guessed addresses and no outside database. Sites without a team page or imprint give no people.
- **Third parties can appear.** An imprint can name the web agency or a dispute-resolution body; their addresses are kept but sorted after the site's own, and never chosen as `primaryEmail` when the site has its own.

### Data protection

Business contact pages often name employees with their direct email, phone or LinkedIn profile. That is personal data under the GDPR and similar laws. You are responsible for having a legal basis for what you do with it — for example, German law (§ 7 UWG) and other EU rules restrict unsolicited advertising emails, and the US CAN-SPAM Act sets rules for commercial email. Use the data for legitimate business purposes only.

### FAQ

**Is this an email extractor or a social media scraper?**
Both. Each row has the emails, the phone numbers and the social profile links of one website, so you do not need three separate tools.

**How many websites can I check at once?**
There is no fixed limit. Thousands of URLs in one run are fine; duplicates are removed automatically.

**Why is a website free in my results?**
Look at `error`: the site was down, blocked bots, disallowed bots in robots.txt, or had no contact data on the pages read.

**Do names, job titles and email checks cost extra?**
No. They are part of the $0.006 per website. You can switch them off with `findPeople` and `verifyEmails` if you do not need them; the price stays the same.

**Can I get the company name, address and register number too?**
The company name is included. For the full legal data of German, Austrian and Swiss companies (address, Handelsregister number, VAT ID), use the [Impressum & Imprint Scraper](https://apify.com/joseph_cloud/impressum-company-data).

**Can I run it on a schedule or from my code?**
Yes. Use Apify schedules, the REST API, the JavaScript or Python clients, or integrations like Make, Zapier, n8n and Google Sheets.

### Other Actors by the same developer

- [Impressum & Imprint Scraper – German Company Data, HRB & VAT](https://apify.com/joseph_cloud/impressum-company-data) — legal name, address, Handelsregister number, VAT ID checked in EU VIES and managing directors from DACH websites
- [Email Provider & DNS Checker](https://apify.com/joseph_cloud/email-dns-checker) — find the email provider (Google Workspace, Microsoft 365, IONOS …) plus SPF, DMARC and DKIM status of any domain list
- [Tech Stack Detector – Wappalyzer & BuiltWith Alternative](https://apify.com/joseph_cloud/tech-stack-detector) — find the CMS, shop system, analytics, CDN and 7,000+ other technologies behind any website list

### Support

Open an issue on the Actor's Issues tab; it is usually answered within one to two days. If a contact is missed or wrong for a site, include the URL — every report makes the extractor better.

# Actor input Schema

## `urls` (type: `array`):

Domains or URLs (e.g. stripe.com or https://www.example.de). The Actor opens the homepage, finds the contact, imprint and about pages itself and returns one row per website. Duplicates are removed.

## `maxPagesPerSite` (type: `integer`):

Homepage plus the best contact, imprint and about pages. 5 covers most sites; raise it for large sites with many contact pages. The price is per website, not per page.

## `defaultCountry` (type: `string`):

Two-letter country code (DE, US, GB, ...) used to read phone numbers written without a country prefix. Leave empty to detect it from the domain ending and the page language.

## `browser` (type: `string`):

auto (recommended): plain HTTP first, and a real Chrome browser only for sites that block simple requests, build their content with JavaScript or show no email or phone without it. off: plain HTTP only, fastest. always: Chrome for every site, slowest. The price is the same in all modes.

## `findPeople` (type: `boolean`):

Names and job titles from the imprint (managing directors, owners), team pages and schema.org data, linked to their personal email and LinkedIn profile when the site shows them. Included in the price.

## `verifyEmails` (type: `boolean`):

For every email: does its domain accept mail (MX record), which provider runs it (Google Workspace, Microsoft 365, IONOS ...), free mailbox or company domain, generic (info@) or personal. Domain level only, no mail is sent. Included in the price.

## Actor input object example

```json
{
  "urls": [
    "fastly.com",
    "ellaskitchen.co.uk",
    "adac.de",
    "sonnen.de",
    "immuta.com"
  ],
  "maxPagesPerSite": 5,
  "defaultCountry": "",
  "browser": "auto",
  "findPeople": true,
  "verifyEmails": true
}
```

# Actor output Schema

## `results` (type: `string`):

One item per website: primary email and phone, all emails, phones in E.164 format, social profiles for 14 networks, and the pages read.

# API

You can run this Actor programmatically using our API. Below are code examples in JavaScript, Python, and CLI, as well as the OpenAPI specification and MCP server setup.

## JavaScript example

```javascript
import { ApifyClient } from 'apify-client';

// Initialize the ApifyClient with your Apify API token
// Replace the '<YOUR_API_TOKEN>' with your token
const client = new ApifyClient({
    token: '<YOUR_API_TOKEN>',
});

// Prepare Actor input
const input = {
    "urls": [
        "fastly.com",
        "ellaskitchen.co.uk",
        "adac.de",
        "sonnen.de",
        "immuta.com"
    ]
};

// Run the Actor and wait for it to finish
const run = await client.actor("joseph_cloud/website-contact-scraper").call(input);

// Fetch and print Actor results from the run's dataset (if any)
console.log('Results from dataset');
console.log(`💾 Check your data here: https://console.apify.com/storage/datasets/${run.defaultDatasetId}`);
const { items } = await client.dataset(run.defaultDatasetId).listItems();
items.forEach((item) => {
    console.dir(item);
});

// 📚 Want to learn more 📖? Go to → https://docs.apify.com/api/client/js/docs

```

## Python example

```python
from apify_client import ApifyClient

# Initialize the ApifyClient with your Apify API token
# Replace '<YOUR_API_TOKEN>' with your token.
client = ApifyClient("<YOUR_API_TOKEN>")

# Prepare the Actor input
run_input = { "urls": [
        "fastly.com",
        "ellaskitchen.co.uk",
        "adac.de",
        "sonnen.de",
        "immuta.com",
    ] }

# Run the Actor and wait for it to finish
run = client.actor("joseph_cloud/website-contact-scraper").call(run_input=run_input)

# Fetch and print Actor results from the run's dataset (if there are any)
print(f"💾 Check your data here: https://console.apify.com/storage/datasets/{run.default_dataset_id}")
for item in client.dataset(run.default_dataset_id).iterate_items():
    print(item)

# 📚 Want to learn more 📖? Go to → https://docs.apify.com/api/client/python/docs/quick-start

```

## CLI example

```bash
echo '{
  "urls": [
    "fastly.com",
    "ellaskitchen.co.uk",
    "adac.de",
    "sonnen.de",
    "immuta.com"
  ]
}' |
apify call joseph_cloud/website-contact-scraper --silent --output-dataset

```

## MCP server setup

```json
{
    "mcpServers": {
        "apify": {
            "type": "http",
            "url": "https://mcp.apify.com/?tools=fetch-actor-details,joseph_cloud/website-contact-scraper"
        }
    }
}
```

The hosted server signs you in with OAuth on first connect, so no API token belongs in this config. Clients without OAuth support can send an `Authorization: Bearer <APIFY_API_TOKEN>` header instead, using a token from API & Integrations in Apify Console (https://console.apify.com/settings/integrations).

## OpenAPI specification

Download the OpenAPI definition: https://api.apify.com/v2/actors/57mt4cGxZ5VvrYlcx/builds/2sLZEwgBoSX3TYogn/openapi.json
