# Website Email & Contact Extractor - Phones, Socials, VAT (`despottt/website-contact-extractor`) Actor

Extract emails, phone numbers, social media profiles, VAT IDs and addresses from a list of company websites. Crawls contact, about and imprint pages, decodes protected emails and validates phones. You pay only for websites where contacts are found.

- **URL**: https://apify.com/despottt/website-contact-extractor.md
- **Developed by:** [Luca Despot](https://apify.com/despottt) (community)
- **Categories:** Lead generation, Marketing, Automation
- **Stats:** 1 total users, 0 monthly users, 0.0% runs succeeded, 0 bookmarks
- **User rating**: No ratings yet

## Pricing

from $4.00 / 1,000 website with contacts

This Actor is paid per event and usage. You are charged both the fixed price for specific events and for Apify platform usage.

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 Email & Contact Extractor: Emails, Phone Numbers, Social Links and VAT IDs

**Paste a list of company websites and get one clean row of contact details per company: emails, phone numbers, social media profiles, VAT IDs, addresses and the contact page URL.**

You **pay only for websites where at least one contact was found.** Unreachable sites and sites with nothing on them are still listed (for free), so your list stays complete. No browser, no proxy and no login.

### What can this contact scraper do?

- ✅ **Smart crawl:** the homepage plus the most relevant subpages in many languages: contact / contatti / kontakt / contacto, about / chi siamo / über uns, impressum / imprint, legal notice, team and support. A few pages per site, not the whole site, so it's fast and cheap.
- ✅ **Emails other tools miss:** `mailto:` links, plain text, schema.org JSON-LD, **Cloudflare-protected emails** (decoded) and obfuscated forms like `info [at] company [dot] com`. Junk such as `logo@2x.png`, Sentry or Wix addresses and placeholders is filtered out, and the company's own domain comes first.
- ✅ **Phone numbers validated with Google's libphonenumber** and returned in E.164 format (`+390212345678`). The country is guessed from the domain and can be overridden. VAT, REA and fiscal numbers are not mistaken for phones.
- ✅ **Social profiles:** LinkedIn, Facebook, Instagram, X/Twitter, YouTube, TikTok, Pinterest, GitHub, Telegram, WhatsApp and Threads.
- ✅ **EU-ready:** VAT IDs (IT, DE, FR, ES, NL, AT, CZ and more, with a checksum check for Italian *Partita IVA*), addresses from structured data, and imprint pages.
- ✅ **Source of every email** (`emailSources`), so you can check where it was found.
- ✅ **Polite by default:** respects robots.txt and opens only a few pages per site.
- ✅ **REST API (Standby):** `GET /?urls=apify.com,python.org`.

### Use cases

- **Lead enrichment:** turn a column of domains into emails, phones and LinkedIn pages.
- **B2B prospect lists** from directories or Google Maps exports you already have.
- **CRM clean-up:** fill in missing contact data.
- **Supplier checks:** VAT ID, imprint and legal address.
- **Local business outreach** for agencies and web designers.

### How to use it

The input is a simple form, no code needed:

1. Paste website addresses into **🌐 Websites**, one per line (`apify.com` or `https://www.python.org` both work). You can add many websites to one run.
2. Optionally raise **Pages to check per website** (default 6) for big corporate sites, or set **Max websites**.
3. Optional, in **⚙️ Advanced options**: a **Country for local phone numbers** dropdown (Automatic by default, useful when your list is from one country but uses `.com` domains), extra page words, include/skip websites with no contacts, robots.txt and parallelism.
4. Click **Start**. You get one row per website in the *Output* tab; download it as CSV or Excel, or use the API.
5. Chain it after a directory or Google Maps scraper: map the website column into `urls`.

### Input example

```json
{ "urls": ["https://apify.com", "python.org", "https://www.eataly.it"], "maxPagesPerSite": 6 }
```

### Output example (one item per website)

```json
{
  "inputUrl": "https://apify.com",
  "url": "https://apify.com",
  "domain": "apify.com",
  "companyName": "Apify",
  "pageTitle": "Apify: Marketplace of ready-to-run tools for AI",
  "emails": [
    "support@apify.com",
    "hello@apify.com"
  ],
  "phones": [],
  "linkedin": "https://linkedin.com/company/apify",
  "facebook": null,
  "instagram": null,
  "twitter": "https://x.com/apify",
  "youtube": null,
  "tiktok": "https://www.tiktok.com/@apifytech",
  "socialProfiles": {
    "linkedin": [
      "https://linkedin.com/company/apify",
      "https://www.linkedin.com/company/apify"
    ],
    "twitter": [
      "https://x.com/apify"
    ],
    "github": [
      "https://github.com/apify"
    ],
    "tiktok": [
      "https://www.tiktok.com/@apifytech",
      "https://www.tiktok.com/@apifyoffice"
    ]
  },
  "vatIds": [
    "CZ04788290"
  ],
  "addresses": [
    "Na Příkopě 959/27, 11000, Prague, CZ"
  ],
  "contactPageUrl": "https://apify.com/contact",
  "emailSources": {
    "support@apify.com": "https://apify.com",
    "hello@apify.com": "https://apify.com/contact"
  },
  "phoneCountryAssumed": "US",
  "pagesCrawled": 5,
  "pagesSkippedByRobotsTxt": 0,
  "contactsFound": true,
  "error": null
}
```

*(Real output from a cloud test run on 27 Oct 2026.)*

### Pricing

Pay per event, with platform usage included. You pay only for:

- **$0.002 per run start** (one start event per GB of memory; the default 512 MB run counts as one).
- **$0.004 per website with contacts found**, which is **$4 per 1,000 websites with contacts**.

Websites where nothing is found, and unreachable websites, are free. There is no per-page fee and no extra proxy fee. Example: 1,000 websites of which 700 have contacts cost about $2.80.

### FAQ

**Does it guess or verify emails?** No. It returns only addresses actually published on the site. It does not generate patterns like `firstname@company.com` and does not send verification emails.

**How many pages does it open per site?** Up to **Max pages per website** (default 6): the homepage plus the most relevant contact, about and imprint pages. 4–8 pages finds most contacts.

**Is it legal?** It reads publicly published business contact details. In the EU/UK, GDPR and ePrivacy rules apply to emails of identifiable people (for example `mario.rossi@…`). Prefer generic company addresses (info@, sales@), have a legitimate interest, honour opt-outs, and don't send unsolicited bulk email where that's illegal. Don't use it on sites whose terms forbid automated access.

### Limitations

- **JavaScript-only websites:** it reads the HTML the server sends, which works for the vast majority of company sites. Sites that show contacts only after JavaScript runs, or only as images, may return fewer results.
- It doesn't find personal emails of employees that the site doesn't publish, and it doesn't search LinkedIn or other external sources.
- Contact forms are detected only as a contact page URL; form submissions are never made.
- Pages blocked by robots.txt are skipped while **Respect robots.txt** is on (the default).

Issues and feature requests: use the *Issues* tab.

# Actor input Schema

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

One website or domain per line, e.g. <code>https://www.example.com</code> or <code>example.it</code>. Duplicates are removed.

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

Home page + the best contact / about / imprint pages. 4-8 is enough for most sites.

## `maxItems` (type: `integer`):

Stop after this many websites. 0 = no limit.

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

Used to read phone numbers written without the +prefix. Automatic = guessed from the domain (.it = Italy, .de = Germany ...), otherwise US.

## `extraPageKeywords` (type: `array`):

Words in a link or URL that point to contact info, e.g. <code>sedi</code>, <code>filiali</code>, <code>press</code>.

## `includeEmptySites` (type: `boolean`):

Keep a row for sites where nothing was found or that were unreachable (these rows are free).

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

Skip pages that the website asks robots not to visit.

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

How many websites are processed at the same time.

## Actor input object example

```json
{
  "urls": [
    "https://apify.com",
    "https://www.python.org"
  ],
  "maxPagesPerSite": 6,
  "maxItems": 0,
  "defaultCountry": "",
  "extraPageKeywords": [],
  "includeEmptySites": true,
  "respectRobotsTxt": true,
  "maxConcurrency": 10
}
```

# Actor output Schema

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

All dataset items produced by 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",
        "https://www.python.org"
    ]
};

// Run the Actor and wait for it to finish
const run = await client.actor("despottt/website-contact-extractor").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",
        "https://www.python.org",
    ] }

# Run the Actor and wait for it to finish
run = client.actor("despottt/website-contact-extractor").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",
    "https://www.python.org"
  ]
}' |
apify call despottt/website-contact-extractor --silent --output-dataset

```

## MCP server setup

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

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/5SkGr75dFGJ81QwcK/builds/7e2fbLZbJwAnoIYRB/openapi.json
