# Company Website Contact Scraper – Emails, Phones, Socials (`ryumoon-data/company-contact-details-scraper`) Actor

Extract business emails, phones and social profiles from company websites. One row per site. Pay only when contacts are found ($1.50 per 1,000). No login.

- **URL**: https://apify.com/ryumoon-data/company-contact-details-scraper.md
- **Developed by:** [Ryu Moon](https://apify.com/ryumoon-data) (community)
- **Security:** Limited permissions
- **Stats:** 2 total users, 1 monthly users, 100.0% runs succeeded, 0 bookmarks
- **User rating**: No ratings yet

## Pricing

from $1.50 / 1,000 websites

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 Contact Details Scraper: Emails, Phones & Social Links

**Turn a list of company websites into a clean lead sheet with business emails, phones and social profiles, for $1.50 per 1,000 websites where something is found.**

#### Who it's for

B2B sales and marketing teams, agencies, partnership and PR teams, and anyone enriching a CRM from company domains.

#### What people use it for

- 🛍️ **Shopify and e-commerce brand contacts.** Get the support, press and wholesale emails plus Instagram and TikTok handles for D2C stores.
- 🧾 **CRM enrichment.** Add phone, LinkedIn, address and contact-page URL to a list of company domains.
- 🤝 **Partnership and PR outreach.** Find `press@`, `partners@` and `hello@` style role addresses.
- 🏛️ **Nonprofit and organisation directories.** Collect the public contact points of organisations in bulk.

#### Real sample output

From a real run on `https://www.allbirds.com` with 4 pages per website (shortened; results vary by site):

```json
{
  "website": "https://www.allbirds.com",
  "companyName": "Allbirds",
  "emails": [
    "help@allbirds.com"
  ],
  "phones": [
    "+1 424 363 8064"
  ],
  "facebook": "https://www.facebook.com/weareallbirds",
  "instagram": "https://www.instagram.com/allbirds",
  "tiktok": "https://www.tiktok.com/@weareallbirds",
  "pinterest": "https://pinterest.com/weareallbirds",
  "contactPageUrl": "https://www.allbirds.com/pages/help",
  "pagesScanned": 4
}
```

Personal-looking addresses are skipped by default (`includePersonalContacts: false`).

#### What it costs (real prices)

Prices are pay per event: **$0.0015 per website with at least one contact found** and a **$0.005** start fee per run (1 GB default memory). Websites with nothing found, or that fail to load, cost nothing per website (the run start fee still applies).

| Job | Calculation | USD | GBP\* |
|---|---|---|---|
| 100 websites, all with contacts | 100 × $0.0015 + $0.005 | $0.155 | £0.12 |
| 1,000 websites, 700 with contacts | 700 × $0.0015 + $0.005 | $1.055 | £0.79 |
| 10,000 websites, 7,000 with contacts | 7,000 × $0.0015 + $0.005 | $10.505 | £7.85 |

\*GBP at 1 USD = £0.74711 (ECB rate, 6 Nov 2026). Apify bills in USD.

### Integrations

All recipes below use Apify's own official integrations. You need a free Apify account.

- **Zapier.** Add Apify as the action in a Zap, pick **Run Actor** (or **Run Task** for a saved example), choose `ryumoon-data/company-contact-details-scraper` and paste the input JSON. Then add **Fetch dataset items** to pass the results to Google Sheets, Slack, Notion and so on. Synchronous runs in Zapier time out after 30 seconds, so for big batches use the **Finished Actor run** trigger in a second Zap. [Apify docs: Zapier](https://docs.apify.com/platform/integrations/zapier)
- **Make.** Add the Apify module **Run an Actor** with "Run synchronously" set to Yes, then **Get Dataset Items** using the run's default dataset ID, then e.g. Google Sheets "Bulk Add Rows". For long runs, use the **Watch Actor Runs** trigger instead. [Apify docs: Make](https://docs.apify.com/platform/integrations/make)
- **n8n.** Install the Apify node (`@apify/n8n-nodes-apify` from Community Nodes on self-hosted, or search "Apify" in the nodes panel on n8n Cloud). Add an Apify API key or OAuth2 (Cloud) credential, then use it as an action to run this Actor, or as the **On new Apify Event** trigger to process results when a run finishes. [Apify docs: n8n](https://docs.apify.com/platform/integrations/n8n)
- **MCP (Claude, ChatGPT and other AI agents).** Add Apify's hosted MCP server to your client. To load only this Actor, use `https://mcp.apify.com?tools=ryumoon-data/company-contact-details-scraper`. The first time you connect, your browser opens so you can sign in to Apify. Alternatively, send an `Authorization: Bearer <APIFY_TOKEN>` header:
  ```json
  { "mcpServers": { "apify": { "url": "https://mcp.apify.com?tools=ryumoon-data/company-contact-details-scraper" } } }
  ```
  Your assistant can then run it from a prompt like *"Find the business contact emails and socials for allbirds.com and brooklinen.com"*. [Apify docs: MCP server](https://docs.apify.com/platform/integrations/mcp)

***

**Give it a list of company websites and get back one clean row per company**: business email addresses, phone numbers, LinkedIn, Facebook, Instagram, X/Twitter, YouTube, TikTok, Pinterest, GitHub and more, plus the postal address and contact page URL. The Actor reads the homepage and the pages most likely to hold contact details (Contact, About, Impressum, Team, Support), so it finds more while scanning fewer pages.

**You only pay for websites where something was found**: $1.50 per 1,000 websites with contacts. Websites with nothing on them, or that fail to load, cost nothing per website.

### Use with AI agents (MCP, Claude, ChatGPT, Cursor)

**Purpose:** Get business emails, phone numbers and social profile links (LinkedIn, Facebook, Instagram, X, YouTube, TikTok) from company websites. One deduplicated row per website.

**When to use it**

- The user has a list of company websites and wants their public contact details (lead lists, CRM enrichment, outreach research).

**When not to use it**

- It does not find companies; give it website URLs (e.g. from a search or a directory).
- Business contacts only by default: personal-looking emails are skipped unless `includePersonalContacts` is on. Follow GDPR / local law when you use the data.

**Example input**

```json
{
  "websites": [
    "https://www.python.org",
    "apify.com"
  ],
  "maxPagesPerWebsite": 6
}
```

**Output fields (one dataset item per row):** `website`, `companyName`, `emails`, `phones`, `linkedin`, `facebook`, `instagram`, `twitter`, `youtube`, `tiktok`, `contactPageUrl`, `pagesScanned`, `error`.

**Cost:** $0.005 per run + $0.0015 per website with contacts found ($1.50 per 1,000).

**Connect it to your agent:** add this remote MCP server (Apify's official MCP server, loaded with just this tool):

```json
{"mcpServers": {"company-contact-details-scraper": {"url": "https://mcp.apify.com?tools=ryumoon-data/company-contact-details-scraper"}}}
```

Or call it from any agent with the Apify API: `POST https://api.apify.com/v2/acts/ryumoon-data~company-contact-details-scraper/run-sync-get-dataset-items` with the input above as the JSON body. Agents without an Apify account can pay per run with [agentic payments](https://docs.apify.com/agents/payments) (x402, MPP or Skyfire).

### What can it do?

- 📧 **Emails** from `mailto:` links, page text, schema.org data, Cloudflare-protected addresses and simple `name [at] domain` tricks. Image names and placeholder emails are filtered out.
- 🏷️ **Business vs personal emails**: each email is labelled `role` (info@, sales@, support@…) or `personal` (jane.doe@…). By default only business emails are returned (see Privacy below).
- 📞 **Phone numbers** from `tel:` links, schema.org data and the page text, validated with Google's libphonenumber and formatted internationally (+44 20 7946 0958). Placeholder numbers are dropped.
- 🔗 **Social profiles**: LinkedIn company pages, Facebook, Instagram, X/Twitter, YouTube, TikTok, Pinterest, GitHub, Threads, WhatsApp, Telegram and Discord, without share buttons and tracking links.
- 🏢 **Company name, postal address** (from schema.org) and **contact page URL**.
- 🧮 **One row per website**, deduplicated across all pages. Easy to import into a CRM or Google Sheets.
- ⚡ **Fast and light**: plain HTTP requests, no browser, 10 websites in parallel by default.

### Use cases

- **Lead generation**: enrich a list of company domains (from a directory, trade show list or Google Sheets) with contact details.
- **CRM enrichment**: fill in missing phone numbers and social profiles for accounts you already have.
- **Agencies and freelancers**: find the right business inbox before you pitch.
- **Market research**: see which competitors are on TikTok, YouTube or LinkedIn.
- **Data cleaning**: check that company websites still list the contact details you have on file.

### How much does it cost?

Pay-per-event pricing:

| Event | Price | When it is charged |
|---|---|---|
| Actor start | **$0.005** | Once per run (at the default 1 GB memory) |
| Website | **$0.0015** | Once per website where at least one email, phone or social profile was found |

Examples:

- 1,000 websites, 800 with contacts: **about $1.21**
- 100 websites: **at most $0.155**
- 10,000 websites, 75% with contacts: **about $11.26**

Charging per website, not per page scanned, keeps the price predictable. Set a *maximum cost per run* in Apify Console to cap spend.

### Input

| Field | What it does | Default |
|---|---|---|
| `websites` (required) | Website URLs or bare domains | two examples |
| `maxPagesPerWebsite` | Homepage + likely contact pages to read | `6` |
| `includePersonalContacts` | Also return named-person emails and personal LinkedIn profiles | `false` |
| `onlyEmailsOnSiteDomain` | Drop emails at other domains | `false` |
| `skipWebsitesWithoutContacts` | Leave out empty rows | `false` |
| `defaultCountry` | Country for local phone formats (`GB`, `US`, `DE`…) | from the domain |
| `maxConcurrency`, `requestTimeoutSecs`, `proxyConfiguration` | Advanced | `10`, `20`, none |

```json
{
  "websites": ["zyte.com", "https://www.pret.co.uk", "https://www.lush.com"],
  "maxPagesPerWebsite": 6,
  "onlyEmailsOnSiteDomain": true
}
```

### Output

A real row (shortened):

```json
{
  "input": "https://www.zyte.com",
  "website": "https://www.zyte.com",
  "domain": "zyte.com",
  "companyName": "Zyte",
  "emails": ["marketing@zyte.com", "legal@zyte.com", "jobs@zyte.com"],
  "phones": ["+1 415 854 8183", "+1 415 903 5095"],
  "linkedin": "https://www.linkedin.com/company/zytedata",
  "facebook": "https://www.facebook.com/zytedata",
  "instagram": "https://www.instagram.com/zytedata",
  "twitter": "https://twitter.com/zytedata",
  "youtube": "https://www.youtube.com/@zytedata",
  "github": "https://github.com/scrapy",
  "socials": { "github": ["https://github.com/scrapy", "https://github.com/zytedata"], "discord": ["https://discord.gg/mv3yErfpvq"] },
  "address": { "street": "Cuil Greine House", "city": "Ballincollig Commercial Park", "region": "Ballincollig Co. Cork", "postalCode": null, "country": "Ireland" },
  "contactPageUrl": "https://www.zyte.com/contact-us/",
  "emailDetails": [{ "email": "marketing@zyte.com", "type": "role", "foundVia": "mailto", "foundOn": "https://www.zyte.com/contact-us/" }],
  "phoneDetails": [{ "phone": "+1 415 854 8183", "e164": "+14158548183", "country": "US", "foundVia": "text", "foundOn": "https://www.zyte.com/contact-us/" }],
  "personalContactsHidden": 8,
  "pagesScanned": 6,
  "scrapedAt": "2026-11-02T17:25:15.000Z",
  "error": null
}
```

`emails`, `phones` and the top-level social fields are ready for spreadsheets. `emailDetails` and `phoneDetails` show where each one was found. `personalContactsHidden` tells you how many personal contacts were left out.

Export as CSV, Excel, JSON or JSONL, or connect to Google Sheets, HubSpot, Make, Zapier or n8n through Apify integrations.

### Privacy and responsible use

- The Actor only reads **public pages of company websites** you give it. It does not log in, guess emails or use third-party databases.
- **Personal data is off by default.** Named-person emails and personal LinkedIn profiles are hidden unless you turn on `includePersonalContacts`. Under the GDPR, UK GDPR and similar laws, you need a lawful basis to process them, and many countries restrict unsolicited marketing email. You're responsible for how you use the data.
- Please respect each website's terms of use.

### Tips and limits

- Some sites block automated requests or return different HTML. A blocked homepage is listed with an `error` and isn't charged per website. If only some pages fail, you can get partial results with no error. A website is charged when any email, phone or social profile is found, even if no email is found. The per-run start fee always applies.
- Pages built entirely with JavaScript may hide contacts from plain HTTP requests.
- Raise `maxPagesPerWebsite` for large corporate sites with many regional contact pages.

### FAQ

**Why does a website show no emails?** Many companies use only a contact form. The row then has `contactPageUrl` and usually phone numbers and social profiles. If nothing at all is found, you pay nothing.

**Do you verify emails?** No SMTP checks are done. Emails are taken as published on the site.

**Can I run it on a schedule?** Yes. Use Apify Schedules, for example to re-check a list every month.

# Actor input Schema

## `websites` (type: `array`):

Company website URLs or bare domains, e.g. 'https://acme.com' or 'acme.com'. Duplicates are removed. Paste thousands at once if you like.

## `maxPagesPerWebsite` (type: `integer`):

The homepage plus the most likely contact pages (Contact, About, Impressum, Team, Support…). 4 finds most contacts; raise it for big sites.

## `includePersonalContacts` (type: `boolean`):

By default only business/role emails (info@, sales@, support@…) and company profiles are returned. Turn on to also return named-person emails (jane.doe@…) and personal LinkedIn profiles. Only do this if you have a lawful basis (e.g. GDPR legitimate interest) to process them.

## `onlyEmailsOnSiteDomain` (type: `boolean`):

Drop emails at other domains (e.g. agencies, partners, gmail.com).

## `skipWebsitesWithoutContacts` (type: `boolean`):

By default every website gets a row (empty ones are free). Turn on for a cleaner export.

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

Used to read local phone numbers without a + prefix, e.g. 'GB', 'US', 'DE'. Empty = guess from the domain (.co.uk → GB, .de → DE, otherwise US).

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

How many websites are processed at once.

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

Give up on a page after this many seconds.

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

Usually not needed. Apify datacenter proxy or your own proxy URLs are supported. Apify residential proxy is not supported.

## Actor input object example

```json
{
  "websites": [
    "https://apify.com",
    "https://www.python.org"
  ],
  "maxPagesPerWebsite": 4,
  "includePersonalContacts": false,
  "onlyEmailsOnSiteDomain": false,
  "skipWebsitesWithoutContacts": false,
  "maxConcurrency": 10,
  "requestTimeoutSecs": 20,
  "proxyConfiguration": {
    "useApifyProxy": false
  }
}
```

# Actor output Schema

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

All websites and their contact details in the run's default dataset.

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

Counts of websites checked, with contacts and failed.

# 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 = {
    "websites": [
        "https://apify.com",
        "https://www.python.org"
    ],
    "maxPagesPerWebsite": 4
};

// Run the Actor and wait for it to finish
const run = await client.actor("ryumoon-data/company-contact-details-scraper").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 = {
    "websites": [
        "https://apify.com",
        "https://www.python.org",
    ],
    "maxPagesPerWebsite": 4,
}

# Run the Actor and wait for it to finish
run = client.actor("ryumoon-data/company-contact-details-scraper").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 '{
  "websites": [
    "https://apify.com",
    "https://www.python.org"
  ],
  "maxPagesPerWebsite": 4
}' |
apify call ryumoon-data/company-contact-details-scraper --silent --output-dataset

```

## MCP server setup

```json
{
    "mcpServers": {
        "apify": {
            "type": "http",
            "url": "https://mcp.apify.com/?tools=fetch-actor-details,ryumoon-data/company-contact-details-scraper"
        }
    }
}
```

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/B6KHPxDbsVyWhBAj7/builds/lgYXmECCgSaH1NeYI/openapi.json
