# Website Contact Scraper (`asgardlabs/website-contacts-extractor`) Actor

The right email, phone, social profiles, postal address and legal company name from any company website. Reads the pages that matter (contact, about, imprint, team), scores each email, drops placeholders. Half a cent per site; blocked or dead sites free.

- **URL**: https://apify.com/asgardlabs/website-contacts-extractor.md
- **Developed by:** [Asgard Labs](https://apify.com/asgardlabs) (community)
- **Stats:** 2 total users, 1 monthly users, 100.0% runs succeeded, 0 bookmarks
- **User rating**: No ratings yet

## Pricing

from $5.00 / 1,000 sites

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?

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 – emails, phones, socials, address, legal entity from any company site

Paste a list of company websites. Get back, for each one, the email that is not just info@, the phone number, the company's own social profiles, the postal address, the registered legal name with VAT and registration number, and the people named on the team page.

It reads the pages where this data actually lives: home, contact, about, imprint / legal notice and team. Not just the home page. Every email carries a confidence score and a flag for whether it belongs to the site's own domain, so you always know which one to use.

### Website contact data per site

- **bestEmail** – a personal address at the company's domain when one is published, otherwise the best available.
- **bestGenericEmail** – the info@, hello@ or support@ style mailbox.
- **emails** – every address found, with confidence, where it was found and whether it is a role mailbox.
- **phones** – deduplicated, tel: links first.
- **socials** – LinkedIn, X, Facebook, Instagram, YouTube, TikTok, GitHub, Pinterest, Threads, Crunchbase. Only the company's own profiles, not the customer logos on the home page.
- **addresses** – from structured data, microdata or address blocks.
- **org** – name, legal name, VAT id, registration id, logo, description, founding year, employee count when the site publishes them.
- **people** – names with job titles from team pages and structured data.
- **title, description, pagesFetched, summary** – what was read and how much was found.

### Use cases

- Build a prospect list from a set of company websites, with the best email to write to.
- Enrich a CRM export that has only domains with phone, LinkedIn and the registered company name.
- Verify who is behind a website before a deal: legal name, VAT id, registration number.
- Find the people and titles a company lists on its team page.

### Input

| Field | Default | Meaning |
|---|---|---|
| `urls` | – | Domains or full URLs, one per line. `example.com` is enough. |
| `maxPages` | 6 | Extra pages read per site after the home page. |
| `tryCommonPaths` | true | Also try /contact, /about, /impressum, /team when the home page does not link to them. |
| `timeoutSecs` | 20 | Wait per page. A site never takes longer than about three times this. |
| `concurrency` | 10 | Sites processed in parallel. |

### Output example

```json
{
  "domain": "apify.com",
  "finalUrl": "https://apify.com/",
  "status": 200,
  "title": "Apify: The largest marketplace of trusted tools for AI",
  "bestEmail": "james.hill@apify.com",
  "bestGenericEmail": "hello@apify.com",
  "emails": [
    { "value": "hello@apify.com", "domainMatches": true, "generic": true, "confidence": 1, "sources": ["mailto", "text"], "pages": ["https://apify.com/contact"] },
    { "value": "james.hill@apify.com", "domainMatches": true, "generic": false, "confidence": 0.65, "sources": ["text"], "pages": ["https://apify.com/about"] }
  ],
  "bestPhone": "+17183565168",
  "phones": [{ "value": "+17183565168", "confidence": 0.5, "sources": ["text"] }],
  "socials": { "linkedin": "https://linkedin.com/company/apify", "twitter": "https://x.com/apify", "github": "https://github.com/apify", "tiktok": "https://www.tiktok.com/@apifytech" },
  "addresses": [{ "street": "Na Příkopě 959/27", "city": "Prague", "postalCode": "11000", "country": "CZ", "source": "jsonld" }],
  "org": { "name": "Apify", "legalName": "Apify Technologies s.r.o.", "url": "https://apify.com/", "foundingDate": "2015" },
  "people": [],
  "pagesFetched": ["https://apify.com/", "https://apify.com/contact", "https://apify.com/about"],
  "summary": { "emails": 3, "phones": 1, "socials": 4, "addresses": 1, "people": 0, "hasOrgSchema": true },
  "durationMs": 5800
}
```

### How to use

1. Paste your website domains, one per line into the input form. The example input is ready to run as is.
2. Click **Start**. Rows appear in the **Output** tab as they are found.
3. Download the table as CSV, JSON or Excel, or read it through the API.

### Pricing

**$0.005 per website** that returned a page. 1,000 websites cost $5. Sites that block automated visitors (HTTP 403 / 429), time out or do not resolve are reported in the dataset with the reason and are **not charged**.

### Good to know

- No browser and no proxies, so it is fast: usually 4 to 6 seconds per site.
- It reads what the site publishes. It does not guess emails or buy data.
- Works with old sites too: handles ISO-8859-1 pages and falls back to http when https is broken.
- Failures come with a plain reason: `timeout`, `ENOTFOUND (domain not found)`, `no HTML (HTTP 429)`.
- Typical use: run a domain list from your CRM or a lead list, then filter on `bestEmail` and `org.legalName`.

### Use from code or an AI agent

Every run can be started and read through the Apify API, the JavaScript and Python clients, or an AI agent with tool access. Open the **API** tab on this page for ready-made snippets. Pricing is per event, so an agent pays only for what it receives.

### FAQ

**Why is `bestEmail` a person and not info@?**
Personal addresses at the site's own domain rank first; info@, sales@ and other role mailboxes are kept in `bestGenericEmail`. Both are in the row.

**What if the site blocks automated visitors?**
The site is reported as blocked with the HTTP status and is not charged. Nothing is guessed.

**Does it read imprint and legal pages?**
Yes. Contact, about, imprint, legal, privacy and team pages are ranked from the home page links, and the usual paths are tried when they are not linked.

**How many pages does it read per site?**
The home page plus up to `maxPages` more, six by default. A site never takes longer than about three times the timeout.

**Does it guess or buy contact data?**
No. It only returns what the site publishes, with the page each item came from.

# Actor input Schema

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

Domains or URLs, one per line.

## `maxPages` (type: `integer`):

Contact/about/imprint/team pages fetched after the home page.

## `tryCommonPaths` (type: `boolean`):

When the home page does not link to them, also request the usual contact, about, imprint, legal and team paths.

## `timeoutSecs` (type: `integer`):

Give up on a single page after this many seconds. A site takes at most about three times this in total.

## `concurrency` (type: `integer`):

How many sites to process at the same time. Ten is safe at the default memory; higher values need more memory.

## Actor input object example

```json
{
  "urls": [
    "apify.com",
    "mollie.com",
    "personio.com"
  ],
  "maxPages": 6,
  "tryCommonPaths": true,
  "timeoutSecs": 20,
  "concurrency": 10
}
```

# Actor output Schema

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

One row per website: bestEmail, emails, phones, socials, addresses, org (legal name, VAT, registration id), people, pagesFetched, or ok:false with a plain error.

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

Counts, skipped inputs with reasons, errors in plain words, charge-limit state.

# 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": [
        "apify.com",
        "mollie.com",
        "personio.com"
    ]
};

// Run the Actor and wait for it to finish
const run = await client.actor("asgardlabs/website-contacts-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": [
        "apify.com",
        "mollie.com",
        "personio.com",
    ] }

# Run the Actor and wait for it to finish
run = client.actor("asgardlabs/website-contacts-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": [
    "apify.com",
    "mollie.com",
    "personio.com"
  ]
}' |
apify call asgardlabs/website-contacts-extractor --silent --output-dataset

```

## MCP server setup

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