# Website Email Finder & Contact Details Scraper: Phones, Socials (`nebulacolors/website-contact-finder`) Actor

Website email finder, email extractor and contact finder: the emails, phones and social profiles (LinkedIn, Facebook, Instagram, X, YouTube, TikTok) a company lists on its home, contact, about and imprint pages. For lead lists and AI agents. $0.004 per site, free when no email or phone is found.

- **URL**: https://apify.com/nebulacolors/website-contact-finder.md
- **Developed by:** [Nebula Colors LLC](https://apify.com/nebulacolors) (community)
- **Categories:** Lead generation, Marketing, Automation
- **Stats:** 3 total users, 2 monthly users, 75.0% runs succeeded, 0 bookmarks
- **User rating**: No ratings yet

## Pricing

from $2.80 / 1,000 sites

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

## Website Contact Finder: Emails, Phones, Social Links

Give it a list of company websites and get back the emails, phone numbers and social profiles each company publishes on its own site. It reads the home page and then the pages most likely to hold contact details: contact, imprint (Impressum), about, team, press and legal pages, in many languages. $0.004 per site, and only when an email or phone number is found. It works for people and for AI agents through Apify's MCP server.

### What it's for

- Lead lists: turn a list of company domains into emails, phone numbers and LinkedIn pages.
- Enrich a CRM or a spreadsheet of accounts with the contact details each company shows publicly.
- Give an AI agent a company's public contact details before it writes to them.

### Input

| Field | What to put |
|---|---|
| Websites | One per line, like `basecamp.com` or `https://example.com/en/`. Required. |
| Pages per site | How many pages to read on each site, home page included. 10 by default, 10 at most. Contact-like pages are read first, so most sites take about 5. The price per site stays the same. |
| Max emails per site | 20 by default. Some sites list their whole staff; the company's own addresses and the ones on the home and contact pages come first. |
| Check emails | Off by default. Turn it on to check each email found: valid syntax, a mail server for its domain, and not a throwaway-address service. $0.0003 per email checked. |
| Proxy | Off by default. Turn on Apify Proxy (datacenter) for sites that block cloud servers, or give your own proxy URLs. Residential proxies aren't available in this tool. |

Example:

```json
{
  "urls": ["manufactum.de", "https://www.netventure.pl"]
}
```

### Output

One row per website, in the order you gave them. This one came from a test run on October 17, 2026 (empty social lists left out here):

```json
{
  "type": "site",
  "inputUrl": "manufactum.de",
  "url": "https://manufactum.de/",
  "finalUrl": "https://www.manufactum.de/",
  "status": "ok",
  "domain": "manufactum.de",
  "companyName": "manufactum",
  "emails": ["info@manufactum.de", "presse@manufactum.de", "behoerdenkontakt@manufactum.de", "produktsicherheit@manufactum.de", "behling@buse.de"],
  "phones": ["+492309939050", "+492309939057", "+49230993900", "+492309939270"],
  "facebook": ["https://www.facebook.com/manufactum"],
  "instagram": ["https://www.instagram.com/manufactum"],
  "pinterest": ["https://www.pinterest.com/manufactum"],
  "emailSources": [
    { "email": "info@manufactum.de", "page": "https://www.manufactum.de/" },
    { "email": "presse@manufactum.de", "page": "https://www.manufactum.de/kontakt-c199446/" },
    { "email": "behoerdenkontakt@manufactum.de", "page": "https://www.manufactum.de/impressum-c199455/" },
    { "email": "produktsicherheit@manufactum.de", "page": "https://www.manufactum.de/impressum-c199455/" },
    { "email": "behling@buse.de", "page": "https://www.manufactum.de/impressum-c199455/" }
  ],
  "emailsFound": 5,
  "contactPage": "https://www.manufactum.de/kontakt-c199446/",
  "pagesChecked": [
    "https://www.manufactum.de/",
    "https://www.manufactum.de/kontakt-c199446/",
    "https://www.manufactum.de/pressekontakt-c199458/",
    "https://www.manufactum.de/impressum-c199455/",
    "https://www.manufactum.de/datenschutz-c199450/"
  ],
  "charged": true,
  "checkedAt": "2026-10-17T04:33:35.978Z"
}
```

- `emails`: lowercase, the ones on the company's own domain first. Addresses on other domains are kept, after the company's own (in our test, 27% of them: parent companies, PR agencies, hotel groups). Placeholders (name@example.com), image names (logo@2x.png) and library paths (bootstrap@5.2.3) are left out. Addresses hidden by Cloudflare or written as "name \[at] site \[dot] com" are read.
- `phones`: in international form. They come from phone links, the site's schema.org data and numbers written like phone numbers in the text. A number without a country code is read as the site's country (its country domain, else the US).
- `linkedin`, `facebook`, `instagram`, `x`, `youtube`, `tiktok`, `pinterest`, `github`: the company's own profiles. Share buttons, single posts and the profiles of people its pages mention are left out.
- `companyName`: the name the site gives itself in its metadata, as written, without a tagline after " | ", " - " or ": ". It can be empty.
- `emailSources`: the page each email was found on. `emailsFound` says how many there were before Max emails per site.
- `emailChecks` (with Check emails on): one entry per email with a `verdict`: `ok` (its domain takes mail), `invalid` (bad syntax, no such domain, or no mail server), `disposable` (a throwaway-address service) or `unknown` (DNS didn't answer, not charged), plus the `reason` and the domain's mail servers.
- `status`: `ok`, `no_contacts`, `blocked`, `dead`, `timeout`, `disallowed` (by robots.txt) or `error`. A failed site has an `error` with the reason in plain words.

The run's `SUMMARY` record counts the sites with contact details, with none found and failed.

### Price

- $0.004 per site where at least one email or phone number is found, so $4 per 1,000. In a 50-site test, 37 had an email or phone and were charged.
- A site with a phone number and no email is charged too.
- $0.0003 for each email checked, only when you turn on Check emails. In our 50-site test the sites with an email had about 11 each, so checking them added about $0.003 a site; Max emails per site (20) caps it at $0.006. Emails DNS can't answer for aren't charged.
- Free: sites with no email or phone (even if they show social profiles), and sites that fail, block the visit or that robots.txt disallows.
- One row per website, never one per page: a site is charged once, however many pages were read.
- You can set a maximum charge for a run. It stops when it's reached and keeps what it already found.

### Good to know

- **What a test found.** In a 50-site test: an email on 35 sites, a phone on 22, LinkedIn on 14, Facebook and Instagram on 27 each.
- **Only what the company publishes.** It reads the company's own pages, the way a visitor would, and returns the contact details shown there. It doesn't guess addresses or look anywhere else.
- **Your use of the contacts.** You're responsible for using them lawfully, for example under GDPR in the EU and CAN-SPAM in the US.
- **Staff directories.** Some sites publish whole staff lists (up to 95 addresses in our test). Max emails per site keeps the first 20 by default, and `emailSources` shows which page each came from, so you can keep only the contact page's.
- **What the email check can't tell you.** It doesn't send mail or connect to the mail server, so it can't say whether one mailbox exists, only that the domain takes mail. On the 362 emails from our 50-site test, all were on domains that take mail. On 29 known cases (typos, made-up domains, throwaway services, big mail providers) it got all 29 right.
- **No browser.** It reads the pages a site serves, without running JavaScript. That's fast and cheap (50 sites in under 3 minutes in a test run), but a site whose pages are built entirely by JavaScript can show nothing. Those rows are free.
- **Blocked sites.** Some sites block cloud servers (in a 50-site test, 4 refused the visit). Turning on Apify Proxy can help; those rows are free either way.
- **Polite.** It reads each site's robots.txt and skips what it disallows, and reads one page of a site at a time. If no email or phone turns up on the contact-like pages, it reads the home page's other links, still within Pages per site.

### Use it from an AI agent

The Actor works through Apify's MCP server like any Store Actor. An agent can find it, read its input and call it. The MCP call waits 30 seconds by default (45 at most), and a few sites finish in that time. A bigger list takes longer, so the call returns the run's status and dataset ID, and the agent reads the rows with `get-dataset-items`.

### Questions or problems

Open an issue on this Actor's Issues tab. I read them.

# Actor input Schema

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

One per line: a domain like basecamp.com or an address like https://example.com/en/. Each site's home page is read, then its contact, about, imprint and team pages.

## `maxPagesPerSite` (type: `integer`):

How many pages to read on each site, home page included (1 to 10). Only the home page and pages that look like contact, about, imprint, team or legal pages are read, so most sites stop under this. The price per site stays the same.

## `maxEmailsPerSite` (type: `integer`):

Most emails to return for one site (1 to 500). Some sites list their whole staff; the company's own addresses and those on the home and contact pages come first. emailsFound on each row says how many there were in all.

## `verifyEmails` (type: `boolean`):

Checks each email found: valid syntax, a mail server for its domain (DNS MX records), and not a disposable-address service. No message is sent and the mail server isn't contacted, so it shows the domain takes mail, not that the mailbox exists. Each email checked is one email-check event; ones DNS can't answer are free.

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

Off by default. Turn on Apify Proxy (datacenter) for sites that block cloud servers, or give your own proxy URLs. Residential proxies aren't available in this tool.

## Actor input object example

```json
{
  "urls": [
    "https://basecamp.com",
    "apify.com"
  ],
  "maxPagesPerSite": 10,
  "maxEmailsPerSite": 20,
  "verifyEmails": false,
  "proxyConfiguration": {
    "useApifyProxy": false
  }
}
```

# Actor output Schema

## `sites` (type: `string`):

All site rows as JSON, in input order: inputUrl, status, domain, companyName, emails, phones, linkedin, facebook, instagram, x, youtube, tiktok, pinterest, github, emailSources, contactPage and pagesChecked. A site that failed has an error instead.

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

Sites with an email or phone, with none found and failed, and why the run stopped.

# 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://basecamp.com",
        "apify.com"
    ]
};

// Run the Actor and wait for it to finish
const run = await client.actor("nebulacolors/website-contact-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 = { "urls": [
        "https://basecamp.com",
        "apify.com",
    ] }

# Run the Actor and wait for it to finish
run = client.actor("nebulacolors/website-contact-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 '{
  "urls": [
    "https://basecamp.com",
    "apify.com"
  ]
}' |
apify call nebulacolors/website-contact-finder --silent --output-dataset

```

## MCP server setup

```json
{
    "mcpServers": {
        "apify": {
            "type": "http",
            "url": "https://mcp.apify.com/?tools=fetch-actor-details,nebulacolors/website-contact-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/RWk94vjdraNfBmghZ/builds/ZGYGxacuqtmK2PhRb/openapi.json
