# 🌟 Contact Details Scraper Pro (`databuddy/contact-details-scraper-pro`) Actor

Email extractor and lead scraper to extract and download emails, phone numbers, Facebook, Twitter, LinkedIn, Instagram, Threads, Snapchat, and Telegram profiles from any website. Extract contact information at scale from lists of URLs and download the data as Excel, CSV, JSON, HTML, and XML.

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

## Pricing

from $0.001 / scraped page

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

## Contact Details Scraper Pro: Emails, Phones & 18 Social Networks, Verified

Crawl any list of websites and get **one clean row per website** with:

- **emails**, each **verified** (MX records, role vs personal, free-mail, disposable) and **confidence-scored** with proof of where it was found;
- **phone numbers**, split into confirmed and uncertain;
- **18 social and messaging networks**;
- the **people** published on the site, **company name and address**, **contact page and forms**, the **email provider** and the **technology stack**.

Link-in-bio pages (Linktree, Beacons, lnk.bio…) are followed automatically.

**From $0.80 per 1,000 loaded pages. Verification, merging, tech detection and people are included. Pages that fail to load are never charged.**

### What you get per website

**Same fields as the original Contact Details Scraper:** `originalStartUrl`, `domain`, `scrapedUrls`, `emails`, `phones`, `phonesUncertain`, `linkedIns`, `twitters`, `instagrams`, `facebooks`, `youtubes`, `tiktoks`, `pinterests`, `discords`, `snapchats`, `threads`, `telegrams`, `reddits`, `whatsapps`.

**Plus:**

- **Emails:**
  - `bestEmail`, the most reliable address on the company's own domain;
  - `personalEmails` and `roleEmails`;
  - `emailDetails`, with type, domainMatch, freeProvider, disposable, **mxValid**, a 1–99 **confidence** score, the pages it was found on, and evidence such as *"mailto link on example.com/contact"*.
- **Phones:** `phoneDetails`, with the E.164 format where possible and the evidence for each number.
- **More networks:** `githubs`, `mediums`, `twitches`, `calendlys` and `linkInBioPages`.
- **People:** `people`, with name, job title, email, LinkedIn and phone, from the site's structured data (team pages, founders, authors).
- **Company:** `companyName`, `description`, `address`, `language`.
- **Contact routes:** `contactPageUrl` and `contactFormUrls`.
- **Email setup:** `emailProvider` (Google Workspace, Microsoft 365…), `hasMxRecords`, `hasSpf`, `hasDmarc`.
- **Technology:** `techStack`, for example Shopify, WordPress, HubSpot or Klaviyo.
- **Flags:** `parkedDomain` (domains for sale) and `jsRendered` (JavaScript-only sites), each with a `note`.
- **Origin:** `discoveredVia`, for sites found through a link-in-bio page.

### How it finds more

- **Smart crawl order:** contact, team, about and imprint pages are visited first, so 5–10 pages per site usually find everything. Common contact pages (`/contact`, `/about`, `/team`…) are also tried when they aren't linked, which covers menus built by JavaScript.
- **Hidden emails:** decodes Cloudflare-protected addresses, written-out ones (`name [at] company [dot] com`), `mailto:` links and structured data. Placeholders (example.com, sentry, wixpress…) and no-reply addresses are removed.
- **Phones without the noise:** numbers from `tel:` links, structured data, international formats or "Phone:/Call/Tel" cues are **confirmed**. Other number-like text goes to `phonesUncertain`. Dates, year ranges, order numbers and score lists are rejected.
- **Social links that are real profiles:** share buttons, intent links, post and video URLs are ignored. URLs are normalised (twitter.com becomes x.com, regional LinkedIn hosts become www.linkedin.com, WhatsApp "send" links become wa.me).
- **Link-in-bio pages:** their social icons are read from the page's embedded data and every linked site is crawled.
- **Redirects:** sites that redirect, and duplicates in your list, are crawled once.

### How it is better than the original

| | Contact Details Scraper | Pro |
|---|---|---|
| Price per page | $2.00 → $1.05 / 1,000 | **$1.50 → $0.80 / 1,000** (25% cheaper on every plan) |
| One row per website | Separate merge actor | ✅ Built in (per-page mode also available) |
| Email verification | Paid add-on, enrichment leads only | ✅ **Free** MX check for every email, plus role/personal, free-mail and disposable flags |
| Email confidence and evidence | — | ✅ |
| Confirmed vs uncertain phones | ✅ | ✅ plus E.164 and evidence |
| Social networks | 13 | **18** |
| People from team pages | Paid enrichment | ✅ From the site's structured data |
| Company name, address, contact page, contact forms | — | ✅ |
| Email provider, SPF, DMARC, technology stack | — | ✅ |
| Parked-domain and JavaScript-site warnings | — | ✅ |
| Failed sites | Silent | ✅ Free row with the reason and how to fix it |

### Pricing (pay per event)

| Event | When | Free / Starter | Scale | Business |
|---|---|---|---|---|
| `page-scraped` | One web page loaded successfully | $1.50 / 1,000 | $1.10 / 1,000 | $0.80 / 1,000 |
| `residential-page` | Extra, only when you choose the RESIDENTIAL proxy (it costs ~10× more) | $2.00 / 1,000 | $1.50 / 1,000 | $1.05 / 1,000 |

Email verification (MX), merging, people, technology detection and company info are **included at no extra cost**. The original charges $4.00 per 1,000 for email verification alone.

Rows are free, and so are failed, blocked and non-HTML pages. The run stops cleanly at your **Maximum cost per run**, and the residential extra is counted in that limit.

### Example input

```json
{
  "startUrls": [{ "url": "https://apify.com" }, { "url": "growwstacks.com" }, { "url": "https://linktr.ee/somebrand" }],
  "maxRequestsPerStartUrl": 10,
  "maxDepth": 2
}
```

### Example output (shortened, real run)

```json
{
  "originalStartUrl": "https://apify.com",
  "domain": "apify.com",
  "scrapedUrls": ["https://apify.com/", "https://apify.com/contact", "https://apify.com/contact-sales", "https://apify.com/about"],
  "emails": ["hello@apify.com"],
  "bestEmail": "hello@apify.com",
  "emailDetails": [{ "email": "hello@apify.com", "type": "role", "domainMatch": true, "mxValid": true, "confidence": 95, "evidence": ["mailto link on apify.com/contact"] }],
  "twitters": ["https://x.com/apify"],
  "youtubes": ["https://www.youtube.com/apify"],
  "tiktoks": ["https://www.tiktok.com/@apifytech", "https://www.tiktok.com/@apifyoffice"],
  "githubs": ["https://github.com/apify"],
  "companyName": "Apify",
  "contactPageUrl": "https://apify.com/contact",
  "emailProvider": "Google Workspace",
  "techStack": ["Next.js", "Bootstrap", "Google Tag Manager", "HubSpot", "Intercom", "Amazon Web Services", "Amazon CloudFront"]
}
```

Sites that can't be read come back as free rows with `status`, `error` and `fixHint`. The possible statuses are `unreachable`, `blocked`, `http_error`, `not_html`, `invalid_input` and `redirects_to_duplicate`.

### Run summary

Each run saves a `RUN_SUMMARY` in the key-value store. It contains:

- sites crawled, and how many had contacts;
- pages loaded, failed and charged;
- fill rates for emails, phones and each main network;
- how many link-in-bio pages were followed;
- skip reasons.

### Tips

- **5–10 pages per website** is the sweet spot. The contact pages come first.
- **Sites behind bot protection** (Cloudflare challenges) need the RESIDENTIAL proxy group. It adds the `residential-page` extra, so use it only for the sites that need it.
- **JavaScript-only sites** (`jsRendered: true`) show little without a browser, so some contacts may be missing.
- **Lead lists:** turn on "Only emails on the website's own domain" and "Only websites with contacts".

### Legal

Contact details can be personal data under the GDPR and similar laws. Collect them only with a legitimate purpose and follow the rules for outreach in your country.

# Actor input Schema

## `startUrls` (type: `array`):

Website URLs or plain domains (example.com). Also link-in-bio pages (linktr.ee/…, beacons.ai/…) — every site they link to is crawled too.

## `maxRequestsPerStartUrl` (type: `integer`):

Pages to load per website. Contact, team, about and imprint pages are visited first, so 5–10 is usually enough.

## `maxDepth` (type: `integer`):

How many clicks away from the start page to go. 0 = start page only.

## `maxRequests` (type: `integer`):

Stop after this many loaded pages across all websites. 0 = no limit.

## `sameDomain` (type: `boolean`):

Follow only links of the same website (subdomains included). Link-in-bio pages are still followed.

## `mergeContacts` (type: `boolean`):

All contacts of a website in one row (no separate merge actor needed). Turn off for one row per page, like the original.

## `followLinkInBio` (type: `boolean`):

When a site (or your input) is a Linktree / Beacons / lnk.bio page, crawl the sites it links to. Each becomes its own row with "discoveredVia".

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

Free: checks that each email domain can receive mail, marks role vs personal, free-mail and disposable addresses, and adds the website's email provider, SPF and DMARC.

## `detectTechnologies` (type: `boolean`):

Free: CMS, e-commerce, analytics, chat and marketing tools found in the website's code (e.g. Shopify, WordPress, HubSpot).

## `includeUncertainPhones` (type: `boolean`):

Number-like text without a "phone" cue goes to "phonesUncertain" (as in the original). Confirmed numbers are always in "phones".

## `onlySameDomainEmails` (type: `boolean`):

Drop emails of other domains (agencies, vendors, platforms).

## `ignoreEmailDomains` (type: `array`):

Email domains to drop, e.g. wixpress.com, sentry.io (common placeholders are already removed).

## `onlyResultsWithContacts` (type: `boolean`):

Leave out rows without any email, phone or social profile. Pages loaded for them are still charged.

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

Apify's datacenter proxy (default) works for most websites. Use RESIDENTIAL only for sites behind bot protection: each page then also counts as a "residential-page" event, because residential traffic costs ~10× more.

## Actor input object example

```json
{
  "startUrls": [
    {
      "url": "https://apify.com"
    }
  ],
  "maxRequestsPerStartUrl": 20,
  "maxDepth": 2,
  "maxRequests": 0,
  "sameDomain": true,
  "mergeContacts": true,
  "followLinkInBio": true,
  "verifyEmails": true,
  "detectTechnologies": true,
  "includeUncertainPhones": true,
  "onlySameDomainEmails": false,
  "ignoreEmailDomains": [],
  "onlyResultsWithContacts": false,
  "proxyConfiguration": {
    "useApifyProxy": true
  }
}
```

# Actor output Schema

## `contacts` (type: `string`):

No description

## `leads` (type: `string`):

No description

## `runSummary` (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 = {
    "startUrls": [
        {
            "url": "https://apify.com"
        }
    ],
    "proxyConfiguration": {
        "useApifyProxy": true
    }
};

// Run the Actor and wait for it to finish
const run = await client.actor("databuddy/contact-details-scraper-pro").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 = {
    "startUrls": [{ "url": "https://apify.com" }],
    "proxyConfiguration": { "useApifyProxy": True },
}

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

```

## MCP server setup

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

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/GoabnjkI7qpVCidW1/builds/PenusLqLrXoLV6gpB/openapi.json
