# Contact Details Scraper (`data_wiki/contact-details-scraper`) Actor

Get emails, phone numbers, social links, company name and address from any list of websites. Every email gets a quality check and every site a confidence score. No login needed. Great for lead generation, sales outreach and building clean contact lists fast.

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

## Pricing

from $0.70 / 1,000 results

This Actor is paid per event and usage. You are charged both the fixed price for specific events and for Apify platform usage.
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

### Contact Details Scraper — emails, phones, socials

Contact Details Scraper reads any list of public websites and returns one clean result per site: **emails**, **phone numbers** in international format, **social profile links**, plus the company name, postal address and tech stack when the site publishes them. Every email gets a quality check (role, free-webmail, disposable, mail-server result) and every site gets a 0–100 contact confidence score. No login and no cookies are needed. Every response is structured JSON — ready to pass directly to an LLM, index into a vector store, or feed a lead-generation pipeline. Paste your list of domains, press **Start**, and get a contact sheet you can export in minutes.

### Why choose Contact Details Scraper?

- **Honest results.** Every website has a `status` (`ok`, `no_contacts`, `http_404`, `fetch_failed: …`, `invalid_url`) so you always know why a row is empty instead of getting a silent blank.
- **Own-company emails first.** The `emails` list holds the website's own addresses; other companies' addresses (a chat widget's legal contact, a template's sample address) go to `emailsExternal` so your list stays clean.
- **More than contacts.** Company details, address, tech stack and site info come back in the same pass.
- **Free email quality check.** Role / free / disposable flags and a mail-server check on every email, with no paid verifier.
- **Live output.** Rows appear in the Output tab while the run is going, split into separate tables for emails, phones, social profiles, company and tech stack.
- **Few, clear inputs.** Websites, pages per site, email check, phone country, and an optional proxy.

### Key features

- Bulk input: one website or thousands, bare domains or full addresses, duplicates removed.
- Contact and about pages are read first, so the useful pages are covered even with a small page limit.
- Emails from visible text, mail links, obfuscated forms such as `name (at) domain (dot) com`, and hidden email addresses.
- Phone numbers validated and converted to international format using your chosen country for local numbers; doubtful numbers go to `phonesUncertain`.
- 16 social networks: LinkedIn, X / Twitter, Instagram, Facebook, YouTube, TikTok, Pinterest, Discord, Snapchat, Threads, Telegram, Reddit, WhatsApp, GitHub, Medium, Vimeo.
- Retries and switches to a stronger proxy automatically when a website refuses the request.

### Input

```json
{
  "urls": ["https://apify.com", "basecamp.com"],
  "maxWebsites": 100,
  "maxPagesPerSite": 10,
  "verifyEmails": true,
  "country": "US",
  "onlyWithContacts": false,
  "proxyConfiguration": { "useApifyProxy": false }
}
```

| Field | What it does |
|---|---|
| `urls` (required) | Websites or bare domains, one per line. Duplicates are removed. |
| `maxWebsites` | Stop after this many websites. Free plan: up to 10 results per run. |
| `maxPagesPerSite` | Pages read per website (default 10). `1` = only the exact address, `0` = no limit (capped at 60). |
| `verifyEmails` | Checks each email's domain and flags role, free-webmail and disposable addresses. |
| `country` | Country (dropdown) used to read local phone numbers (default `US`). |
| `onlyWithContacts` | Return only websites with at least one email or phone. |
| `proxyConfiguration` | Optional. Default is no proxy; the Actor upgrades automatically if a website refuses. |

If you already use another contact-info scraper, `startUrls` and `maxRequestsPerStartUrl` are accepted as names for `urls` and `maxPagesPerSite`.

### Output

One result per website. This is a real result for `https://apify.com` (shortened):

```json
{
  "originalStartUrl": "https://apify.com",
  "domain": "apify.com",
  "status": "ok",
  "pagesScraped": 8,
  "emails": ["hello@apify.com", "support@apify.com", "james.hill@apify.com"],
  "emailsExternal": ["info@baeckerei-mustermann.de", "legal@intercom.io"],
  "phones": ["+17183565168"],
  "phonesUncertain": ["+49301234567"],
  "linkedIns": ["https://linkedin.com/company/apify"],
  "twitters": ["https://x.com/apify"],
  "company": { "name": "Apify", "legalName": "Apify Technologies s.r.o.", "foundingDate": "2015" },
  "address": { "city": "Prague", "postalCode": "11000", "country": "CZ" },
  "techStack": [{ "name": "Next.js", "category": "Framework" }],
  "contactConfidence": 100
}
```

| Field | Meaning |
|---|---|
| `status` | Why the row looks the way it does. |
| `emails` / `emailsExternal` | The website's own addresses / other companies' addresses. |
| `emailsDetailed` | Each email with type, free/disposable flags, `deliverable` (valid, invalid, unknown), mail server and pages it was found on. |
| `phones` / `phonesDetailed` / `phonesUncertain` | Valid numbers, their national format and country, and doubtful numbers. |
| `linkedIns`, `twitters`, `instagrams`, `facebooks`, … | Social profile links per network. |
| `company`, `address`, `siteMeta` | Details the site publishes about itself. |
| `techStack` | Detected technologies and their category. |
| `contactConfidence` | 0–100 score for how complete the contact data is. |

The Output tab also has separate tables: **Emails**, **Phones**, **Social profiles**, **Company** and **Tech stack**, each filled live. Export any of them as JSON, CSV, Excel or HTML.

### 🚀 How to use (Apify Console)

1. Log in at [console.apify.com](https://console.apify.com) and open **Actors**.
2. Find **Contact Details Scraper** and open it.
3. Paste your websites into **Websites to scan**.
4. Adjust pages per website, email check and phone country if needed.
5. Click **Start**.
6. Watch the live log; each finished website shows its counts.
7. Open the **Output** tab and export to JSON, CSV or Excel.

### 🤖 Use via API / MCP

```bash
curl -X POST "https://api.apify.com/v2/actors/BCCaskbnZu7s26tjt/runs" \
  -H "Authorization: Bearer $APIFY_TOKEN" \
  -H "Content-Type: application/json" \
  -d '{"urls":["https://apify.com","basecamp.com"],"maxPagesPerSite":10}'
```

For AI agents, connect the Apify MCP server with `claude mcp add --transport http apify "https://mcp.apify.com"`; the agent can find this Actor through the server's search, details and call tools.

### Best use cases

- Build a lead list of company emails and phones from a list of domains.
- Enrich a CRM with social profiles, company names and addresses.
- Check which prospects publish a real contact address before outreach.
- Map the tech stack of a list of competitors or prospects.

### Pricing

Billing is pay-per-event. One `main_result` event is charged for each website that was read successfully (status `ok` or `no_contacts`). Websites that could not be reached, invalid addresses and websites removed by *Only websites with contacts* are not charged. Free plan runs return up to 10 results.

### Frequently asked questions

**Why is a website `no_contacts`?** The pages that were read did not publish a valid email or phone. Raise `maxPagesPerSite` to read more pages.

**Why is an email in `emailsExternal`?** It belongs to another company's domain (for example a chat tool's legal address). It is kept in `emailsDetailed` with `onDomain: false`.

**What does `deliverable: unknown` mean?** The email's domain exists but publishes no mail server, so the address cannot be confirmed.

**Are phone numbers guaranteed?** Only numbers that pass international phone validation go to `phones`. Doubtful ones are listed separately in `phonesUncertain`.

**Does it work on every website?** It reads the public page content. If a website changes its layout or blocks automated visitors, some fields may come back empty and the `status` tells you why.

### Support and feedback

Found a website that returns wrong or missing data? Open an issue from the Actor page in Apify Console and include the website and the run link.

### Legal

Data is collected only from publicly available pages. You are responsible for following GDPR, CCPA, anti-spam laws and the terms of the websites you scan.

# Actor input Schema

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

Website addresses or bare domains, one per line (for example apify.com or https://basecamp.com/about). Duplicates are removed and every website returns one result.

## `maxWebsites` (type: `integer`):

Stop after this many websites. Free plan: up to 10 results per run; paid plans have no run limit.

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

How many pages to read on each website. Contact, about and team pages are visited first. 1 = only the exact address you gave, 0 = no limit (capped at 60 pages for safety).

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

Check whether each email's domain can receive mail and flag role, free-webmail and disposable addresses. Adds a deliverability result to every email.

## `country` (type: `string`):

Country used to turn local phone numbers (no country code) into international format, for example US numbers become +1….

## `onlyWithContacts` (type: `boolean`):

Return only websites where at least one email or phone number was found. Off = every website is returned with its status.

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

By default no proxy is used. If a website refuses the request, the Actor switches to a stronger proxy automatically and keeps using it.

## Actor input object example

```json
{
  "urls": [
    "https://apify.com",
    "basecamp.com"
  ],
  "maxWebsites": 10,
  "maxPagesPerSite": 10,
  "verifyEmails": true,
  "country": "US",
  "onlyWithContacts": false,
  "proxyConfiguration": {
    "useApifyProxy": false
  }
}
```

# Actor output Schema

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

One row per website.

## `emails` (type: `string`):

One row per email with quality flags.

## `phones` (type: `string`):

One row per phone number.

## `socialProfiles` (type: `string`):

One row per social profile link.

## `company` (type: `string`):

Company, address and site info.

## `techStack` (type: `string`):

Technologies detected per website.

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

Counts and timing of the run.

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

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

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

```

## MCP server setup

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