# Website Email Extractor & Contact Scraper: Emails, Phones (`gouda_studios/website-contact-extractor`) Actor

Email extractor and contact scraper for lead gen. Give it any list of websites and get emails, phones, LinkedIn, Facebook, Instagram, X and TikTok links and addresses, one deduplicated row per site. Cloudflare emails decoded, phones validated. Pay only for sites where contacts are found.

- **URL**: https://apify.com/gouda_studios/website-contact-extractor.md
- **Developed by:** [Gouda Studios](https://apify.com/gouda_studios) (community)
- **Categories:** Lead generation, Automation
- **Stats:** 2 total users, 1 monthly users, 0.0% runs succeeded, 0 bookmarks
- **User rating**: No ratings yet

## Pricing

from $2.50 / 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

## Email Extractor and Contact Scraper: Emails, Phones and Social Links from Any Website

This **email extractor** turns a list of websites into a clean lead sheet. Paste domains or URLs, and the contact scraper returns **one deduplicated row per website** with email addresses, phone numbers, social media profiles and the business address. Use it as an email scraper for lead generation, a contact finder for B2B prospecting, or a bulk website email finder for a CRM import.

**You pay only for websites where we find at least one email or phone number.** Sites that fail to load or have no contact details are still returned so you can see what happened, but they are free.

### Why use this email extractor?

- **One row per website, not per page.** No merge or dedupe step. Ready for CSV, Excel, Google Sheets or your CRM.
- **Priced per website, not per page.** $2.50 per 1,000 websites with contacts found, no matter how many pages we read on each site (up to 40).
- **Finds what simple scrapers miss.** Decodes Cloudflare-protected emails, reads `mailto:` and `tel:` links, schema.org data, and common obfuscation like `name [at] company [dot] com`.
- **Cleaner phones.** Every phone number is validated and returned in E.164 format (`+12125551234`) plus national format, country and line type. Random digit strings are dropped instead of being dumped into an "uncertain" list.
- **Email quality hints.** Each email is flagged as role account (info@, sales@) or personal, whether it matches the website's own domain, and whether its domain has MX records that can receive mail.
- **Smart page selection.** Reads the homepage first, then the pages most likely to hold contacts: Contact, About, Team, Impressum, Support and Locations.
- **Polite by default.** Respects robots.txt and needs no login, cookies or proxy for most business sites.

### What data do you get?

| Field | Example |
| --- | --- |
| `domain` | `acme-plumbing.com` |
| `siteName` | `Acme Plumbing` |
| `primaryEmail` | `info@acme-plumbing.com` |
| `emails` | all emails found on the site |
| `primaryPhone` / `phones` | `+15125550199` |
| `linkedin`, `facebook`, `instagram`, `x`, `youtube`, `tiktok` | profile URLs |
| `otherSocials` | GitHub, Pinterest, Threads, Telegram, WhatsApp, Discord, Reddit, Bluesky |
| `addresses` | street, city, region, postal code, country (from schema.org) |
| `contactPageUrls` | links to the site's contact pages |
| `emailDetails` | per email: page found on, source, role account, domain match, MX check |
| `phoneDetails` | per phone: E.164, international and national format, country, type, source |
| `status` | `ok`, `no_contacts_found` or `failed` |
| `charged` | `true` only for rows you paid for |

### How to scrape emails from websites

1. Paste your websites into **Websites**, one per line. Bare domains like `example.com` work.
2. Optional: change **Max pages per site** (default 8), **Default phone country** (default US) or turn on a proxy.
3. Click **Start**. Download the emails and phone numbers as CSV, Excel, JSON or HTML, or pull them with the API.

Got leads from Google Maps, Yelp, a directory or a trade show list? Export the website column and paste it here to get the emails those sources leave out.

#### Input example

```json
{
  "startUrls": ["https://apify.com", "python.org", "acme-plumbing.com"],
  "maxPagesPerSite": 8,
  "defaultCountry": "US",
  "checkMx": true,
  "respectRobotsTxt": true
}
```

#### Output example

```json
{
  "domain": "apify.com",
  "siteName": "Apify",
  "status": "ok",
  "primaryEmail": "support@apify.com",
  "emails": ["support@apify.com", "hello@apify.com"],
  "phones": [],
  "linkedin": ["https://www.linkedin.com/company/apify"],
  "x": ["https://x.com/apify"],
  "otherSocials": { "github": ["https://github.com/apify"], "discord": ["https://discord.gg/..."] },
  "addresses": [{ "street": "Na Prikope 959/27", "city": "Prague", "postalCode": "11000", "country": "CZ" }],
  "contactPageUrls": ["https://apify.com/contact"],
  "pagesScanned": 4,
  "charged": true
}
```

### Pricing

Pay per event:

- **Website with contacts:** $0.0025 per website ($2.50 per 1,000) where at least one email or phone is found.
- **Actor start:** $0.0005 per run.
- Websites with no contacts, or that fail to load: **free**.

Example: 1,000 websites where 700 have contacts costs about $1.75. Set a maximum charge per run in the run options and the Actor stops cleanly when it is reached.

### Use cases

- **Lead generation:** scrape emails and phone numbers from prospect websites and load them into your outreach tool or CRM
- **Google Maps lead enrichment:** add emails and social profiles to business lists exported from Google Maps or other map scrapers
- Enrich a list of company domains from a CRM, trade show or directory export
- Find contact emails and phones for local businesses, agencies, law firms, clinics and contractors
- Collect official social media profiles for brand monitoring or outreach
- Feed AI agents and automations (Make, Zapier, n8n, MCP) with structured contact data

### Use with AI agents and MCP

This Actor works through the Apify MCP server and the Apify API, so agents like Claude or ChatGPT can call it with a list of URLs and get JSON back. It is also listed on [Gouda Studios Agent Tools](https://gouda-studios-agent-tools.vercel.app/).

### FAQ

**How is this different from a Google Maps email extractor?** Map scrapers find businesses; this Actor finds the contact details on each business's own website. Run a map scraper first, then feed its website column here.

**Can I extract emails from thousands of websites at once?** Yes. Paste or upload as many URLs as you like; sites are crawled in parallel and you pay only for sites where contacts are found.

**Does it log in to sites or bypass paywalls?** No. It reads only public pages that any visitor can see, and it respects robots.txt by default.

**Why is a site marked `failed`?** The domain did not resolve, timed out, or blocked automated requests. Failed rows are free. Turning on Apify Proxy often helps with sites that block datacenter traffic.

**Is it legal to extract contact details?** Collecting publicly listed business contact information is generally lawful, but results can include personal data (for example a named employee's email). Privacy laws such as GDPR and CCPA, and anti-spam laws such as CAN-SPAM, still apply to how you store and use it. You are responsible for having a lawful basis. If in doubt, ask a lawyer.

**Does it handle JavaScript-heavy sites?** It reads the HTML the server returns, which covers the vast majority of business websites and keeps runs fast and cheap. Contact details that only appear after JavaScript runs may be missed.

### Feedback

Found a site where we missed a contact? Open an issue in the Issues tab with the URL and we will look at it.

# Actor input Schema

## `startUrls` (type: `array`):

Websites or domains to extract contacts from, one per line. Examples: https://www.example.com or example.com. Each site becomes exactly one output row.

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

How many pages to read on each site, starting with the homepage and then the most likely contact pages (Contact, About, Team, Impressum, Support). You pay per site, not per page, so higher values only cost more time.

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

Two-letter country code used to read local phone numbers that have no +country prefix, e.g. US, GB, DE, AU.

## `checkMx` (type: `boolean`):

Adds a free DNS check that each email domain can receive mail. Flags typos and dead domains.

## `respectRobotsTxt` (type: `boolean`):

Skip pages that a site's robots.txt asks crawlers not to visit.

## `proxyConfiguration` (type: `object`):

Optional. Most business sites work without a proxy. Turn on Apify Proxy if many sites time out or block requests.

## Actor input object example

```json
{
  "startUrls": [
    "https://apify.com",
    "https://www.python.org"
  ],
  "maxPagesPerSite": 8,
  "defaultCountry": "US",
  "checkMx": true,
  "respectRobotsTxt": true,
  "proxyConfiguration": {
    "useApifyProxy": false
  }
}
```

# Actor output Schema

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

No description

# 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 = {
    "startUrls": [
        "https://apify.com",
        "https://www.python.org"
    ]
};

// Run the Actor and wait for it to finish
const run = await client.actor("gouda_studios/website-contact-extractor").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 = { "startUrls": [
        "https://apify.com",
        "https://www.python.org",
    ] }

# Run the Actor and wait for it to finish
run = client.actor("gouda_studios/website-contact-extractor").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 '{
  "startUrls": [
    "https://apify.com",
    "https://www.python.org"
  ]
}' |
apify call gouda_studios/website-contact-extractor --silent --output-dataset

```

## MCP server setup

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

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/kPgZfzQ1DpFWCNnvV/builds/is388qfKhbeA4Gjaw/openapi.json
