# Company Email Finder — B2B Contact Discovery API (`nexgendata/company-email-finder`) Actor

Find the business emails a company publishes on its own website. Give it company domains, get one row per address — email, role or personal type, source page, email provider and an MX check that the domain accepts mail. Delivers to Notion via Apify MCP connectors. No API key. Pay per record.

- **URL**: https://apify.com/nexgendata/company-email-finder.md
- **Developed by:** [NexGenData](https://apify.com/nexgendata) (community)
- **Categories:** Lead generation, Automation, Business
- **Features:** Limited permissions
- **Stats:** 234 total users, 7 monthly users, 90.8% runs succeeded, 0 bookmarks
- **User rating**: No ratings yet

## Pricing

from $100.00 / 1,000 business email records

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

## Company Email Finder

Company Email Finder is a NexGenData tool on Apify that returns business email addresses with role type, source page and an MX check from each company's own website.

Find the email addresses a company publishes on its own website. Give it company domains, get back one clean JSON row per address — deduplicated, classified as `role` or `personal`, with an MX check that the domain accepts mail.

> Output is a prospect list assembled from the company's own public web pages. Addresses are **not SMTP-verified**. Use it in line with applicable outreach and privacy law.

### What it does

For each domain the actor fetches the homepage plus common contact/about/team/legal pages (`/contact`, `/about`, `/team`, `/impressum`, `/privacy`, …), extracts every address on that domain (visible text and `mailto:` links), drops placeholders (`john.doe@`, `email@`, …) and vendor noise, deduplicates, and reports the domain's MX records. It does **not** guess addresses, infer names or titles, score confidence, or verify deliverability. Optionally the same rows are delivered to Notion or Supabase.

Every domain ends in exactly one outcome and the run status message names the counts:
`N domains: A delivered X emails, B had no published emails, C unreachable, D blocked, E not processed (time budget)`.

- **delivered** — at least one address found and pushed.
- **no published emails** — the site served at least one page from its own host, and it contains no address on that domain.
- **unreachable** — DNS failure, connection error, timeout or an error status on every page tried (a dead or JavaScript-only site).
- **blocked** — 401/403/429/503 or a bot-wall page.
- **not processed** — the run's time budget ran out before the domain started.

If a run finds nothing to deliver — every site was unreachable or blocked, the sites publish no email address, or the entries are not domains (a bare company name such as "Stripe" is skipped; use stripe.com) — it ends **SUCCEEDED with 0 rows**, a status message that says why, and nothing charged beyond the run start. Non-Latin domains (for example münchen.de) are looked up in their ASCII form.

### Input

The only required field is `domains` — a list of company domains or URLs (up to 200 per run). Everything else is optional delivery configuration.

#### Example input

```json
{
  "domains": ["postmarkapp.com", "apple.com", "https://notion.so"]
}
```

#### Configuration

| Field | Type | Required | Description |
|---|---|---|---|
| `domains` | array of strings | **Yes** | Company domains or URLs to scan (e.g. `stripe.com`, `https://apple.com`). Max 200 per run; domains are processed 3 at a time and any that cannot start inside the run timeout are reported as not processed. |
| `notionConnector` | string | No | Connect a Notion workspace to also write the found emails to a Notion page. |
| `notionParentId` | string | No | Notion page ID to create the page under. Leave blank to create a private page. |
| `supabaseConnector` | string | No | Connect your own Supabase project to also insert rows into a table. |
| `supabaseTable` | string | No | Target table in the public schema. Defaults to `nexgendata_leads`, created if missing. |
| `supabaseProjectId` | string | No | Your Supabase project reference (e.g. `abcdefghijklmnop`), required unless the connector URL already includes it. |
| `deliveryDedup` | boolean | No | When on (default), rows already delivered in a previous run are not delivered again. |

### Output

One record per email address (8 fields). Only email rows are ever written — no sentinel or error rows.

| Field | Description |
|---|---|
| `email` | The address found (lower-cased). |
| `emailType` | `role` for functional mailboxes (`info@`, `sales@`, `support@`, `hr@`, `press@`, …), otherwise `personal`. |
| `source` | The page the address was parsed from: `Homepage (https://domain)` or `Page (https://domain/contact)`. |
| `domain` | Requested company domain the address belongs to. |
| `companyName` | The homepage `<title>` text, when available. |
| `emailProvider` | Mail provider inferred from MX records (Google Workspace, Microsoft 365, Zoho Mail, ProtonMail, Mimecast, Proofpoint, or Unknown). |
| `mxRecords` | The domain's MX records as `[{"priority": 10, "exchange": "host"}]` (empty list if none). |
| `verified` | `true` when the domain has MX records (it accepts mail). This is an MX check only — the address itself is not SMTP-verified. |

#### Example output

```json
{
  "email": "support@postmarkapp.com",
  "emailType": "role",
  "source": "Page (https://postmarkapp.com/contact)",
  "domain": "postmarkapp.com",
  "companyName": "Postmark: Fast, reliable email delivery",
  "emailProvider": "Google Workspace",
  "mxRecords": [{"priority": 1, "exchange": "aspmx.l.google.com"}],
  "verified": true
}
```

**Pricing:** $0.10 per email row (Pay-Per-Event) plus $0.00005 actor start — about **10 emails per $1**. Domains with no published emails, unreachable or blocked domains cost nothing beyond the start event.

### Use with AI agents

Point Claude, the OpenAI Agents SDK, an n8n flow or any MCP-aware client at it and run prospecting on demand.

**Agentic payments (x402):** Supports agentic payment via x402 — agents can call this actor with USDC, no API key required.

### Run it on a schedule

The emails a company publishes on its own website change slowly, so a monthly run over your target domains is usually enough. Run it more often only while you are adding new accounts to the list. Between runs you may see new addresses that a company added to its contact, about or team pages, and addresses that disappeared. The actor removes duplicates within a run, but it does not remember earlier runs, so compare results by `email` to find addresses that are new. Send each run's results onward with a webhook, Google Sheets, Zapier, Make or the Apify API.

Video guides from Apify: [Schedule your Actor](https://www.youtube.com/watch?v=1jI7WcVQmwM) · [Integrations](https://www.youtube.com/watch?v=bNACk1_S_6w)

### FAQ

#### Why use this instead of checking each company's website by hand?

You can find these addresses yourself by reading each site's contact pages. This actor does it for up to 200 domains per run. It checks the homepage and common contact, about, team, support, legal and privacy pages, removes placeholders and duplicates, marks each address as `role` or `personal`, records the page it came from, and reports the domain's mail provider from its MX records. It needs no subscription or separate API key, and you pay only for emails it finds.

#### What does a typical run cost?

You pay per result, not for run time: $0.10 for each row in the results, plus $0.00005 per run start (charged per GB of run memory, minimum one). A run that returns 5 emails costs about $0.50. Live prices are always shown in the Pricing tab.

#### How do I find the contact emails for a list of company domains?

Put the domains in the `domains` list, for example `stripe.com`. Each address found becomes one row with `email`, `emailType`, `source`, `domain`, `companyName`, `emailProvider`, `mxRecords` and `verified`. The run's status message also tells you how many domains had no published emails, were unreachable or were blocked.

#### Are the emails verified?

Not at the address level. `verified: true` only means the domain has MX records and accepts mail. The actor does not run SMTP checks or catch-all detection. To check deliverability, pass the results through an email verification actor.

#### Can it find a specific person's email address?

Only if the company publishes that address on its own website. It does not guess address patterns and does not return names, job titles or LinkedIn profiles. For a name plus company lookup, use Business Email Lookup.

#### What happens if a company publishes no email addresses?

That domain is reported as "no published emails" and adds no email charges. The actor has no contact database of its own, so a site that offers only a web form returns nothing.

### Related actors

- [Email Verification API — Bulk Syntax, MX & Disposable Checks](https://apify.com/nexgendata/email-verification-tool) — check the addresses you found before you send.
- [Business Email Lookup — Email Finder by Name and Domain](https://apify.com/nexgendata/person-business-email-finder) — look up a named person at a company.
- [Website Contact Details Extractor — Contact Scraper](https://apify.com/nexgendata/contact-info-scraper) — add phone numbers and social links from the same sites.
- [Company Enrichment API — Domain to Firmographics & Tech](https://apify.com/nexgendata/company-enrichment-tool) — add size, industry and tech details to each domain.
- [B2B Leads Finder — Prospects by Title, Industry & Location API](https://apify.com/nexgendata/b2b-leads-finder) — build the list of target companies in the first place.

### Related actors from NexGenData

If this actor is useful, these related ones from the same publisher may cover your next step:

- **[Person Enrichment API — Name & Company to Public Profile](https://apify.com/nexgendata/person-enrichment-lookup)** — A person's public profile from their company's own site, from name + company.
- **[Phone Number Validation API — Format, Carrier & Line Type](https://apify.com/nexgendata/phone-number-validator)** — Phone number check: format, line type, carrier and country.
- **[Google Maps Business Emails — Google Maps Email Scraper & Leads](https://apify.com/nexgendata/google-maps-extractor)** — Local businesses from Google Maps with phone, website, rating and verified emails.
- **[Local Business Leads — Google Maps + Verified Emails API](https://apify.com/nexgendata/local-business-leads-scraper)** — Local businesses by industry and city with a verified business email.
- **[Sales Intelligence MCP — B2B Leads & Enrichment for Agents](https://apify.com/nexgendata/sales-intelligence-mcp)** — B2B lead finding, enrichment, email discovery and funding tracking as AI-agent tools.

# Actor input Schema

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

List of company domains or URLs to scan for published email addresses (e.g. 'apple.com', 'https://stripe.com'). Up to 200 per run; domains are processed 3 at a time and any that cannot start inside the run timeout are reported as not processed in the run status message. Use the company's domain or website URL, not just its name. A run that finds nothing ends SUCCEEDED with 0 rows and a message; nothing is charged beyond the run start.

## `notionConnector` (type: `string`):

Optional. Connect your Notion workspace and the found email addresses are also written as a Notion page in the same run — the Actor never sees your Notion credentials. Authorize a Notion MCP connector in Apify Console → Settings → API & Integrations, then select it here.

## `notionParentId` (type: `string`):

Optional. The Notion page ID to create the page under. If blank, Notion creates a private page in your workspace.

## `supabaseConnector` (type: `string`):

Optional. Connect your own Supabase project and the results are also inserted into a table in the same run — the Actor never sees your Supabase credentials. Authorize a write-scoped, project-scoped Supabase MCP connector in Apify Console (Settings -> Integrations), then select it here.

## `supabaseTable` (type: `string`):

Target table in the public schema (created if missing, with id, a jsonb data column, and a scraped_at timestamp). Default: nexgendata_leads.

## `supabaseProjectId` (type: `string`):

Your Supabase project reference (e.g. abcdefghijklmnop). Required unless your connector URL is already project-scoped. Find it in your project URL: supabase.com/dashboard/project/THIS_PART.

## `deliveryDedup` (type: `boolean`):

When on (default), records already delivered in a previous run are not delivered again to the same destination — so scheduled runs only push new items. Turn off to deliver every record on every run.

## Actor input object example

```json
{
  "domains": [
    "postmarkapp.com",
    "https://shopify.com",
    "notion.so"
  ],
  "supabaseTable": "nexgendata_leads",
  "deliveryDedup": true
}
```

# Actor output Schema

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

One row per published email address found: email, emailType (role/personal), source page, domain, companyName, emailProvider, mxRecords, verified (MX check only).

# 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"
    ]
};

// Run the Actor and wait for it to finish
const run = await client.actor("nexgendata/company-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"] }

# Run the Actor and wait for it to finish
run = client.actor("nexgendata/company-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"
  ]
}' |
apify call nexgendata/company-email-finder --silent --output-dataset

```

## MCP server setup

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