# Email Extractor for Websites | Emails & Phones | $2 / 1K (`hridayrungta/contact-info-scraper`) Actor

Bulk email extractor for company websites: pulls published emails, phone numbers (E.164) and LinkedIn, Facebook, Instagram, X, YouTube, TikTok links per domain. No browser, no login. $2 per 1,000 domains with contacts.

- **URL**: https://apify.com/hridayrungta/contact-info-scraper.md
- **Developed by:** [Hriday Rungta](https://apify.com/hridayrungta) (community)
- **Categories:** Lead generation, Automation, Social media
- **Stats:** 3 total users, 2 monthly users, 93.8% runs succeeded, 0 bookmarks
- **User rating**: No ratings yet

## Pricing

from $2.00 / 1,000 domain with contact data

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?

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

A bulk **email extractor** for company websites: it pulls the emails, phone numbers and social media links that a business publishes on its own site, **one clean row per domain**. Paste your domains, get back a contact sheet you can drop into a CRM, a cold-email tool or a spreadsheet. It reads each homepage plus the pages most likely to hold contact details (contact, about, team, impressum, support), decodes obfuscated emails, and normalises every phone number to international E.164 format. Plain HTTP, no browser, no login, public pages only.

You pay **$2 per 1,000 domains that return contact data**, plus a $0.001 start fee per run. Domains that fail to load or return nothing are written to the dataset but never charged.

#### What can you use this email extractor for?

- **Bulk email extractor for a website list.** Extract emails from a website list: Turn a column of domains into a column of published email addresses, with the page each one was found on.
- **Find emails of local businesses.** Run it on the websites of restaurants, clinics, gyms, salons, tradespeople or shops to build a local business contact list.
- **Build a lead list from company websites.** Take company domains from a directory, a trade show list, a funding database or Google Maps and add emails, phones and social profiles.
- **Enrich a company domain list with contact information.** Fill in the missing email, phone and LinkedIn columns in an existing spreadsheet or CRM export.
- **Prospect agencies, freelancers and B2B companies.** Collect outreach contacts for sales, partnerships, PR and link-building campaigns.
- **Scrape contact information from competitor and supplier sites.** Keep a current contact sheet for a market you track.
- **Phone number extractor with clean E.164 output.** Every number is validated with libphonenumber, so it imports straight into dialers, WhatsApp and SMS tools.
- **Find social media profiles of companies.** Get LinkedIn, Facebook, Instagram, X/Twitter, YouTube, TikTok, Pinterest and WhatsApp links per domain.

#### What data do you get?

For every website, one row with:

- **Emails**: from `mailto:` links, plain text, JSON-LD (`schema.org`), Cloudflare-protected `data-cfemail` blobs, and obfuscated forms like `name [at] site [dot] com`. Junk such as image file names (`logo@2x.png`), `example.com`, Sentry and Wix tracking addresses is filtered out.
- **Phone numbers**: from `tel:` links, JSON-LD and page text, validated with libphonenumber and returned in E.164 (`+14155552671`) plus a readable international format and country.
- **Social links**: LinkedIn, Facebook, Instagram, X/Twitter, YouTube, TikTok, Pinterest, WhatsApp. Share buttons and bare network homepages are dropped.
- **Where it was found**: every email and phone number comes with the page URL it was found on, and how (mailto, text, json-ld, cloudflare, tel-link).
- Pages crawled, status, and an error message if the site could not be loaded.

#### Input

| Field | What it does | Default |
|---|---|---|
| **Websites** (`startUrls`) | URLs or bare domains, one per line. Duplicates are merged. | required |
| **Max pages per domain** (`maxPagesPerDomain`) | Homepage plus the best contact-like pages found via same-site links. 1 = homepage only. | 5 |
| **Max domains** (`maxItems`) | Cost cap for the run. | 100 |
| **Default country** (`defaultCountry`) | 2-letter code used to read local-format phone numbers like `(415) 555-0132`. | US |
| **Extract social links** (`includeSocials`) | Collect social profile links. | on |
| **Proxy** (`useProxy`) | Request directly, and retry through Apify datacenter proxy only when a site blocks the request. | on block |
| **Parallel domains** (`maxConcurrency`) | Domains crawled at once (pages inside one domain are fetched one by one with a pause). | 10 |
| **Request timeout** (`requestTimeoutSecs`) | Per-page timeout in seconds. | 15 |

Example input:

```json
{
  "startUrls": ["nav43.com", "thefatduck.co.uk", "studiodrift.com"],
  "maxPagesPerDomain": 5,
  "defaultCountry": "US",
  "includeSocials": true
}
```

#### Output example

```json
{
  "url": "https://nav43.com/",
  "domain": "nav43.com",
  "status": "found",
  "emails": ["contact@nav43.com"],
  "phones": ["+16477940043"],
  "emailDetails": [
    { "email": "contact@nav43.com", "foundOn": "https://nav43.com/", "source": "cloudflare" }
  ],
  "phoneDetails": [
    { "number": "+16477940043", "formatted": "+1 647 794 0043", "country": "CA", "foundOn": "https://nav43.com/", "source": "json-ld" }
  ],
  "linkedin": ["https://linkedin.com/company/nav43"],
  "facebook": ["https://facebook.com/nav43"],
  "instagram": ["https://instagram.com/NAV43digital"],
  "twitter": [],
  "youtube": ["https://youtube.com/channel/UC6mZC3UhZA4r6AKfBt7cYuw"],
  "tiktok": ["https://tiktok.com/@nav43digital"],
  "pinterest": [],
  "whatsapp": [],
  "pagesCrawled": 3,
  "usedProxy": false,
  "error": null
}
```

(Shortened: real rows can list more LinkedIn profiles found on team pages.)

`status` is `found` (at least one email, phone or social link), `no-contacts` (page loaded, nothing found) or `failed` (site could not be loaded).

#### How to use the email extractor (4 steps)

1. Open the Actor and paste your company websites into **Websites**, one per line.
2. Set the **Default country** if your targets are not in the US.
3. Leave **Max pages per domain** at 5, or raise it for bigger sites.
4. Click **Start**, then download the results as JSON, CSV or Excel from the Output tab, or call it from the API.

#### Pricing

- **$0.001 once per run** (start fee).
- **$0.002 per domain** that returns at least one email, phone number or social link (`domain-scraped`).
- Domains with status `failed` or `no-contacts` are written to the dataset but **not charged**.

| Example | Cost |
|---|---|
| 100 domains, about 75 return data | about $0.15 |
| 1,000 domains, about 750 return data | about $1.50 |
| 10,000 domains, about 7,500 return data | about $15 |

Set **Max domains** or the run's maximum charge to cap spending.

#### Integrations and scheduling

Use the dataset wherever your leads live:

- **Google Sheets, Make, n8n, Zapier**: connect the Actor through Apify's integrations and send each finished run's rows to a sheet, a CRM or an email tool.
- **Webhooks and API**: start runs and fetch results over the Apify API, or get a webhook when a run finishes.
- **Apify Schedules**: re-run the same task daily, weekly or monthly on a fresh list of domains so new leads keep arriving without manual work.
- **AI agents**: call it from any agent through the Apify MCP server, input fields and output fields are documented in the schemas.

A simple recurring setup: one scheduled run per week, fed by a new batch of domains from your lead source, writing straight into a Google Sheet.

#### FAQ

##### Does it work on every website?

No. It reads the HTML a normal HTTP request returns. Sites that build their pages with JavaScript after loading (some single-page apps and site builders) can come back with `no-contacts`, and some sites block datacenter traffic even after retrying. In our own test on 44 real small-business and agency sites, 41 loaded; 34 of those (83%) returned at least one email, phone or social link, 27 (66% of loaded sites) returned at least one email, and 7 (17%) returned nothing, which covers JavaScript-only pages and sites that publish no contact details. The other 3 domains did not exist. You are not charged for those.

##### Do I get every email on a site?

No. It crawls a small number of likely pages (default 5), not the whole site, and only finds addresses that are actually present in the page or its Cloudflare/JSON-LD/obfuscated forms. Contact forms without a published address give no email.

##### Email finder vs email extractor: which one is this?

This is an email extractor. It reads the pages of the websites you give it and returns the emails, phone numbers and social links that are published there. It is not an email finder in the person-lookup sense: it does not guess or look up a named person's address from their name and company, and it does not query any contact database. If you need that, use a lead database or finder tool; if you already have company domains and want what each company publishes, this is the right tool.

##### Does it verify that emails are deliverable?

No. It extracts what is published. It does not send mail or check mailboxes. Run the list through an email verification service before a cold campaign.

##### Can it find personal emails of people at a company?

Only what the company publishes on its own pages (for example `jane@company.com` on a team page). It does not look people up elsewhere.

##### Which phone numbers are returned?

Numbers that libphonenumber validates for the country given in the text (or a `+` prefix). Some invalid or non-phone digit strings may still occasionally slip through, and some real numbers may be skipped.

##### Why use this instead of a paid email extractor, email finder or lead database?

Those tools sell a database of people, usually billed per seat or per credit. This Actor works differently: it reads the websites you give it and returns only what each company publishes itself, billed per domain that returns data. It is a good fit when you already have a list of domains and want emails, phones and social links, not a pre-built database. If you need contacts at specific job titles or verified addresses, use a lead database or an email verifier alongside it.

##### What are the best email extractor alternatives?

For a more established general contact scraper, look at [Contact Details Scraper](https://apify.com/vdrmota/contact-info-scraper), which has a much larger user base. This Actor is a lighter option: HTTP only, no browser, one row per domain, E.164 phone normalisation, and you are only charged for domains that return contact data. If you start from Google Maps instead of a domain list, use a Google Maps scraper (see Related Actors below).

##### Can I find emails of local businesses without a domain list?

Not with this Actor alone: it needs websites as input. First collect business websites with a Google Maps scraper, then paste them here. Our own Google Maps Scraper returns each place's website, and the combination gives you a local business email list.

##### Is it legal?

It reads only public web pages, no login, no private data. You are responsible for how you use the contact data, including GDPR, CAN-SPAM and local marketing rules, and for respecting each site's terms.

#### Related Actors

| Actor | What it does |
|---|---|
| [Google Maps Scraper (Places, Phones, Emails)](https://apify.com/hridayrungta/google-maps-places-scraper) | Find local businesses and their websites, then feed the domains into this Actor |
| [Google Maps Scraper by compass](https://apify.com/compass/crawler-google-places) | The most-used Google Maps places scraper on the Store |
| [Google Maps Email Extractor](https://apify.com/lukaskrivka/google-maps-with-contact-details) | Google Maps places with contact details from their websites |
| [Contact Details Scraper](https://apify.com/vdrmota/contact-info-scraper) | General contact scraper for websites, larger user base |
| [Website to Markdown Crawler](https://apify.com/hridayrungta/website-to-markdown-crawler) | Crawl a whole site into clean Markdown for LLMs and RAG |
| [LinkedIn Jobs Scraper](https://apify.com/hridayrungta/linkedin-jobs-scraper) | Job postings by keyword, location or company |

# Actor input Schema

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

Company websites to scrape, one per line: full URLs or bare domains (acme.com). One result row per domain; duplicates are merged.

## `maxPagesPerDomain` (type: `integer`):

Homepage plus the pages most likely to hold contact details (contact, about, team, impressum, support...), found by following same-site links. 1 = homepage only. Higher = more emails found, a little slower.

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

Cost cap: the run processes at most this many domains from your list.

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

2-letter ISO code (US, GB, DE, IN, AU...). Used to read local-format numbers such as (415) 555-0132. Numbers written with a + country code are always read correctly.

## `includeSocials` (type: `boolean`):

Collect LinkedIn, Facebook, Instagram, X/Twitter, YouTube, TikTok, Pinterest and WhatsApp profile links found on the crawled pages.

## `useProxy` (type: `string`):

"On block" first requests every page directly and retries through Apify datacenter proxy (fresh IP each attempt) only when a site refuses the request. "Never" skips the proxy entirely.

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

Domains crawled at the same time. Pages within one domain are always fetched one by one with a short pause.

## `requestTimeoutSecs` (type: `integer`):

Per-page timeout. Slow sites that exceed it are skipped for that page.

## Actor input object example

```json
{
  "startUrls": [
    "nav43.com",
    "thefatduck.co.uk",
    "studiodrift.com"
  ],
  "maxPagesPerDomain": 5,
  "maxItems": 10,
  "defaultCountry": "US",
  "includeSocials": true,
  "useProxy": "onBlock",
  "maxConcurrency": 10,
  "requestTimeoutSecs": 15
}
```

# Actor output Schema

## `results` (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": [
        "nav43.com",
        "thefatduck.co.uk",
        "studiodrift.com"
    ],
    "maxItems": 10,
    "defaultCountry": "US"
};

// Run the Actor and wait for it to finish
const run = await client.actor("hridayrungta/contact-info-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 = {
    "startUrls": [
        "nav43.com",
        "thefatduck.co.uk",
        "studiodrift.com",
    ],
    "maxItems": 10,
    "defaultCountry": "US",
}

# Run the Actor and wait for it to finish
run = client.actor("hridayrungta/contact-info-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 '{
  "startUrls": [
    "nav43.com",
    "thefatduck.co.uk",
    "studiodrift.com"
  ],
  "maxItems": 10,
  "defaultCountry": "US"
}' |
apify call hridayrungta/contact-info-scraper --silent --output-dataset

```

## MCP server setup

```json
{
    "mcpServers": {
        "apify": {
            "type": "http",
            "url": "https://mcp.apify.com/?tools=fetch-actor-details,hridayrungta/contact-info-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/0Z8SuhnJq9qLLEcIy/builds/jZYFd7egfhSeLSV1B/openapi.json
