# Email Finder & Verifier (`hermesexp/email-finder`) Actor

Find email addresses from any website for lead generation and sales outreach. Scrape contact pages, crawl links, and extract verified emails with domain info.

- **URL**: https://apify.com/hermesexp/email-finder.md
- **Developed by:** [Dima Radov](https://apify.com/hermesexp) (community)
- **Categories:** Marketing, Social media
- **Stats:** 2 total users, 1 monthly users, 100.0% runs succeeded, 0 bookmarks
- **User rating**: No ratings yet

## Pricing

Pay per usage

This Actor is paid per platform usage. The Actor is free to use, and you only pay for the Apify platform usage, which gets cheaper the higher subscription plan you have.

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

## 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 & Verifier

Finds and verifies email addresses from a domain. Ideal for lead generation, sales outreach, and contact discovery.

### Features

- **Website Crawling** — Crawls the website homepage, /contact, /about, /team, and linked internal pages to find published email addresses
- **Email Extraction** — Extracts emails from page text and `mailto:` links using BeautifulSoup
- **Common Pattern Generation** — Generates and tests common email patterns: info@, contact@, hello@, support@, admin@, sales@, and 25+ more
- **Name-Based Pattern Generation** — If a person's name is provided, generates common patterns: first@, first.last@, firstlast@, f.last@, and more
- **Format Validation** — Validates email format (RFC 5321-style) with detailed issue reporting
- **MX Record Checking** — Checks if the domain has valid MX records for email delivery using DNS lookup
- **Deduplication** — Automatically deduplicates emails found from multiple sources

### Input

| Field | Type | Required | Description |
|-------|------|----------|-------------|
| `domain` | string | ✅ | Domain to search (e.g., `example.com`) |
| `firstName` | string | ❌ | First name for name-based patterns |
| `lastName` | string | ❌ | Last name for name-based patterns |
| `crawlWebsite` | boolean | ❌ | Crawl website for emails (default: true) |
| `tryCommonPatterns` | boolean | ❌ | Try common email prefixes (default: true) |
| `tryNamePatterns` | boolean | ❌ | Try name-based patterns (default: true) |
| `checkMxRecords` | boolean | ❌ | Check MX records (default: true) |
| `maxCrawlPages` | integer | ❌ | Max pages to crawl (default: 10, max: 50) |

### Output

The actor outputs a summary object plus individual email entries:

#### Summary Object

```json
{
  "domain": "example.com",
  "firstName": null,
  "lastName": null,
  "stats": {
    "totalEmailsFound": 5,
    "validFormat": 4,
    "invalidFormat": 1,
    "sources": {
      "website_crawl": 3,
      "common_patterns": 10,
      "name_patterns": 0
    }
  },
  "emails": [
    {
      "email": "contact@example.com",
      "formatValid": true,
      "localPart": "contact",
      "domain": "example.com",
      "issues": [],
      "sources": ["common_patterns", "website_crawl"],
      "discoveredBy": "common_patterns"
    },
    ...
  ],
  "mxRecords": {
    "domain": "example.com",
    "hasMxRecords": true,
    "mxRecords": [
      {"preference": 10, "exchange": "mail.example.com"}
    ]
  },
  "crawlResults": {
    "pagesCrawled": ["https://example.com", "https://example.com/contact"],
    "pageErrors": {},
    "emailsFoundOnWebsite": ["contact@example.com"]
  }
}
```

#### Individual Email Entries

Each validated email is also pushed as a separate dataset item for easy CSV/JSON export, including the search domain and MX record status.

### How It Works

1. **Input Validation** — Cleans the domain and validates required fields
2. **Website Crawling** — Fetches the website homepage and common pages, extracts all visible email addresses
3. **Pattern Generation** — Generates common (info@, contact@, etc.) and name-based (first.last@) patterns
4. **Validation** — Validates each email's format with detailed RFC-style checks
5. **MX Check** — Queries DNS MX records to verify the domain can receive email
6. **Dedup & Output** — Merges, deduplicates, and outputs results

### Use Cases

- Lead generation and prospecting
- Sales outreach contact discovery
- Marketing campaign list building
- Competitor analysis
- Finding press/media contacts
- Discovering support/billing contacts

### Limitations

- Crawls publicly visible pages only — does not bypass authentication or scrape behind logins
- Email pattern generation produces likely addresses but cannot confirm deliverability without sending an actual email
- MX record checking confirms the domain can receive email, but does not verify individual email existence
- Some websites obfuscate email addresses (e.g., using JavaScript or images) which cannot be extracted with simple HTTP crawling
- Respects `robots.txt` is recommended when used at scale

# Actor input Schema

## `domain` (type: `string`):

The domain to search for email addresses (e.g., example.com). Do NOT include http:// or www.

## `firstName` (type: `string`):

First name of the person to find an email for.

## `lastName` (type: `string`):

Last name of the person to find an email for.

## `crawlWebsite` (type: `boolean`):

Crawl the website pages to find emails displayed on the site.

## `tryCommonPatterns` (type: `boolean`):

Try common email patterns like info@, contact@, hello@, support@.

## `tryNamePatterns` (type: `boolean`):

If first/last name is provided, try patterns like first@, first.last@, firstlast@.

## `checkMxRecords` (type: `boolean`):

Check if the domain has valid MX records for email delivery.

## `maxCrawlPages` (type: `integer`):

Maximum number of pages to crawl on the website.

## Actor input object example

```json
{
  "domain": "example.com",
  "crawlWebsite": true,
  "tryCommonPatterns": true,
  "tryNamePatterns": true,
  "checkMxRecords": true,
  "maxCrawlPages": 10
}
```

# 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 = {
    "domain": "example.com"
};

// Run the Actor and wait for it to finish
const run = await client.actor("hermesexp/email-finder").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 = { "domain": "example.com" }

# Run the Actor and wait for it to finish
run = client.actor("hermesexp/email-finder").call(run_input=run_input)

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

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

```

## CLI example

```bash
echo '{
  "domain": "example.com"
}' |
apify call hermesexp/email-finder --silent --output-dataset

```

## MCP server setup

```json
{
    "mcpServers": {
        "apify": {
            "command": "npx",
            "args": [
                "mcp-remote",
                "https://mcp.apify.com/?tools=hermesexp/email-finder",
                "--header",
                "Authorization: Bearer <YOUR_API_TOKEN>"
            ]
        }
    }
}

```

## OpenAPI specification

Download the OpenAPI definition: https://api.apify.com/v2/acts/x0QP9gjRhWFGaY5a7/builds/WR5yVplgyTbynqfcb/openapi.json
