# Website Contact Scraper – Verified Emails, Phones & LinkedIn (`arisma_tech/website-contact-email-scraper`) Actor

Find emails, phone numbers and LinkedIn and social media profiles from any list of company websites. MX-verified emails for B2B lead generation. JavaScript and protected sites handled automatically. Export to CSV or Excel. Pay only for websites where contacts are found.

- **URL**: https://apify.com/arisma_tech/website-contact-email-scraper.md
- **Developed by:** [Arishma](https://apify.com/arisma_tech) (community)
- **Categories:** Lead generation, Business
- **Stats:** 2 total users, 1 monthly users, 100.0% runs succeeded, 0 bookmarks
- **User rating**: No ratings yet

## Pricing

from $3.00 / 1,000 website with contacts

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

## Website Contact Scraper – Verified Emails, Phones & LinkedIn

Turn a list of company websites into **clean, verified contact data**: emails (classified and MX-checked), phone numbers, LinkedIn and other social profiles, plus the company's name, description, address and logo. **You only pay for websites where contacts were actually found.**

Built for sales teams, agencies and data enrichment workflows that need reliable company contacts, not a pile of junk addresses.

### What you get

- **Emails, cleaned.** Finds addresses in links, page text, structured data and common obfuscations (`name [at] company [dot] com`, Cloudflare-protected emails), and filters out the junk other tools return (image file names, tracking addresses, placeholder emails like `name@example.com`).
- **Email verification (MX check).** Confirms each email's domain has working mail servers and detects the provider (Google Workspace, Microsoft 365, Zoho, …). This tells you whether the domain can receive email at all. It does not prove a specific mailbox exists. `mxStatus` says why: `mx`, `a_record` (no MX, but the domain accepts mail on its address record), `null_mx` / `no_mail` / `nxdomain` (cannot receive mail), or `timeout` / `dns_error` (could not be determined, `mxValid` is `null`).
- **Email classification.** Each email is tagged `role` (info@, sales@, support@) or `personal`, on-domain or not, free provider (gmail.com…) or disposable.
- **A smart primary email** per company, preferring verified on-domain contact addresses.
- **Only the company's own contacts.** Addresses of other companies that merely appear in page text (product screenshots, testimonials, partner lists) are left out; an off-domain address is kept when the website links it as a contact.
- **Phones** from click-to-call links and structured data, normalized to digits (`+` and country code for international numbers). The same number written in different formats is listed once, best-sourced number first.
- **Social profiles:** LinkedIn, X/Twitter, Facebook, Instagram, YouTube, TikTok and GitHub. Share buttons and post links are excluded. `linkedinUrl`, `twitterUrl`, … hold the company's own profile (from structured data, a matching handle or a site-wide link) and stay empty rather than show an employee's account; every profile found is in `socials`.
- **Company profile:** name, description, address, logo.
- **Smart crawling.** The homepage plus the pages most likely to hold contacts (contact, about, team, imprint/impressum, legal), in many languages. It never wanders off-site.
- **Fast.** Websites are processed in parallel and each result is saved as soon as its website is done; one slow or unreachable website never holds up the others.

### How to use it

1. Paste websites or domains, one per line (`stripe.com`, `https://www.acme.com`).
2. Optionally set the pages per website (default 10) and turn on **One row per email** for CRM imports.
3. Run, then export to CSV, Excel or JSON, or connect it to your CRM via Apify integrations.

#### Output example

```json
{
  "status": "ok",
  "domain": "acme.com",
  "url": "https://acme.com/",
  "redirectedTo": null,
  "companyName": "Acme Inc",
  "description": "Acme makes widgets for modern teams.",
  "address": "1 Main St, San Francisco, US",
  "primaryEmail": "hello@acme.com",
  "primaryEmailMxValid": true,
  "emailProvider": "Google Workspace",
  "emails": [
    { "email": "hello@acme.com", "type": "role", "onWebsiteDomain": true, "isFreeProvider": false,
      "isDisposable": false, "mxValid": true, "mxProvider": "Google Workspace", "sources": ["https://acme.com/contact"] },
    { "email": "jane@acme.com", "type": "personal", "onWebsiteDomain": true, "isFreeProvider": false,
      "isDisposable": false, "mxValid": true, "mxProvider": "Google Workspace", "sources": ["https://acme.com/team"] }
  ],
  "primaryPhone": "+14155550100",
  "linkedinUrl": "https://linkedin.com/company/acme",
  "twitterUrl": "https://x.com/acmeinc",
  "pagesCrawled": 6,
  "scrapedAt": "2026-10-08T12:00:00+00:00"
}
```

`status` is `ok` (contacts found), `no_contacts` (website crawled, nothing published) or `failed` (with an `error` explaining why).

`redirectedTo` is set when the website itself redirects to another domain (a rebrand, an acquisition, a parent company): the contacts then belong to that domain. Check it if a result looks like a different company — you may have meant another website.

The run's `OUTPUT` record summarizes the run, including timing (total seconds, median and slowest website).

### Pricing

Pay-per-event, with platform usage (compute and proxy) included. See the **Pricing** tab for current prices on your plan.

| Event | When it is charged |
|---|---|
| Website with contacts (`domain-result`) | Each website where emails, phones or social profiles were found |
| Protected website (`protected-page`) | Extra charge for each heavily protected website that needs additional processing |

- Websites with no contacts and failed websites are never charged the base price.
- Protected websites are detected and handled automatically. Most business websites are not protected: in our tests about 1 in 20 were. You can turn off *Process protected websites* to skip them and never pay this charge.

### FAQ

**Does the MX check guarantee delivery?** No tool can guarantee that without sending an email. The MX check confirms the domain accepts mail, which catches dead and mistyped domains. Combined with on-domain filtering, it removes most bad addresses.

**How fast is it?** Websites are processed in parallel, so a batch takes about as long as its slowest website, not the sum of all of them; protected websites that need extra handling take longer. Speed depends on the websites themselves. `maxConcurrency` (websites in parallel), `pageTimeoutSecs` and `siteTimeoutSecs` let you trade speed for completeness. More memory (4 GB) lets more websites that need a full browser run in parallel.

**Why no emails for a website?** Many companies only publish a contact form. Those websites are returned as `no_contacts` and are not charged.

**Is this legal?** The actor only collects contact details that companies publish on their own websites. If you process personal data (for example a named employee's email), you are responsible for complying with GDPR, CAN-SPAM and similar laws, including having a lawful basis for outreach.

# Actor input Schema

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

Company websites or domains, e.g. stripe.com or https://www.acme.com. One per line.

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

Upper limit. The homepage is checked first, then the most relevant pages (contact, imprint, about, team) a few at a time; crawling stops as soon as the website's contact details are found, so most websites use far fewer pages.

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

Check that each email's domain has working mail servers, and detect the email provider (Google Workspace, Microsoft 365, …).

## `includePhones` (type: `boolean`):

Collect phone numbers published on the website.

## `includeFreeEmails` (type: `boolean`):

Keep addresses like name@gmail.com found on the website. Turn off for company-domain emails only.

## `oneRowPerEmail` (type: `boolean`):

Output one row per email (with company details repeated) instead of one row per website. Handy for CRM imports. Charging is still per website.

## `allowProtectedPages` (type: `boolean`):

Websites that block normal access are detected and processed automatically, with an extra Protected website charge for each one. Turn off to skip them: they are reported as failed and not charged.

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

Maximum number of websites processed in parallel (each loads up to 3 pages at a time). Websites that need a full browser are additionally limited by the run's memory.

## `pageTimeoutSecs` (type: `integer`):

How long to wait for one page to load before giving up on it.

## `siteTimeoutSecs` (type: `integer`):

Maximum time spent on one website, all pages and retries included. A website that runs out of time keeps the contacts found so far; one whose homepage never loaded is reported as failed.

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

Used only for websites that block direct access (most websites are fetched directly). Apify Proxy is recommended.

## Actor input object example

```json
{
  "websites": [
    "apify.com",
    "basecamp.com",
    "pipedrive.com"
  ],
  "maxPagesPerSite": 10,
  "verifyEmails": true,
  "includePhones": true,
  "includeFreeEmails": true,
  "oneRowPerEmail": false,
  "allowProtectedPages": true,
  "maxConcurrency": 20,
  "pageTimeoutSecs": 15,
  "siteTimeoutSecs": 90,
  "proxyConfiguration": {
    "useApifyProxy": true
  }
}
```

# Actor output Schema

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

No description

## `summary` (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 = {
    "websites": [
        "apify.com",
        "basecamp.com",
        "pipedrive.com"
    ],
    "proxyConfiguration": {
        "useApifyProxy": true
    }
};

// Run the Actor and wait for it to finish
const run = await client.actor("arisma_tech/website-contact-email-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": [
        "apify.com",
        "basecamp.com",
        "pipedrive.com",
    ],
    "proxyConfiguration": { "useApifyProxy": True },
}

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

```

## MCP server setup

```json
{
    "mcpServers": {
        "apify": {
            "type": "http",
            "url": "https://mcp.apify.com/?tools=fetch-actor-details,arisma_tech/website-contact-email-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/gPANwX3erNboF9k8q/builds/WnVGg6ysWHVI2HDsm/openapi.json
