# Website Contact Finder for Emails & Phones (`goldish_fireplace/website-contact-finder`) Actor

Extract emails, phone numbers and social profiles from a list of websites. One deduplicated row per domain, junk emails filtered, mail domains checked. Fast, no browser.

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

## Pricing

from $2.10 / 1,000 processed domains

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: Email Extractor, Phone Number & Social Media Scraper for Websites

**Turn a list of websites or domains into contact details.** This email extractor and contact details scraper visits each website's homepage, contact, about, team and imprint pages and returns **one deduplicated row per website** with emails, phone numbers (E.164) and social profiles (LinkedIn, X/Twitter, Facebook, Instagram and more). Use it for lead generation, CRM enrichment and B2B prospect lists.

**Website Contact Finder** takes a list of websites and returns **one clean row per website** with the company's **emails, phone numbers and social profiles**. It checks the homepage plus the pages that actually hold contact details (Contact, About, Team, Impressum/Imprint), throws away junk addresses, checks that each email domain can receive mail, and hands you a spreadsheet you can use straight away.

It's fast and cheap because it reads plain HTML over HTTP with no headless browser: a typical website takes under a second.

### What does it find?

| Data | Details |
| --- | --- |
| **Emails** | `mailto:` links, addresses written on the page, obfuscated ones (`name [at] company [dot] com`, `(at)`, `{at}`, `(punkt)`, full-width ＠), **Cloudflare-protected emails** (decoded), and JSON-LD `email` fields |
| **Phone numbers** | `tel:` links and numbers written on the page, **validated** with Google's libphonenumber and returned in international **E.164** format (`+27212017500`). Country is guessed from the domain (.de, .co.uk, .co.za...) or set by you |
| **Social profiles** | LinkedIn, X/Twitter, Facebook, Instagram, YouTube, TikTok, GitHub, Pinterest, Threads, WhatsApp, Telegram, Discord. Share buttons, intent links and post URLs are ignored; the company's own handle is ranked first |
| **Contact page** | The URL of the best contact page found, so you can open it in one click |
| **Proof** | `emailSources` shows the page each email came from; `rejectedEmails` shows what was thrown away and why |

### Why use it?

- 🧹 **One deduplicated row per website.** No merging step, no "one row per page" mess. `www.`/non-`www`, `http`/`https` and repeated inputs are merged automatically.
- 🚫 **No junk emails.** Filters image names (`logo@2x.png`), placeholders (`you@example.com`, `name@domain.com`, `max.mustermann@`), tracking hashes (Sentry, Wix), `noreply@` and text glued together from neighbouring elements. Emails whose domain can't receive mail are dropped by a DNS (MX) check.
- 📊 **CSV and Google Sheets ready.** Besides the arrays you get flat columns: `primaryEmail`, `emailsJoined`, `primaryPhone`, `phonesJoined`, `linkedin`, `twitter`, `facebook`, `instagram`, `youtube`, `tiktok`, `github`.
- ⚡ **Fast and light.** HTTP-only, 256 MB memory, many websites in parallel. 5 websites finished in under 3 seconds in our tests.
- 💸 **Pay per website, not per page.** Failed websites (dead domains, timeouts, blocked) are listed with the reason and **never charged**.
- 🎯 **Smart page picking.** Finds contact pages in many languages (Kontakt, Contacto, Impressum, Über uns, Mentions légales...), and tries `/contact` and `/about` when the menu is built with JavaScript.
- ✉️ **Pairs with Email Checker.** Pass this run's dataset ID to **Email Checker** to validate every address before outreach.

### How to use Website Contact Finder

1. Paste your websites into **Websites**, one per line. Bare domains (`acme.com`), full URLs or even email addresses (`jane@acme.com` → `acme.com`) work.
2. Optional: change **Max pages per website** (default 5), turn phones or socials off, or keep only emails on the website's own domain.
3. Click **Start**. Open the **Output** tab, then export to CSV, Excel, JSON or Google Sheets.

### Input example

```json
{
    "domains": ["apify.com", "plausible.io", "truth.coffee", "hetzner.com"],
    "maxPagesPerDomain": 5,
    "includePhones": true,
    "includeSocials": true,
    "verifyEmailDomains": true,
    "onlyOwnDomainEmails": false
}
```

### Output example

One item per website (real output for a small Cape Town coffee roaster, run on 1 Nov 2026):

```json
{
    "domain": "truth.coffee",
    "url": "https://truth.coffee/",
    "status": "ok",
    "error": null,
    "primaryEmail": "info@truth.coffee",
    "emails": ["info@truth.coffee", "needbeans@truthcoffee.com", "marketing@truthcoffee.com"],
    "emailCount": 3,
    "emailsJoined": "info@truth.coffee, needbeans@truthcoffee.com, marketing@truthcoffee.com",
    "primaryPhone": "+27212017500",
    "phones": ["+27212017500", "+27212017000"],
    "phonesJoined": "+27212017500, +27212017000",
    "socials": {
        "facebook": ["https://www.facebook.com/truth.coffee"],
        "instagram": ["https://www.instagram.com/truth.coffee.roasting", "https://www.instagram.com/truthcoffee"]
    },
    "linkedin": null,
    "twitter": null,
    "facebook": "https://www.facebook.com/truth.coffee",
    "instagram": "https://www.instagram.com/truth.coffee.roasting",
    "contactPageUrl": "https://truth.coffee/pages/contact-us",
    "emailSources": {
        "info@truth.coffee": "https://truth.coffee/pages/contact-us",
        "needbeans@truthcoffee.com": "https://truth.coffee/",
        "marketing@truthcoffee.com": "https://truth.coffee/pages/policies-and-terms"
    },
    "rejectedEmails": [],
    "pagesChecked": 5,
    "durationMs": 859
}
```

More rows from the same test run:

| Website | Best email | Phones | LinkedIn / X | Pages | Time |
| --- | --- | --- | --- | --- | --- |
| apify.com | support@apify.com (+ hello@) | none listed | linkedin.com/company/apify · x.com/apify | 4 | 0.4 s |
| plausible.io | hello@plausible.io | none listed | linkedin.com/company/plausible-analytics · x.com/plausiblehq | 5 | 0.2 s |
| hetzner.com | 5 emails incl. info@hetzner.com | 6, E.164 | linkedin.com/company/hetzner-online · x.com/Hetzner_Online | 5 | 2.6 s |
| no-such-domain-xyz123abc.com | *failed: "Domain does not exist (no DNS records)"*, not charged | | | 0 | 0.1 s |

A **SUMMARY** record in the key-value store shows how many websites were processed, failed and had emails.

### How much does it cost?

You pay a small fixed price **per website processed** (see the **Pricing** tab). Platform usage is minimal because no browser is used and the default memory is 256 MB. Websites that fail (domain doesn't exist, site down, blocked) are **free**. Set a maximum cost per run and the Actor stops before going over it.

### Responsible use and GDPR

This Actor only reads **publicly published business contact details** from the websites you give it. It doesn't log in, bypass paywalls or CAPTCHAs, or guess addresses that aren't on the page.

Contact details can still be **personal data** (for example `jane.smith@company.com`, or a sole trader's phone number). If you are in the EU/UK, or contacting people there, the **GDPR**, **UK GDPR** and **ePrivacy/PECR** rules apply; other places have their own laws (CAN-SPAM, POPIA, CASL...). You are responsible for having a lawful basis (usually legitimate interest for B2B outreach), telling people where you got their data, honouring opt-outs, and not storing data longer than you need. Turn on **Only emails on the website's own domain** and filter role addresses (`info@`, `sales@`) if you want to stay close to company contacts. If in doubt, ask a lawyer. Apify's guide: [Is web scraping legal?](https://blog.apify.com/is-web-scraping-legal/)

### Use it from AI agents, Zapier, Make, n8n or the API

- **AI agents (MCP):** works with the [Apify MCP server](https://mcp.apify.com), so Claude, Cursor, ChatGPT and other MCP clients can run it. Ask: *"Find contact emails for these 20 websites."*
- **No-code:** use the Apify app in **Zapier**, **Make** or **n8n** to enrich new leads in your CRM or a Google Sheet.
- **API:** `POST https://api.apify.com/v2/acts/goldish_fireplace~website-contact-finder/run-sync-get-dataset-items` with `{"domains": ["acme.com"]}` and get the rows back in one call.

### Limitations

- **Only what the website publishes.** It does not guess email patterns, look up people in databases or find personal contact details that are not on the site.
- **No JavaScript rendering.** Details loaded only by JavaScript, shown as images, or hidden behind a contact form are not found.
- **A few pages per website.** By default it checks up to 5 pages per website (you can raise this), chosen to be the most likely to hold contact details.
- **The MX check confirms the domain receives mail, not the mailbox.** Use Email Checker for more checks before you send.
- **Starts from websites, not from a business name or a search.** You give it the websites.

### FAQ

**How do I find the email address of a company website?** Paste the website (or many websites, one per line) into **Websites** and click **Start**. Each row has a `primaryEmail`, all other emails found, and the page each one came from.

**Can I upload a list of domains from a spreadsheet?** Yes. Paste the column of websites into **Websites**, one per line. Bare domains, full URLs and even email addresses work.

**Does it render JavaScript?** No. It reads the HTML the server sends, which is fast and cheap. Most business sites put contact details in plain HTML (and in the footer). Sites that load contact details only with JavaScript, or hide them behind a contact form, return fewer results.

**Why are some websites empty?** Some sites only offer a contact form, or show contact details as an image. The row is still returned (status `ok`, no emails) so nothing disappears silently.

**Does it follow links to other websites?** No. It stays on the website's own domain (subdomains such as `support.acme.com` count, at lower priority).

**Does it respect robots.txt?** Optional. It's off by default because some sites disallow all crawlers, which would return empty rows for a handful of public pages. Turn on **Respect robots.txt** if you need it.

**Does it find people's names or verify mailboxes?** No. It finds what the website publishes. To check whether addresses can receive mail, run **Email Checker** on the results.

### Feedback

Found a website where it missed something? Open an issue on the Issues tab with the URL and we'll improve the extractor.

### Related tools

- ✉️ **[Email Checker](https://apify.com/goldish_fireplace/email-checker)**: bulk-validate the emails you found (syntax, MX, disposable, role, typos) before sending.
- 🔗 **[Broken Link Checker](https://apify.com/goldish_fireplace/broken-link-checker)** and 🔎 **[SEO Audit Crawler](https://apify.com/goldish_fireplace/seo-audit-crawler)**: audit the same websites for broken links and on-page SEO.

# Actor input Schema

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

Domains or URLs to find contacts for, one per line (e.g. apify.com or https://www.example.com/shop). Duplicates and www/non-www variants are merged automatically. You can also paste a comma-separated list.

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

Homepage plus the most contact-like pages (contact, about, team, imprint). 5 finds nearly everything; raise it for big sites. The price is per website, not per page.

## `includePhones` (type: `boolean`):

Extract and validate phone numbers (tel: links and numbers written on the page), returned in international E.164 format.

## `includeSocials` (type: `boolean`):

LinkedIn, X/Twitter, Facebook, Instagram, YouTube, TikTok, GitHub, Pinterest, Threads, WhatsApp, Telegram and Discord.

## `verifyEmailDomains` (type: `boolean`):

Drop emails whose domain cannot receive mail (no MX/A record). Removes typos and scraped garbage. Uses DNS only: no emails are sent.

## `onlyOwnDomainEmails` (type: `boolean`):

Keep only emails like name@company.com for company.com. Turn on to drop third-party addresses (agencies, partners, free mail).

## `maxSocialsPerPlatform` (type: `integer`):

The company's own account is ranked first; extra profiles (e.g. testimonial authors) are cut.

## `defaultCountry` (type: `string`):

Two-letter code (US, GB, DE, ZA...) used to read local numbers without a +country prefix. Leave empty to guess from the domain ending (.de, .co.uk, .co.za...).

## `skipFailedDomains` (type: `boolean`):

By default every input gets a row; failed websites show the reason and are never charged.

## `respectRobotsTxt` (type: `boolean`):

Skip pages disallowed by the website's robots.txt. Some sites disallow everything, which then returns empty rows.

## `maxConcurrency` (type: `integer`):

Requests in flight across all websites.

## `requestTimeoutSecs` (type: `integer`):

Give up on a page after this long.

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

Not needed for most websites. Use Apify Proxy if many sites block you.

## Actor input object example

```json
{
  "domains": [
    "apify.com",
    "plausible.io",
    "truth.coffee"
  ],
  "maxPagesPerDomain": 5,
  "includePhones": true,
  "includeSocials": true,
  "verifyEmailDomains": true,
  "onlyOwnDomainEmails": false,
  "maxSocialsPerPlatform": 3,
  "skipFailedDomains": false,
  "respectRobotsTxt": false,
  "maxConcurrency": 20,
  "requestTimeoutSecs": 20,
  "proxyConfiguration": {
    "useApifyProxy": false
  }
}
```

# Actor output Schema

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

No description

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

No description

# 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": [
        "apify.com",
        "plausible.io",
        "truth.coffee"
    ]
};

// Run the Actor and wait for it to finish
const run = await client.actor("goldish_fireplace/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 = { "domains": [
        "apify.com",
        "plausible.io",
        "truth.coffee",
    ] }

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

```

## MCP server setup

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