# Email & Contact Extractor — Emails, Phones, Socials (`haketa/email-extractor`) Actor

Email and contact extractor API: crawl any website or URL list and export emails, phone numbers and social profiles (LinkedIn, Instagram, Facebook, X, YouTube, TikTok). Lead generation, contact enrichment and sales outreach data — fast, no login.

- **URL**: https://apify.com/haketa/email-extractor.md
- **Developed by:** [Haketa](https://apify.com/haketa) (community)
- **Categories:** Lead generation, Automation
- **Features:** Limited permissions
- **Stats:** 63 total users, 2 monthly users, 100.0% runs succeeded, 1 bookmarks
- **User rating**: No ratings yet

## Pricing

from $1.20 / 1,000 results

This Actor is paid per event. You are not charged for the Apify platform usage, but only a fixed price for specific events.
Since this Actor supports Apify Store discounts, the price gets lower the higher subscription plan you have.

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 Scraper & Contact Extractor — Emails, Phones & Socials from Any Website

**Paste a list of company websites or domains and get back a clean, deduplicated dataset of every email address, phone number, and social-profile link each site publishes.** This **email scraper** and **website contact extractor** crawls each domain's homepage plus its canonical contact pages — `/contact`, `/about`, `/team`, `/impressum`, `/contatti`, `/contacto`, `/kontakt` — decodes **Cloudflare-obfuscated emails** automatically, and returns one structured row per website. No login, no coding, no browser extensions.

Use it to **scrape website emails** and B2B contact intelligence at scale across `1,000+` domains in a single run. Export every result to **JSON, CSV, Excel, XML, or API**.

> **Built for** B2B sales teams, outbound agencies, recruiters, PR & media outreach teams, VC and corp-dev researchers, local-SEO agencies, and AI automation pipelines that need high-volume **contact enrichment** and **lead generation** from company URLs.

[![Apify Actor](https://img.shields.io/badge/Apify-Actor-blue)](https://apify.com/haketa/email-extractor)
[![Live Data](https://img.shields.io/badge/Data-Live%20at%20Run%20Time-orange)]()
[![Scale](https://img.shields.io/badge/Scale-1%2C000%2B%20Domains%20Supported-brightgreen)]()
[![Cloudflare](https://img.shields.io/badge/Deobfuscation-Cloudflare%20%2B%20Entity%20Decoder-purple)]()
[![Proxy](https://img.shields.io/badge/Proxy-Datacenter%20Supported-success)]()
[![Exports](https://img.shields.io/badge/Export-JSON%20%7C%20CSV%20%7C%20Excel%20%7C%20API-informational)]()

***

### ⚡ At a glance

| Feature | Details |
|---|---|
| **Input Format** | Any list of full website URLs (`https://stripe.com/contact`) or bare domains (`stripe.com`) — **1 input website = 1 aggregated output row** |
| **Multi-Page Discovery** | Probes homepage + 11 canonical English & European contact paths (`/contact`, `/contact-us`, `/about`, `/about-us`, `/team`, `/company`, `/impressum`, `/imprint`, `/contatti`, `/contacto`, `/kontakt`) |
| **Email Extraction** | `mailto:` links, visible body/footer text, **Cloudflare `data-cfemail` XOR hex decoding**, `[at]` / `(at)` / `[dot]` text deobfuscation, and `&#64;` HTML entity decoding |
| **Noise & Decoy Filtering** | Automatically strips template domains (`example.com`, `yourdomain.com`), telemetry tokens (`sentry.io`, `wixpress.com`), image retina suffixes (`@2x.png`), and hash strings |
| **Phone Extraction** | `tel:` links and verified international E.164 (`+CC`) patterns with anti-ID noise filtering |
| **8 Social Networks** | Extracts **LinkedIn, Twitter/X, Facebook, Instagram, YouTube, GitHub, TikTok, and Pinterest** company/profile URLs in a single pass |
| **Batch Scale & Speed** | Unlimited domain batching (`maxWebsites: 0`, `1,000+` domains per run) with up to `50` parallel domain workers on **Apify Datacenter Proxy** |
| **Output Formats** | JSON, CSV, Excel (XLSX), HTML Table, XML, RSS, REST API & Webhooks |

***

### 📋 Table of contents

- [Why scrape website contact data?](#-why-scrape-website-contact-data)
- [What this email & contact extractor does](#-what-this-email-scraper-does)
- [How it compares to email-finder SaaS tools](#-how-it-compares-to-email-finder-saas-tools)
- [High-value B2B use cases & industry playbooks](#-use-cases)
- [Input configuration](#-input)
- [Output data & field reference](#-output)
- [Batch scaling to 1,000+ websites](#-pagination--scale)
- [How to use (Console & API)](#️-how-to-use)
- [Pro tips for clean outreach lists](#-tips)
- [Frequently asked questions](#-faq)
- [Related contact enrichment & verification actors](#-related-scrapers)
- [Changelog](#-changelog)

***

### 🔎 Why scrape website contact data?

Nearly every business publishes contact information on its website — an `info@`, `sales@`, `hello@`, `support@`, `partnerships@`, or `press@` mailbox on `/contact`, a legal address and email on `/impressum`, a phone number in the footer, and official social links in the header. That information is **live, authoritative, and published specifically so customers, partners, and journalists can reach the company** — yet gathering it manually across hundreds or thousands of domains takes days of repetitive clicking.

Even worse, many websites hide their published email addresses behind **Cloudflare Email Address Obfuscation** (`data-cfemail` hex ciphers) or text substitutions (`sales [at] company [dot] com`, `&#64;`) that cause simple regex scrapers to return zero emails.

This **website email scraper & contact extractor** solves both problems at once:

1. It visits each domain's homepage and probes canonical contact, about, team, and legal imprint paths automatically.
2. It decodes Cloudflare hex ciphers and text obfuscations on the fly, filters out false-positive telemetry/asset strings, and consolidates every unique email, phone number, and social profile into **one clean row per website**.

**Common reasons teams use this email & contact extractor:**

- 📬 **Build B2B outbound lists** from Google Maps, directory, trade-show, or TAM exports that only contain company URLs.
- 🔄 **Enrich CRM accounts** (HubSpot, Salesforce, Pipedrive, Clay, Attio) with verified company emails, phone numbers, and 8 social links.
- 📰 **PR, podcast & media pitching** — harvest `press@`, `media@`, and `pr@` inboxes across hundreds of brand and publisher websites.
- 🤝 **Agency, partnership & affiliate outreach** — collect direct contact channels and Instagram/TikTok/YouTube profiles for e-commerce brands and creators.
- 🧑‍💼 **Recruiting & talent sourcing** — extract company LinkedIn pages, GitHub organizations, and `careers@` / `hr@` mailboxes.
- 🇪🇺 **European DACH / IT / ES B2B prospecting** — automatically scrape `/impressum`, `/kontakt`, `/contatti`, and `/contacto` where EU law mandates direct company email disclosure.
- 🤖 **AI agent & n8n/Make enrichment pipelines** — turn raw domain lists into structured contact records via webhook or REST API.

***

### ✨ What this email scraper does

- ✅ **Accepts bare domains or full URLs** — paste `stripe.com`, `https://stripe.com`, or `https://stripe.com/contact`; every input URL is normalized, deduplicated, and mapped to **one output row**.
- ✅ **Multi-page contact path crawling** — fetches your input URL first, then probes up to `maxPagesPerDomain - 1` contact paths (`/contact`, `/contact-us`, `/about`, `/about-us`, `/team`, `/company`, `/impressum`, `/imprint`, `/contatti`, `/contacto`, `/kontakt`). Missing paths (`404`) are skipped cleanly without failing the domain.
- ✅ **Cloudflare & obfuscation decoding** — decodes Cloudflare `data-cfemail` attributes, `/cdn-cgi/l/email-protection#` links, `name [at] domain [dot] com` / `(at)` / `(dot)` patterns, and `&#64;` / `&#x40;` HTML entities.
- ✅ **Strict email quality & decoy filtering** — automatically removes placeholder domains (`example.com`, `domain.com`, `yourdomain.com`, `test.com`), error-tracking DSN keys (`*.sentry.io`, `wixpress.com`), image/font file extensions (`@2x.png`, `.svg`, `.woff2`), and malformed anti-spam strings.
- ✅ **Clean phone number extraction** — captures `tel:` links and international `+CC` phone numbers while rejecting analytics IDs, timestamps, and JSON numeric tokens.
- ✅ **Eight social networks in one pass** — extracts canonical profile URLs for **LinkedIn, Twitter/X, Facebook, Instagram, YouTube, GitHub, TikTok, and Pinterest** while ignoring `/share`, `/intent`, `/login`, and individual post links.
- ✅ **High-speed HTTP architecture** — runs on standard **Apify Datacenter proxies** with per-request session rotation and configurable parallel concurrency (`1`–`50` websites at once).

***

### 📊 How it compares to email-finder SaaS tools

| Capability | Email & Contact Extractor (This Actor) | Predictive Email SaaS (Hunter / Snov / Apollo) |
|---|---|---|
| **Data Source** | Live extraction from the target website's actual pages | Static cached database + guessed `{first}.{last}` patterns |
| **Cloudflare Email Decoding** | ✅ Built-in XOR cipher + entity decoder | ❌ Often missed or outdated in static crawls |
| **EU Impressum / Contatti / Contacto** | ✅ Probed automatically on every domain | ⚠️ Rarely indexed for SMBs and local businesses |
| **Phone Numbers Included** | ✅ Yes (`tel:` + international E.164) | ⚠️ Usually costs extra mobile/phone credits |
| **Social Profiles Included** | ✅ 8 networks (LinkedIn, X, IG, FB, YT, GitHub, TikTok, Pinterest) | ⚠️ Usually LinkedIn only |
| **Pricing Model** | Pay-per-run on Apify — no monthly seat lock-in | Expensive monthly subscriptions + expiring credit tiers |

***

### 🎯 Use cases

#### 1. Local business & Google Maps lead enrichment

Local-SEO agencies, commercial service providers, and B2B reps export business websites from Google Maps, Yelp, or state contractor registries, then feed those URLs into this **website contact scraper** to harvest the `info@` / `office@` email addresses and Facebook/Instagram links that directory cards omit.

#### 2. E-commerce & DTC brand prospecting

UGC agencies, 3PL logistics providers, packaging suppliers, and Shopify app founders paste lists of e-commerce store domains to extract brand contact emails alongside **Instagram, TikTok, YouTube, and Pinterest** profile links in a single batch.

#### 3. European (DACH, Italy, Spain) B2B lead generation

Because German, Austrian, Swiss, Italian, and Spanish companies are legally required to publish a direct electronic contact address on their `/impressum`, `/imprint`, `/kontakt`, `/contatti`, or `/contacto` page, this actor achieves exceptionally high email fill rates on European SMB domains.

#### 4. Technical & open-source due diligence

Venture capital analysts, DevRel teams, and developer-tool marketers enrich software company domains with both their corporate **LinkedIn/X** presence and their official **GitHub organization URL** (`githubUrl`).

#### 5. PR, backlink & digital-marketing outreach

SEO link-builders, podcast bookers, and PR agencies scan hundreds of publication, blog, and brand domains to collect editorial (`press@`, `editor@`, `media@`) and partnership inboxes.

***

### 📥 Input

Configure the actor in the Apify Console visual form or pass a JSON payload via the API. Every field has sensible defaults — simply paste your URLs or domains into `startUrls` and click **Start**.

| Field | Type | Default / Prefill | Description |
|---|---|---|---|
| `startUrls` | array | 5 sample sites | Websites to scan. Paste full URLs (`https://eff.org`) or bare domains (`eff.org`). Each unique URL produces one output row. Leave empty to run the built-in demo sample. |
| `maxWebsites` | integer | `0` (unlimited) | Safety cap on how many websites from your list to process (`0` = process all `1,000+` websites in `startUrls`). |
| `maxPagesPerDomain` | integer | `6` | Maximum pages to crawl per website (`1` = homepage only for maximum speed; `6` = homepage + top 5 contact paths; max `30`). |
| `contactPaths` | array (string) | 11 paths | Sub-paths probed on each domain when `maxPagesPerDomain > 1`: `["/contact", "/contact-us", "/about", "/about-us", "/team", "/company", "/impressum", "/imprint", "/contatti", "/contacto", "/kontakt"]`. |
| `includeSocials` | boolean | `true` | Extract LinkedIn, Twitter/X, Facebook, Instagram, YouTube, GitHub, TikTok, and Pinterest URLs. |
| `includePhones` | boolean | `true` | Extract phone numbers from `tel:` links and international `+CC` patterns. |
| `decodeObfuscatedEmails` | boolean | `true` | Decode Cloudflare `data-cfemail` hex ciphers, `[at]`/`[dot]` text tricks, and `&#64;` HTML entities. |
| `maxConcurrency` | integer | `5` (max `50`) | Number of websites crawled in parallel. Increase to `15`–`30` for large `1,000+` domain lists. |
| `requestDelay` | integer (ms) | `500` | Polite delay in milliseconds between page fetches within the same website (`0`–`10000`). |
| `proxyConfiguration` | object | Datacenter Proxy ON | Apify Proxy configuration. Default **Datacenter proxy** rotates IPs per request and works well for company websites. |

#### Example input — B2B domain enrichment batch

```json
{
  "startUrls": [
    { "url": "https://eff.org" },
    { "url": "https://cncf.io" },
    { "url": "https://mozilla.org" },
    { "url": "https://plausible.io" },
    { "url": "https://n8n.io" }
  ],
  "maxWebsites": 0,
  "maxPagesPerDomain": 6,
  "includeSocials": true,
  "includePhones": true,
  "decodeObfuscatedEmails": true,
  "maxConcurrency": 10,
  "requestDelay": 500,
  "proxyConfiguration": {
    "useApifyProxy": true,
    "apifyProxyGroups": []
  }
}
```

***

### 📤 Output

Each input website produces **one aggregated, deduplicated JSON record** containing every email, phone number, and social profile found across the pages crawled on that domain.

#### Sample output record

```json
{
  "inputUrl": "https://eff.org",
  "rootDomain": "eff.org",
  "title": "Electronic Frontier Foundation | Defending your rights in the digital world",
  "emails": [
    "activist@eff.org",
    "extension-devs@eff.org",
    "hr@eff.org",
    "info@eff.org",
    "membership@eff.org",
    "press@eff.org"
  ],
  "phones": [
    "+14154369333"
  ],
  "linkedinUrl": "https://www.linkedin.com/company/EFF",
  "twitterUrl": "https://x.com/EFF",
  "facebookUrl": "https://www.facebook.com/eff",
  "instagramUrl": "https://www.instagram.com/efforg",
  "youtubeUrl": "https://www.youtube.com/@efforg",
  "githubUrl": "https://github.com/EFForg",
  "tiktokUrl": "https://www.tiktok.com/@efforg",
  "pinterestUrl": null,
  "emailCount": 6,
  "phoneCount": 1,
  "socialCount": 6,
  "pagesScraped": [
    "https://eff.org",
    "https://eff.org/contact",
    "https://eff.org/about"
  ],
  "fetchedPagesCount": 3,
  "errors": [
    "https://eff.org/contact-us → HTTP 404, 19526B",
    "https://eff.org/about-us → HTTP 404, 19611B"
  ],
  "scrapedAt": "2026-11-10T02:00:00.000Z"
}
```

#### Output field reference & coverage

##### 🌐 Domain Identity & Crawl Metadata

| Field | Type | Coverage | Description |
|---|---|---|---|
| `inputUrl` | string | 🟢 High (100%) | Normalized URL from your input list (ideal for joining back to your source spreadsheet/CRM). |
| `rootDomain` | string | 🟢 High (100%) | Clean registrable root domain without `www.` or protocol (e.g. `eff.org`). |
| `title` | string|null | 🟢 High (~95%) | HTML `<title>` of the homepage or first reachable page on the domain. |
| `pagesScraped` | array (string) | 🟢 High (100%) | List of URLs on the domain that returned HTTP 200 and were parsed. |
| `fetchedPagesCount` | integer | 🟢 High (100%) | Total number of pages successfully fetched and scanned for this domain. |
| `errors` | array|null | 🟡 Conditional | Diagnostic list of sub-paths that returned 404/timeout (or `null` when all probed paths succeeded). |
| `scrapedAt` | string | 🟢 High (100%) | ISO 8601 timestamp of the extraction run. |

##### 📬 Extracted Emails, Phones & Counts

| Field | Type | Coverage | Description |
|---|---|---|---|
| `emails` | array (string) | 🟡 Conditional (Site-dependent) | Sorted array of unique, lowercase, de-obfuscated email addresses found across the domain. |
| `phones` | array (string) | 🟡 Conditional (Site-dependent) | Array of unique phone numbers extracted from `tel:` links and `+CC` patterns. |
| `emailCount` | integer | 🟢 High (100%) | Number of unique emails in `emails` (`0` when the site publishes no email). |
| `phoneCount` | integer | 🟢 High (100%) | Number of unique phone numbers in `phones`. |
| `socialCount` | integer | 🟢 High (100%) | Number of distinct social networks found for this domain (`0`–`8`). |

##### 🔗 Social Media Profile Fields (8 Networks)

| Field | Type | Coverage | Description |
|---|---|---|---|
| `linkedinUrl` | string|null | 🟡 Conditional (~56%) | Official LinkedIn company/school/personal profile URL. |
| `twitterUrl` | string|null | 🟡 Conditional (~54%) | Official Twitter / X profile URL. |
| `facebookUrl` | string|null | 🟡 Conditional (~49%) | Official Facebook page URL. |
| `instagramUrl` | string|null | 🟡 Conditional (~48%) | Official Instagram profile URL. |
| `youtubeUrl` | string|null | 🟡 Conditional (~50%) | Official YouTube channel or handle URL. |
| `githubUrl` | string|null | 🟡 Conditional (~25%) | Official GitHub organization or user URL. |
| `tiktokUrl` | string|null | 🟡 Conditional (~16%) | Official TikTok profile URL (`/@handle`). |
| `pinterestUrl` | string|null | 🟡 Conditional (~8%) | Official Pinterest profile URL. |

> **Honest note on coverage:** Identity and count fields (`inputUrl`, `rootDomain`, `emailCount`, `phoneCount`, `socialCount`, `pagesScraped`, `fetchedPagesCount`, `scrapedAt`) populate on **100%** of rows. Contact fields reflect what each website actually publishes: across a 74-domain verification benchmark, **87.8%** of websites yielded at least one contact signal, with **78.4%** returning social profiles and **36.5%–65%** returning direct email addresses (higher on SMB, agency, e-commerce, and EU Impressum sites; lower on Fortune 500 enterprise sites that use web-only contact forms).

***

### 🔁 Pagination & scale

Instead of paginating a single search directory, this actor scales horizontally across your **website list** (`startUrls`) and vertically across each domain's **contact pages** (`maxPagesPerDomain`):

- **1,000+ websites per run (`maxWebsites: 0`):** With `maxWebsites: 0` (the default), there is no cap on how many websites you can process in a single run. Paste `100`, `1,000`, or `5,000` domains into `startUrls` and every unique URL is queued, crawled, and output as one deduplicated row.
- **Tunable depth vs. speed:**
  - Set `maxPagesPerDomain: 1` for an ultra-fast homepage-only scan (1 request per domain).
  - Keep `maxPagesPerDomain: 6` (default) to scan the homepage plus the 5 highest-yield contact/about paths (`/contact`, `/contact-us`, `/about`, `/about-us`, `/team`).
  - Raise `maxConcurrency` to `15`–`30` when running `1,000+` domains so dozens of websites are crawled concurrently.

***

### ⚙️ How to use

#### Option 1: Apify Console (No Coding)

1. Open **Email & Contact Extractor** in the Apify Console and click **Try for free**.
2. Paste your list of company URLs or bare domains into **Websites** (`startUrls`), or upload a `.txt`/`.csv` list.
3. Choose **Max Pages Per Website** (`6` recommended for full contact-page coverage; `1` for homepage-only speed).
4. Click **Start** and download your enriched dataset as **JSON, CSV, or Excel (XLSX)**.

#### Option 2: Call via Python API

```python
from apify_client import ApifyClient

client = ApifyClient("YOUR_APIFY_TOKEN")
run = client.actor("haketa/email-extractor").call(run_input={
    "startUrls": [
        {"url": "https://eff.org"},
        {"url": "https://cncf.io"},
        {"url": "https://mozilla.org"},
    ],
    "maxWebsites": 0,
    "maxPagesPerDomain": 6,
    "maxConcurrency": 10,
})

for row in client.dataset(run["defaultDatasetId"]).iterate_items():
    print(row["rootDomain"], row["emails"], row["phones"], row["linkedinUrl"])
```

#### Option 3: Call via Node.js / JavaScript SDK

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

const client = new ApifyClient({ token: process.env.APIFY_TOKEN });
const run = await client.actor('haketa/email-extractor').call({
    startUrls: [
        { url: 'https://eff.org' },
        { url: 'https://cncf.io' },
        { url: 'https://mozilla.org' },
        { url: 'https://plausible.io' },
    ],
    maxWebsites: 0,
    maxPagesPerDomain: 6,
    decodeObfuscatedEmails: true,
    maxConcurrency: 10,
});

const { items } = await client.dataset(run.defaultDatasetId).listItems();
console.log(`Processed ${items.length} domains.`);
```

#### Option 4: Call via cURL (REST API)

```bash
curl -X POST "https://api.apify.com/v2/acts/haketa~email-extractor/runs?token=YOUR_APIFY_TOKEN" \
  -H "Content-Type: application/json" \
  -d '{
    "startUrls": [
      { "url": "https://eff.org" },
      { "url": "https://cncf.io" }
    ],
    "maxPagesPerDomain": 6,
    "includeSocials": true,
    "includePhones": true
  }'
```

***

### 🔌 CRM & Automation Integrations

Connect your extracted website contact dataset directly to your sales and marketing stack:

| Destination | Workflow |
|---|---|
| **Clay / HubSpot / Salesforce / Pipedrive** | Trigger the actor via webhook or REST API whenever a new lead domain enters your CRM, and write `emails[0]`, `phones[0]`, and `linkedinUrl` back to the account record. |
| **Make / n8n / Zapier** | Chain Google Maps or directory scrapers → **Email & Contact Extractor** → **Bulk Email Verifier** → Instantly / Smartlead / Lemlist cold outreach sequences. |
| **Google Sheets & Excel** | Export one row per domain with comma-separated `emails` and `phones` columns + 8 dedicated social profile columns (`linkedinUrl` through `pinterestUrl`). |
| **Snowflake / BigQuery / Postgres** | Schedule recurring monthly domain crawls to keep your B2B TAM contact graph fresh. |

***

### 💡 Tips

- **Filter emails to match `rootDomain` for cold outbound:** If a website mentions a third-party press or partner email, you can filter `emails` downstream so the domain after `@` matches `rootDomain`.
- **Speed up 1,000+ domain runs:** For lists of `1,000+` websites, set `maxConcurrency: 20`, `requestDelay: 300`, and `maxPagesPerDomain: 4` (covering homepage + `/contact` + `/contact-us` + `/about`) to finish thousands of websites in minutes.
- **Target EU domains with `/impressum`:** If you are scraping German, Austrian, or Swiss domains (`.de`, `.at`, `.ch`), consider putting `"/impressum"` and `"/kontakt"` at the top of `contactPaths` so they are probed even at `maxPagesPerDomain: 3`.
- **Switch to Residential Proxy only when needed:** Standard Apify Datacenter proxies work for ~95% of company websites. If your list targets heavily protected domains that return `403` in `errors`, switch `proxyConfiguration` to `RESIDENTIAL`.

***

### ❓ FAQ

**How many websites can I process in one run?**
You can process **1,000 to 10,000+ websites** in a single run. `maxWebsites` defaults to `0` (unlimited), so your entire `startUrls` list is processed.

**Can I paste bare domains like `stripe.com` without `https://`?**
Yes. The scraper normalizes `stripe.com`, `www.stripe.com`, and `https://stripe.com` automatically.

**Does it decode Cloudflare-protected emails (`[email protected]`)?**
Yes. When `decodeObfuscatedEmails: true` (default), the actor decodes both `<span data-cfemail="...">` attributes and `/cdn-cgi/l/email-protection#...` links, plus `[at]`/`[dot]` text substitutions and HTML entities.

**Why does `errors` show `HTTP 404` on some contact paths?**
Not every website uses every URL convention (for example, `eff.org` has `/contact` and `/about`, while `/contact-us` and `/about-us` return `404`). Those `404` entries are logged in `errors` for transparency and never prevent the domain's valid pages from being scraped.

**Why do some enterprise websites return `0` emails?**
Many large corporations (e.g. Stripe, Apple) intentionally publish zero `mailto:` addresses and route all inquiries through web forms. Even on those domains, the actor still captures `title` and up to 8 official social profile URLs (`linkedinUrl`, `twitterUrl`, `youtubeUrl`, `githubUrl`, etc.).

***

### 🔗 Related scrapers

Chain this **Email & Contact Extractor** with other B2B lead-generation actors by **haketa** for an end-to-end outreach workflow:

- [Bulk Company Name to Domain Finder](https://apify.com/haketa/bulk-company-domain) — convert a list of company names into official domains before feeding them into this extractor.
- [Bulk Email Verifier](https://apify.com/haketa/bulk-email-verifier) — verify extracted emails (MX records, disposable check, syntax, and deliverability) before launching cold email sequences.
- [Email Pattern Finder](https://apify.com/haketa/email-pattern-finder) — discover `{first}.{last}@domain.com` executive email patterns for any company domain.
- [Email Finder & Verifier](https://apify.com/haketa/email-finder-verifier) — find and verify individual decision-maker email addresses by name and domain.
- [Bulk Phone Number Validator](https://apify.com/haketa/bulk-phone-validator) — validate and format extracted phone numbers into E.164 with carrier/line-type intelligence.
- [Podcast Host Contact Scraper](https://apify.com/haketa/podcast-contact-scraper) — extract podcast host emails, websites, and social links by topic or keyword.

***

### 📋 Changelog

- **v1.2 (2026-11)** — Unlocked unthrottled `1,000+` website batch processing (`maxWebsites` prefill/default set to `0` = unlimited, raised `maxConcurrency` ceiling to `50`, lowered default `requestDelay` to `500 ms`), added `urls` and `domains` input array aliases, enriched prefill sample with high-coverage domains (`eff.org`, `cncf.io`, `mozilla.org`), and expanded README with SaaS comparison and coverage tables.
- **v1.1 (2026-07)** — Added suffix-level decoy/telemetry domain filtering (`*.sentry.io`, `*.wixpress.com`) and eliminated post-final-page delay per domain.
- **v1.0 (2026-05)** — Initial release with multi-page contact path probing, Cloudflare `data-cfemail` XOR hex decoder, text/entity deobfuscation, E.164 phone extraction, and 8-network social profile discovery.

# Changelog

This Actor's version history is a separate document: https://apify.com/haketa/email-extractor/changelog.md

# Actor input Schema

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

The websites to scan. Paste full URLs or bare domains — 'stripe.com', 'https://stripe.com' and 'https://stripe.com/contact' all work. Each entry becomes one output row. Leave empty to try the actor on a built-in sample of popular websites.

## `maxWebsites` (type: `integer`):

Safety cap on how many websites to process from your list in one run. Set to 0 for no limit (process the entire 1,000+ website list).

## `maxPagesPerDomain` (type: `integer`):

How many pages of each website to crawl. Page 1 is always the URL you supplied; additional pages come from the contact paths below in order. Set to 1 to only look at the page you supplied (cheapest), 5–8 for typical contact-page coverage.

## `contactPaths` (type: `array`):

Sub-paths the actor probes on each website when Max Pages Per Website > 1. The defaults cover the canonical places companies stash their contact info, including German Impressum / Italian Contatti for EU sites. Advanced — the defaults work for most lists.

## `includeSocials` (type: `boolean`):

Extract LinkedIn, Twitter/X, Facebook, Instagram, YouTube, GitHub, TikTok and Pinterest profile links.

## `includePhones` (type: `boolean`):

Extract phone numbers from `tel:` links and explicit phone patterns. Disable if you only need emails.

## `decodeObfuscatedEmails` (type: `boolean`):

Decode common email obfuscations that many sites use to hide addresses: Cloudflare /cdn-cgi/l/email-protection, 'name \[at] domain \[dot] com', '@' HTML entities, and similar. Recommended — recovers emails a plain scraper would miss.

## `maxConcurrency` (type: `integer`):

How many websites to crawl at the same time. 3–5 is friendly. Raise up to 25–50 for fast runs on 1,000+ website lists.

## `requestDelay` (type: `integer`):

Delay between page fetches inside one website. 300–800 ms is polite.

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

ON by default — Apify Datacenter rotates IPs, which is plenty for the long tail of company websites. If you target harder-to-reach or rate-limited domains, switch the group to RESIDENTIAL.

## Actor input object example

```json
{
  "startUrls": [
    {
      "url": "https://eff.org"
    },
    {
      "url": "https://cncf.io"
    },
    {
      "url": "https://mozilla.org"
    },
    {
      "url": "https://stripe.com"
    },
    {
      "url": "https://ramp.com"
    }
  ],
  "maxWebsites": 0,
  "maxPagesPerDomain": 6,
  "contactPaths": [
    "/contact",
    "/contact-us",
    "/about",
    "/about-us",
    "/team",
    "/company",
    "/impressum",
    "/imprint",
    "/contatti",
    "/contacto",
    "/kontakt"
  ],
  "includeSocials": true,
  "includePhones": true,
  "decodeObfuscatedEmails": true,
  "maxConcurrency": 5,
  "requestDelay": 500,
  "proxyConfiguration": {
    "useApifyProxy": true,
    "apifyProxyGroups": []
  }
}
```

# Actor output Schema

## `rootDomain` (type: `string`):

The website's root domain

## `title` (type: `string`):

Homepage / contact-page title

## `emails` (type: `string`):

Comma-separated emails

## `phones` (type: `string`):

Comma-separated phone numbers

## `linkedinUrl` (type: `string`):

LinkedIn profile URL

## `twitterUrl` (type: `string`):

Twitter / X profile URL

## `facebookUrl` (type: `string`):

Facebook page URL

## `instagramUrl` (type: `string`):

Instagram profile URL

## `youtubeUrl` (type: `string`):

YouTube channel URL

## `githubUrl` (type: `string`):

GitHub organisation URL

## `tiktokUrl` (type: `string`):

TikTok profile URL

## `inputUrl` (type: `string`):

Echo of the URL you supplied

## `scrapedAt` (type: `string`):

ISO timestamp

# 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": [
        {
            "url": "https://eff.org"
        },
        {
            "url": "https://cncf.io"
        },
        {
            "url": "https://mozilla.org"
        },
        {
            "url": "https://stripe.com"
        },
        {
            "url": "https://ramp.com"
        }
    ],
    "maxWebsites": 0,
    "maxPagesPerDomain": 6,
    "contactPaths": [
        "/contact",
        "/contact-us",
        "/about",
        "/about-us",
        "/team",
        "/company",
        "/impressum",
        "/imprint",
        "/contatti",
        "/contacto",
        "/kontakt"
    ],
    "proxyConfiguration": {
        "useApifyProxy": true,
        "apifyProxyGroups": []
    }
};

// Run the Actor and wait for it to finish
const run = await client.actor("haketa/email-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": [
        { "url": "https://eff.org" },
        { "url": "https://cncf.io" },
        { "url": "https://mozilla.org" },
        { "url": "https://stripe.com" },
        { "url": "https://ramp.com" },
    ],
    "maxWebsites": 0,
    "maxPagesPerDomain": 6,
    "contactPaths": [
        "/contact",
        "/contact-us",
        "/about",
        "/about-us",
        "/team",
        "/company",
        "/impressum",
        "/imprint",
        "/contatti",
        "/contacto",
        "/kontakt",
    ],
    "proxyConfiguration": {
        "useApifyProxy": True,
        "apifyProxyGroups": [],
    },
}

# Run the Actor and wait for it to finish
run = client.actor("haketa/email-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": [
    {
      "url": "https://eff.org"
    },
    {
      "url": "https://cncf.io"
    },
    {
      "url": "https://mozilla.org"
    },
    {
      "url": "https://stripe.com"
    },
    {
      "url": "https://ramp.com"
    }
  ],
  "maxWebsites": 0,
  "maxPagesPerDomain": 6,
  "contactPaths": [
    "/contact",
    "/contact-us",
    "/about",
    "/about-us",
    "/team",
    "/company",
    "/impressum",
    "/imprint",
    "/contatti",
    "/contacto",
    "/kontakt"
  ],
  "proxyConfiguration": {
    "useApifyProxy": true,
    "apifyProxyGroups": []
  }
}' |
apify call haketa/email-extractor --silent --output-dataset

```

## MCP server setup

```json
{
    "mcpServers": {
        "apify": {
            "type": "http",
            "url": "https://mcp.apify.com/?tools=fetch-actor-details,haketa/email-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/VbCWXJpXzecrynUy8/builds/GyQr1FKhM9eg4aZvd/openapi.json
