# Website Contact Scraper — Emails, Phones & 5 Socials (`themineworks/website-contact-finder`) Actor

Crawl any list of domains and extract business emails, phone numbers and social profile links (LinkedIn, X, Facebook, Instagram, YouTube) from homepages, contact & about pages. No API key. Use as an MCP server in Claude, ChatGPT & AI agents.

- **URL**: https://apify.com/themineworks/website-contact-finder.md
- **Developed by:** [The Mine Works](https://apify.com/themineworks) (community)
- **Categories:** Lead generation, Business, MCP servers
- **Stats:** 6 total users, 3 monthly users, 100.0% runs succeeded, 0 bookmarks
- **User rating**: No ratings yet

## Pricing

from $0.60 / 1,000 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/platform/actors/running/actors-in-store#pay-per-event

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

## 📇 Website Contact Scraper: Email, Phone & Socials

### Overview

Website Contact Scraper takes any list of domains and extracts business emails, phone numbers, and social profile links (LinkedIn, X, Facebook, Instagram, YouTube) from the pages that actually publish them: homepage, contact page, about page, team page, and the footer. Feed it `stripe.com` and `notion.so` and get back clean JSON with every publicly listed contact detail deduplicated and normalised.

No API key, no signup, no per-seat licence. It's the fastest way to build a contactable list from a set of target domains without paying for a data subscription.

Reliability posture: a domain that fails to crawl or returns no contact info is never charged. You only pay for a domain that actually returned at least one email, phone, or social profile.

✅ No login required | ✅ No API key | ✅ Pay per domain crawled | ✅ MCP-ready for AI agents

### Features

Domain to contacts. Homepage plus standard contact pages tried automatically.
Multi-channel extraction. Emails, phones, and socials pulled in a single pass.
Deduplication. Each domain returns one record with unique emails, phones, and socials.
Configurable depth. Cap pages per site to control cost and speed.
Residential proxy. Handles sites with light bot protection out of the box.

### How it works

For each domain you supply, the actor first tries the homepage and the standard contact surfaces (`/contact`, `/about`, `/contact-us`, `/team`) up to the page budget you set. It then follows relevant footer links to catch contact info that lives on nested pages. Every fetched page is parsed for email patterns (`mailto:` links plus regex-matched addresses), phone numbers (formatted and international), and social profile URLs on LinkedIn, X, Facebook, Instagram, and YouTube.

Results are merged and deduplicated per domain so you get one clean record per site: an array of emails, an array of phones, and a socials object keyed by platform. Requests run through Apify's residential proxy so most sites with light bot protection just work.

### 🧾 Input configuration

```json
{
  "domains": ["stripe.com", "notion.so", "https://linear.app/about"],
  "maxPagesPerSite": 5,
  "proxyConfiguration": {
    "useApifyProxy": true,
    "apifyProxyGroups": ["RESIDENTIAL"]
  }
}
```

### 📤 Output format

```json
{
  "domain": "basecamp.com",
  "emails": ["jason@basecamp.com"],
  "phones": [],
  "socials": {},
  "pagesScanned": 4,
  "scrapedAt": "2026-07-15T04:22:21.685Z"
}
```

This is a real record from a live crawl of basecamp.com. `phones` and `socials` come back empty here because neither was found on the pages crawled within the page budget, which is common: not every site publishes a phone number, and social links often live on pages outside the default crawl depth. When present, `phones` and `socials` are populated the same way as shown in the input example above.

Every domain record contains these fields:

| Field | Description |
| --- | --- |
| 🌐 `domain` | The website domain that was crawled (e.g. stripe.com) |
| 📧 `emails` | Deduplicated list of email addresses found across the crawled pages |
| 📞 `phones` | Deduplicated list of phone numbers found across the crawled pages |
| 🔗 `socials` | Social profile URLs keyed by platform (linkedin, twitter, facebook, instagram, youtube) |
| 📄 `pagesScanned` | Number of pages successfully fetched for this domain |
| 🕒 `scrapedAt` | ISO timestamp when this domain was processed |

### 💼 Common use cases

**Cold outbound & prospecting**
Turn a target-account list into a contactable email and phone list in minutes.
Enrich domains pulled from Google Maps, Trustpilot, or Zillow with real contact details.

**Partnership & BD outreach**
Find the right press, partnerships, or BD email on hundreds of sites at once.
Build a channel-partner shortlist from a directory scrape.

**Recruiter sourcing**
Get the careers or people ops email off company sites for direct outreach.
Enrich a company list with public social handles for research.

**CRM enrichment**
Backfill missing contact info on domains you already own without a data subscription.
Refresh contact records on a schedule without paying per lookup.

### 🚀 Getting started

1. Open the actor and paste the domains you want to enrich. Bare domains (`stripe.com`) or full URLs both work.
2. Set max pages per site (default 5) to control depth and cost.
3. Leave the residential proxy on unless you have a reason to change it.
4. Click Start. Records stream to the dataset as each domain finishes.
5. Download as JSON, CSV, or Excel, or pull the dataset via API or MCP.

### FAQ

**How does it find the right pages?**
It hits the homepage first, then the standard contact surfaces (`/contact`, `/about`, `/contact-us`, `/team`), then follows footer links up to your page budget. This catches the pages where contact info actually lives without burning budget crawling the whole site.

**Does it verify the emails?**
No. This actor extracts every email publicly listed on the site. Pair it with the Email Verifier & Validator actor to MX and SMTP verify before you send.

**How much does it cost?**
Pay per domain crawled, priced pay as you go. No subscription, no seat licence, no monthly minimum.

**Can I use it in an AI agent?**
Yes. It's exposed as an MCP tool. See below.

### Use in Claude, ChatGPT & any MCP agent

```
https://mcp.apify.com/?tools=themineworks/website-contact-finder
```

Or call it programmatically with the Apify client:

```js
import { ApifyClient } from 'apify-client';

const client = new ApifyClient({ token: 'YOUR_APIFY_TOKEN' });

const run = await client.actor('themineworks/website-contact-finder').call({
  domains: ['stripe.com', 'notion.so'],
  maxPagesPerSite: 5,
});

const { items } = await client.dataset(run.defaultDatasetId).listItems();
console.log(items);
```

### 🛠️ Complete your outbound pipeline

Extracted the contacts. Now find the people behind them and verify:

- **[B2B Leads Finder](https://apify.com/themineworks/b2b-leads-finder)**: turn any domain list into named decision-maker contacts with emails.
- **[Email Verifier & Validator](https://apify.com/themineworks/email-verifier-validator)**: MX and SMTP verify every email before you send.
- **[Google Maps Leads Scraper](https://apify.com/themineworks/maps-leads)**: pull businesses and domains from Google Maps by search query.

Typical flow: maps-leads finds the businesses, website-contact-finder pulls the site contacts, email-verifier-validator confirms deliverability.

Questions or need a custom field set? Reach out through the Apify profile.

# Actor input Schema

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

List of websites to extract contact info from. Accepts bare domains ('stripe.com'), full URLs ('https://notion.so/about') or names with a TLD. Each domain is crawled for emails, phone numbers and social links.

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

Maximum number of pages to fetch per domain. The homepage plus common contact pages (/contact, /about, /contact-us, /team) are tried first, then footer links. Keep low for speed.

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

Optional. Apify Proxy used to fetch pages. RESIDENTIAL is the default and works best against sites with light bot protection. Leave default unless you have a reason to change it.

## Actor input object example

```json
{
  "domains": [
    "stripe.com",
    "notion.so"
  ],
  "maxPagesPerSite": 5,
  "proxyConfiguration": {
    "useApifyProxy": true,
    "apifyProxyGroups": [
      "RESIDENTIAL"
    ]
  }
}
```

# Actor output Schema

## `results` (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": [
        "stripe.com",
        "notion.so"
    ],
    "maxPagesPerSite": 5,
    "proxyConfiguration": {
        "useApifyProxy": true,
        "apifyProxyGroups": [
            "RESIDENTIAL"
        ]
    }
};

// Run the Actor and wait for it to finish
const run = await client.actor("themineworks/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": [
        "stripe.com",
        "notion.so",
    ],
    "maxPagesPerSite": 5,
    "proxyConfiguration": {
        "useApifyProxy": True,
        "apifyProxyGroups": ["RESIDENTIAL"],
    },
}

# Run the Actor and wait for it to finish
run = client.actor("themineworks/website-contact-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 '{
  "domains": [
    "stripe.com",
    "notion.so"
  ],
  "maxPagesPerSite": 5,
  "proxyConfiguration": {
    "useApifyProxy": true,
    "apifyProxyGroups": [
      "RESIDENTIAL"
    ]
  }
}' |
apify call themineworks/website-contact-finder --silent --output-dataset

```

## MCP server setup

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

```

## OpenAPI specification

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