# Domain Email Finder — Company Emails from a List of Domains (`actor-forge/domain-email-finder`) Actor

Paste a list of company domains and get the role mailboxes each company publishes on its own website (info@, sales@, support@, press@ …), with the page each address was found on. Personal addresses are never returned. $3 per 1,000 domains with an email found; the rest are free.

- **URL**: https://apify.com/actor-forge/domain-email-finder.md
- **Developed by:** [ActorForge](https://apify.com/actor-forge) (community)
- **Categories:** Lead generation, Automation
- **Security:** Limited permissions
- **Stats:** 2 total users, 1 monthly users, 100.0% runs succeeded, 0 bookmarks
- **User rating**: No ratings yet

## Pricing

from $3.00 / 1,000 domain 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

## Domain Email Finder — Company Emails from a List of Domains

Paste a list of company domains and get the role mailboxes each company publishes on its own website (info@, sales@, support@, press@ …), with the page each address was found on. Personal addresses are never returned. $3 per 1,000 domains with an email found; the rest are free.

**Find the email addresses a company publishes, for a whole list of domains at once.** Paste domains (or website URLs, or work emails) and the actor reads each company's own website: the home page plus up to four of its contact, imprint/Impressum, about, support, privacy and legal pages. You get **one row per domain** with the **primary email**, every **company role mailbox** it found (info@, hello@, sales@, support@, press@, partnerships@, privacy@ …) and **the page and method each address came from** (mailto link, JSON-LD, footer, page text), so every email can be checked.

**Company mailboxes only.** An address is kept only when it is a role or department mailbox on the company's own domain. Anything that looks like a person (jane@, j.smith@, initials) is dropped and only counted, never returned. This is the "domains in, generic company emails out" job for outreach lists, supplier and partner contact sheets, CRM clean-up and Clay or Zapier enrichment columns, without guessing patterns or verifying addresses.

**$3 per 1,000 domains with an email found.** Domains with no published email, unreachable or bot-protected sites and invalid inputs cost nothing.

### What data does it return?

Every run outputs clean, schema-validated rows like these:

| input | status | companyName | primaryEmail | emails | contactPageUrl |
| --- | --- | --- | --- | --- | --- |
| stripe.com | ok | Stripe | dpo@stripe.com | dpo@stripe.com, privacy@stripe.com | https://stripe.com/gb/contact/sales |
| shopify.com | no-emails | Shopify |  |  |  |
| basecamp.com | no-emails | Basecamp |  |  |  |

### How much does it cost?

Transparent pay-per-event pricing — you only pay for what you get, and the
actor **always respects your run budget**: set a maximum total charge and it
stops cleanly at the cap instead of overrunning.

| Event | Price | Charged | Worked example |
| --- | --- | --- | --- |
| `domain-contacts` | $0.003 | per domain with at least one company email found | 1,000 domains, 500 with an email = $1.50; domains without an email are free |
| `apify-actor-start` | $0.00005 | per run per GB of memory (platform start fee) | One Clay row (one run at 256 MB) = $0.004 + $0.0000125 |

### Input options

| Field | Type | Required | Default | Description |
| --- | --- | --- | --- | --- |
| `domains` | array | no | — | Company websites, one per line: domains (acme.com), URLs (https://www.acme.com/about) or work emails (jane@acme.com, only the domain is used). One row per domain, duplicates removed. Up to 100,000 per run. |
| `domain` | string | no | — | Optional: one domain, handy when a tool maps one column to one field. Added to the list above. |
| `maxDomains` | integer | no | `1000` | Stop after this many unique domains (a safety cap for big lists). |
| `maxPagesPerDomain` | integer | no | `5` | Pages read per website, home page included. The others are picked from the home page links most likely to list an email: contact, imprint/Impressum, about, support, privacy and legal. Same price whatever you pick. |

### Limits & honest notes

- Company contacts only: an email is kept only when its local part is a role or department (info, sales, support, hello, contact, press, office, billing, careers, privacy and about 200 more, in several languages) and it sits on the company's own domain, or on a free-mail domain with the brand name in it (acmeplumbing@gmail.com). Name-like addresses are dropped and counted in personalEmailsDropped. This is not a people email finder: it never guesses or builds addresses (first.last@) and never returns named people.
- Many companies publish no email at all, only contact forms. Expect an email for roughly half of company websites; the others come back as free no-emails rows.
- Emails are not verified by SMTP: they are exactly what the company published on its own pages, with the source page in emailSources.
- Reads static HTML only (no browser). Contacts that a site injects with JavaScript, or shows only as images, are not seen. Only the simple obfuscations are decoded: Cloudflare email protection and "\[at]" / "(at)" / "\[dot]" spellings.
- robots.txt is respected for every page. A 403, 429 or CAPTCHA page on the home page gives a free blocked row; on a later page the scan of that site stops (scanStoppedBy) and the row keeps what was already found. No proxies are used.
- The run's spend limit is respected: each domain is charged once, before its row is delivered; when the limit is reached the run stops.

### Related ActorForge actors

- [Contact Details Scraper](https://apify.com/actor-forge/contact-details-scraper) — emails plus phones, postal address and social profiles
- [Domain Enrichment for Clay](https://apify.com/actor-forge/domain-enrichment) — the full company row: logo, tech stack, MX, WHOIS, SSL

### Changelog

- **2026-10-23** — Initial release: email-only listing of the Contact Details Scraper engine, with the source page of every email, charged only when an email is found, $3 per 1,000 domains.

***

*Built and maintained by **ActorForge**. Reliability first: every actor in the
portfolio is monitored by an automated nightly self-test, and breakages are
typically fixed the same day.*

# Actor input Schema

## `domains` (type: `array`):

Company websites, one per line: domains (acme.com), URLs (https://www.acme.com/about) or work emails (jane@acme.com, only the domain is used). One row per domain, duplicates removed. Up to 100,000 per run.

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

Optional: one domain, handy when a tool maps one column to one field. Added to the list above.

## `maxDomains` (type: `integer`):

Stop after this many unique domains (a safety cap for big lists).

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

Pages read per website, home page included. The others are picked from the home page links most likely to list an email: contact, imprint/Impressum, about, support, privacy and legal. Same price whatever you pick.

## Actor input object example

```json
{
  "domains": [
    "stripe.com",
    "shopify.com",
    "notion.so"
  ],
  "maxDomains": 1000,
  "maxPagesPerDomain": 5
}
```

# Actor output Schema

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

One row per domain with the company emails found and their source pages (status ok = charged; everything else is free).

## `summary` (type: `string`):

Domains processed, domains with emails, free rows and personal emails dropped.

# 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 = {
    "domains": [
        "stripe.com",
        "shopify.com",
        "notion.so"
    ]
};

// Run the Actor and wait for it to finish
const run = await client.actor("actor-forge/domain-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 = { "domains": [
        "stripe.com",
        "shopify.com",
        "notion.so",
    ] }

# Run the Actor and wait for it to finish
run = client.actor("actor-forge/domain-email-finder").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 '{
  "domains": [
    "stripe.com",
    "shopify.com",
    "notion.so"
  ]
}' |
apify call actor-forge/domain-email-finder --silent --output-dataset

```

## MCP server setup

```json
{
    "mcpServers": {
        "apify": {
            "type": "http",
            "url": "https://mcp.apify.com/?tools=fetch-actor-details,actor-forge/domain-email-finder"
        }
    }
}
```

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/yF98VVB2sykBe2La6/builds/d9E0GOa3ZnAnqXiO3/openapi.json
