# Website Email & Contact Finder (`makework36/email-finder-scraper`) Actor

Find email addresses, phone numbers, and social media links from any website. Crawls pages and extracts contact information automatically.

- **URL**: https://apify.com/makework36/email-finder-scraper.md
- **Developed by:** [deusex machine](https://apify.com/makework36) (community)
- **Categories:** Lead generation
- **Stats:** 90 total users, 4 monthly users, 100.0% runs succeeded, 1 bookmarks
- **User rating**: No ratings yet

## Pricing

from $5.00 / 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.

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

## What's an Apify Actor?

Actors are web data automations that power AI and operations. They run on the Apify platform to scrape websites, process data, connect APIs, and automate workflows.
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.
Actors are written with capital "A".

## 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.
The best way to integrate Actors is as follows.

- **AI agents and MCP clients** — the [Apify MCP server](https://docs.apify.com/integrations/mcp.md) at `https://mcp.apify.com` (remote, streamable HTTP, OAuth on first use).
- **Agentic workflows and local Actor development** — [Agent Skills](https://apify.com/.well-known/agent-skills/index.json) with the [Apify CLI](https://docs.apify.com/cli/docs.md): `npm install -g apify-cli`, then `apify login`.
- **JavaScript/TypeScript projects** — the official [JS/TS client](https://docs.apify.com/api/client/js/docs.md): `npm install apify-client`.
- **Python projects** — the official [Python client](https://docs.apify.com/api/client/python/docs.md): `pip install apify-client`.
- **Any other language** — the [REST API](https://docs.apify.com/api/v2.md).

For usage examples, see the [API](#api) section below.

For more details, see Apify documentation as [Markdown index](https://docs.apify.com/llms.txt) and [Markdown full-text](https://docs.apify.com/llms-full.txt).

# README

## Email Finder Scraper — Extract Emails, Phones & Social Links from Any Website for Lead Generation

> ⭐ **Useful?** [Leave a review](https://apify.com/makework36/email-finder-scraper/reviews) — it takes 10 seconds and is the single biggest thing that helps other sales and growth teams find this email finder scraper.

A fast, lightweight **email finder scraper** that crawls websites and extracts email addresses, phone numbers and social-media profile links from every reachable internal page. Give it a list of URLs and it follows internal links up to your page cap, pulling contact info across each domain. No signup to third-party contact databases, no seat-based SaaS subscription, no Hunter / Apollo / RocketReach licenses required — just clean JSON or CSV output. Built for B2B sales teams, lead-generation agencies, outbound SDRs, recruiters, data-enrichment pipelines, directory builders, journalists and anyone doing cold outreach at scale.

### ✨ Why use this scraper

Given a list of website URLs (company sites, portfolio pages, SaaS landing pages, ecommerce stores, agencies, directories — anything with a public front-end) this scraper crawls each domain with a breadth-first strategy, visits up to `maxPages` internal pages per site, and extracts three categories of contact data: email addresses, phone numbers and social-media profile URLs. It filters out common false positives (image filenames that look like emails, example addresses, partial phone fragments) so the output is immediately usable in a CRM or spreadsheet.

Every run pulls fresh data from the live site — contact pages change, staff come and go, and social profiles migrate between platforms, so the scraper hits each domain live. Export the dataset as **JSON**, **CSV**, **Excel**, or **XML** directly from the Apify console or via the Apify API.

Commercial email-finder databases (Hunter, Apollo, RocketReach, Lusha, Snov) charge per-lead and cap you with monthly quotas. They're excellent for discovering named individuals at large companies but expensive and redundant when all you need is the public contact page of a known set of websites. This scraper is the opposite tool: you already have the domains — you just need the contact info on them. No seats, no per-lead pricing, no quota, no stale "last verified 6 months ago" data.

### 📤 Output fields

#### Domain record

One output record per crawled domain. Domains where neither emails nor phones are found are excluded from the output.

| Field | Type | Description |
|-------|------|-------------|
| `domain` | string | Website hostname (e.g. `acme.com`, `stripe.com`) |
| `emails` | array<string> | All unique email addresses found, lowercased |
| `phones` | array<string> | All unique phone numbers from `tel:` links and visible text |
| `socialLinks` | array<string> | Full URLs to Facebook, X/Twitter, LinkedIn, Instagram, YouTube and TikTok profiles |
| `scrapedAt` | string | ISO 8601 timestamp of when the domain was crawled |

#### Email extraction details

- Regex-based matching against RFC-5322-style address patterns
- Automatic de-duplication and lowercasing (so `John@Example.com` and `john@example.com` collapse into one entry)
- Heuristic filters to drop image-asset filenames (`banner@2x.png`, `logo@3x.jpg`) and obvious placeholders (`user@example.com`)

#### Phone number extraction details

- Captures `tel:` anchor hrefs — the most reliable signal
- Supplements with strict visible-text pattern matching (North American `(XXX) XXX-XXXX` and international `+CC XX XXXX XXXX` formats)
- Requires proper separators (hyphens, spaces, parentheses) to avoid false positives on zip codes, product SKUs and random number strings

#### Social link extraction

Matches anchor hrefs against six major platforms:

- [Facebook](https://www.facebook.com/)
- X / Twitter
- [LinkedIn](https://www.linkedin.com/)
- [Instagram](https://www.instagram.com/)
- [YouTube](https://www.youtube.com/)
- TikTok

### 🎯 Use cases

- **B2B lead generation** — feed a list of target-account domains (from ZoomInfo, Crunchbase, or an ICP filter) and get back direct contact emails for cold outreach.
- **Cold email outreach campaigns** — power SDR and founder-led outbound with verified-public emails instead of paying per-lead to Hunter or Apollo.
- **Agency sales** — scrape leads lists (directories like Clutch, UpCity, G2) and extract contact info for agency-to-agency outreach.
- **Data enrichment pipelines** — append emails / phones / socials to your existing CRM records (Salesforce, HubSpot, Pipedrive, Copper).
- **Directory and marketplace building** — aggregate contact info from hundreds of local business sites to power a searchable directory.
- **Recruiter sourcing** — scrape portfolio sites, personal-brand domains and "about me" pages for candidate contact info.
- **Journalism and investigative research** — find press contacts across many company or nonprofit sites quickly.
- **Competitive intelligence** — monitor which social platforms your competitors are actively promoting (via `socialLinks`).

### 🚀 How to use

#### Quick scan of a few websites

```json
{
  "urls": ["https://stripe.com/", "https://linear.app/"],
  "maxPages": 15
}
```

#### Single-site deep crawl

```json
{
  "urls": ["https://basecamp.com/"],
  "maxPages": 50
}
```

#### Bulk domain enrichment for a prospect list

```json
{
  "urls": [
    "https://acme.com/", "https://globex.io/", "https://soylent.co/",
    "https://initech.com/", "https://hooli.xyz/", "https://pied-piper.com/"
  ],
  "maxPages": 10
}
```

#### Quick contact-only scan (minimal pages)

```json
{
  "urls": ["https://example-agency.com/"],
  "maxPages": 5
}
```

Setting `maxPages` low keeps runs cheap and fast when you know the contact info will be on the homepage, `/about`, `/contact` or `/team`.

### 📥 Input

| Parameter | Type | Default | Description |
|-----------|------|---------|-------------|
| `urls` | array<string> | — | Website URLs to crawl (required). Include the `https://` prefix. |
| `maxPages` | integer | `10` | Max internal pages to follow per domain (1–100). |

### 📋 Output example

```json
{
  "domain": "stripe.com",
  "emails": [
    "support@stripe.com",
    "press@stripe.com",
    "complaints@stripe.com"
  ],
  "phones": [
    "+1 (888) 926-2289",
    "+353 1 561 9700"
  ],
  "socialLinks": [
    "https://twitter.com/stripe",
    "https://linkedin.com/company/stripe",
    "https://facebook.com/StripeHQ",
    "https://youtube.com/@stripe"
  ],
  "scrapedAt": "2026-04-22T14:30:00.000Z"
}
```

Export the full dataset as CSV directly from the Apify console, or programmatically via the Apify API.

### 💻 Code examples

#### From the Apify API (curl)

```bash
curl -X POST 'https://api.apify.com/v2/acts/makework36~email-finder-scraper/run-sync-get-dataset-items?token=YOUR_TOKEN' \
  -H 'Content-Type: application/json' \
  -d '{
    "urls": ["https://stripe.com/", "https://linear.app/"],
    "maxPages": 15
  }'
```

#### From Python (apify-client)

```python
from apify_client import ApifyClient

client = ApifyClient("YOUR_APIFY_TOKEN")
run = client.actor("makework36/email-finder-scraper").call(run_input={
    "urls": [
        "https://acme.com/",
        "https://globex.io/",
        "https://initech.com/",
    ],
    "maxPages": 10,
})
for domain in client.dataset(run["defaultDatasetId"]).iterate_items():
    print(domain["domain"], "→", len(domain["emails"]), "emails,",
          len(domain["phones"]), "phones")
    for email in domain["emails"]:
        print(f"  {email}")
```

#### From Node.js (apify-client)

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

const client = new ApifyClient({ token: 'YOUR_APIFY_TOKEN' });

const run = await client.actor('makework36/email-finder-scraper').call({
  urls: [
    'https://acme.com/',
    'https://soylent.co/',
    'https://hooli.xyz/',
  ],
  maxPages: 15,
});

const { items } = await client.dataset(run.defaultDatasetId).listItems();
console.table(items.map((d) => ({
  domain: d.domain,
  emails: d.emails.length,
  phones: d.phones.length,
  socials: d.socialLinks.length,
})));
```

#### Export to CSV

From the console run page → *Export* → *CSV*. Or via API:

```
https://api.apify.com/v2/datasets/DATASET_ID/items?format=csv&token=YOUR_TOKEN
```

#### Integrate with a Google Sheet (via Make.com or Zapier)

1. **Trigger** — Google Sheets *New Row* (a new domain is added to your prospect sheet).
2. **Action** — Apify *Run an Actor synchronously* → `makework36/email-finder-scraper` → pass `{ "urls": [new_row_domain] }`.
3. **Action 2** — Google Sheets *Update Row* → write back the extracted emails / phones / socials to the adjacent columns.

You now have a fully automated enrichment pipeline without writing a line of code.

### ⚡ Performance

- **Crawls up to 5 pages concurrently** per run for parallelism without overloading target sites
- **~$0.25–0.50 per 1,000 pages crawled** on the Apify platform
- Uses [Cheerio](https://cheerio.js.org/) (HTML-only, no browser) — dramatically cheaper and faster than browser-based alternatives
- Typical 10-page crawl of a site finishes in 5–15 seconds
- 2 automatic retries per failed request
- Same-domain link strategy prevents the crawler from wandering off-site

### 📊 Comparison

The email-finder landscape has a dozen-plus tools across scraper marketplaces, commercial data providers, and browser extensions. Here's how this scraper stacks up on the metrics that matter for bulk enrichment.

| Feature | This email finder scraper | Commercial contact database (pay-per-lead) | Scraper with residential proxy | Browser-extension email finder |
|---------|---------------------------|--------------------------------------------|--------------------------------|--------------------------------|
| Pricing model | **Pay-per-page (~$0.25/1K)** | Per-lead / per-seat ($50–$500/mo) | Per-page but 3–5× more expensive | Per-seat ($40–$200/mo) |
| Crawls multi-page per site | **Yes** (configurable `maxPages`) | N/A (pre-indexed) | Yes | Typically manual |
| Data freshness | **Real-time** (each run is live) | Hours to months old | Real-time | Real-time |
| Phone number extraction | **Yes** (tel: + strict regex) | Yes | Partial | Rare |
| Social media links | **Yes** (6 platforms) | Partial | No | No |
| Needs signup to third-party data provider | **No** | Yes | No | Yes |
| Cheerio vs headless browser | **Cheerio (fast, cheap)** | N/A | Residential + browser (slow, expensive) | Browser-based |
| Supports bulk-domain input | **Yes** (array input) | Yes | Yes | Typically one-by-one |
| Deduplication across pages | **Yes** (per domain) | Yes | Partial | No |
| Works on any public website | **Yes** | Limited to indexed companies | Yes | Yes |
| GDPR-friendly ("public website" basis) | **Yes** (B2B interest) | Varies by provider | Same as this | Same as this |

The honest take: if you need to discover named individuals at Fortune 500 companies (e.g. find the VP of Marketing at Adobe), a commercial contact database like Hunter or Apollo is still the right tool. For anything that boils down to "here's a list of domains, get me their public contact info" — this scraper is 10–50× cheaper.

### 💵 Pricing

Pay-per-result model:

- **~$0.25–0.50 per 1,000 pages crawled**
- Apify gives every new user a $5 free trial → tens of thousands of pages to evaluate the scraper
- No subscription, no minimum, no egress fees

### ❓ FAQ

#### Is scraping emails legal?

This scraper only reads publicly visible contact information on company websites — the same data any browser visitor can see. In most jurisdictions, B2B contact scraping for legitimate outreach falls under "legitimate interest" (GDPR Article 6(1)(f)) or equivalent legal basis. However, downstream *use* of the emails (e.g. cold email campaigns) is regulated separately — CAN-SPAM in the US, CASL in Canada, GDPR + ePrivacy in the EU. Consult legal counsel for your use case and jurisdiction.

#### Does it find emails hidden behind JavaScript?

No. This scraper uses [Cheerio](https://cheerio.js.org/) which only parses server-rendered HTML. Sites that render their contact details via React / Vue / Angular *after* initial page load won't expose those emails here. For JS-rendered sites, a headless-browser scraper is the right alternative.

#### Does it filter out junk emails?

Yes. The scraper drops image-asset filenames that happen to contain `@` (`logo@2x.png`, `hero@3x.jpg`) and common placeholder addresses (`user@example.com`, `name@example.org`).

#### Why are some phone numbers skipped?

Phone extraction uses strict pattern matching — numbers must have real separators (parentheses, dashes, spaces) and be 10–15 digits. This is a deliberate trade-off: we'd rather miss a few unusually formatted numbers than flood your output with zip codes and random numeric strings.

#### Does it return emails verified as deliverable?

No. This is a scraping tool, not a verification service. The extracted emails are public strings as they appear on the site. If you need deliverability verification, pipe the output into [NeverBounce](https://www.neverbounce.com/), [ZeroBounce](https://www.zerobounce.net/) or a similar service.

#### Can I crawl subdomains?

The crawler uses a same-domain strategy (`enqueueLinks` with `strategy: "same-domain"`). Subdomains (`blog.acme.com` vs `acme.com`) are treated as separate domains — add each explicitly if you want to crawl both.

#### What happens on sites behind Cloudflare or DataDome?

Cheerio-based scraping works on most sites but can be blocked by aggressive bot-protection setups (Cloudflare "I'm Under Attack" mode, DataDome with strict challenges). For those targets, a browser-based scraper with residential proxy is the right escalation.

#### Can I whitelist specific page types (e.g. /contact, /team)?

Not at input level yet — the scraper follows all same-domain links up to `maxPages`. You can simulate whitelisting by passing the specific page URLs directly (e.g. `["https://acme.com/contact", "https://acme.com/about"]`) instead of the homepage.

#### How do I avoid duplicate crawls when running across many domains?

The output is already deduplicated per domain. If you run this scraper weekly, store the output and diff against the previous run — new emails and phone numbers surface as fresh hires are added to team pages.

### 📝 Changelog

- **v1.1** (2026-04-22) — Full SEO rewrite, added Python / Node / curl examples, anonymized comparison table, advanced usage patterns, Google Sheets integration guide.
- **v1.0** (2026-03-15) — Initial release with Cheerio crawler, email + phone + social extraction, strict false-positive filters and same-domain crawling.

### 🔗 Related actors

- [Facebook Comments Scraper](https://apify.com/makework36/facebook-comments-scraper) — extract comments and reactions from public Facebook posts
- [Threads Scraper](https://apify.com/makework36/threads-scraper) — posts and profiles from Meta Threads
- [Reddit Scraper](https://apify.com/makework36/reddit-scraper) — threads and comments from Reddit
- [Fast Airbnb Price Scraper](https://apify.com/makework36/fast-airbnb-price-scraper) — Airbnb listings and prices
- [VRBO Scraper](https://apify.com/makework36/vrbo-scraper) — vacation-rental listings and pricing

# Actor input Schema

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

Websites to find emails on

## `maxPages` (type: `integer`):

Maximum pages to crawl per website

## Actor input object example

```json
{
  "urls": [
    "https://www.example.com/"
  ],
  "maxPages": 10
}
```

# Actor output Schema

## `dataset` (type: `string`):

All scraped items in the default dataset (JSON).

## `csv` (type: `string`):

Default dataset formatted as CSV for spreadsheets (Google Sheets, Excel).

# 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": [
        "https://www.example.com/"
    ]
};

// Run the Actor and wait for it to finish
const run = await client.actor("makework36/email-finder-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": ["https://www.example.com/"] }

# Run the Actor and wait for it to finish
run = client.actor("makework36/email-finder-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": [
    "https://www.example.com/"
  ]
}' |
apify call makework36/email-finder-scraper --silent --output-dataset

```

## MCP server setup

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