# Website Contact Scraper - Emails, Phones & 6 Socials (`gio21/website-contact-extractor`) Actor

Crawl any website (plus /contact, /about, /impressum) and get one row with emails, phones, addresses and links for LinkedIn, X, Instagram, Facebook, YouTube and GitHub. $0.01 per site processed, failed sites free.

- **URL**: https://apify.com/gio21/website-contact-extractor.md
- **Developed by:** [Gio](https://apify.com/gio21) (community)
- **Categories:** Lead generation, Other
- **Features:** Limited permissions
- **Stats:** 110 total users, 7 monthly users, 100.0% runs succeeded, 1 bookmarks
- **User rating**: 5.00 out of 5 stars

## Pricing

$10.00 / 1,000 website processeds

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

## Website Contact Information Extractor

### Why use this scraper

Finding a company's contact details usually means opening its homepage, then its `/contact` page, then `/about`, then giving up and checking LinkedIn or Instagram instead, one company at a time. Sales teams building a lead list, agencies vetting prospects, and researchers building a company directory all hit the same wall: contact info is scattered across a handful of pages per site, in inconsistent formats, and doing it by hand does not scale past a few dozen companies.

This actor automates that walk. Give it a list of websites and it crawls the homepage plus the common contact/about pages on each one, pulls out emails, phone numbers, addresses and social profile links, deduplicates everything, and hands back one consolidated row per website. What would be six or seven browser tabs and a spreadsheet of copy-pasted links per company becomes one API call for the whole list.

### Overview

Input is a list of website URLs or bare domains. For each one, the actor fetches the homepage plus a configurable set of extra paths (contact, about, impressum and legal pages by default), scans every page it reaches for contact patterns, and merges the results into a single deduplicated record per site. A batch of a few hundred sites typically finishes in minutes; sites that fail to load at all are not charged.

### Supported inputs

- **`websites`** (required) - list of URLs or plain domains, one company per entry (e.g. `stripe.com` or `https://stripe.com`).
- **`extraPaths`** - comma-separated paths to crawl in addition to the homepage. Defaults to `/contact,/contact-us,/about,/about-us,/impressum,/legal`, which covers where most companies publish contact details; override it for a site with a non-standard structure.
- **`useProxy`** - routes requests through Apify's residential proxy to get past simple bot blocks. Off by default because it slows down the crawl; turn it on only for sites that return empty results with it off.

### Use cases

- **Sales and lead enrichment** - turn a list of target company domains into a contact sheet with email, phone and social handles for outreach.
- **Agency prospecting** - vet a batch of prospective clients by pulling their public contact info and social presence in one pass.
- **Directory and database building** - populate a company directory with verified contact links instead of manual research.
- **Compliance and due diligence checks** - confirm a website publishes a real, reachable contact page and registered address before doing business with it.
- **Recruiter and partnership outreach** - collect LinkedIn and other social links for companies you plan to approach.
- **Market mapping** - process a scraped list of companies in a niche (from a directory or a prior scrape) and turn it into a contactable database in one pass.
- **Investor and vendor research** - pull the public contact footprint of a shortlist of companies before an outreach call, without opening every site by hand.

### How it works

For each website, the actor fetches the homepage and the configured extra paths with a lightweight crawler, then scans the HTML (including structured data where the page provides it) for email addresses, phone-shaped numbers, postal addresses and links to LinkedIn, Twitter/X, Instagram, Facebook, YouTube and GitHub. Matches from every page checked on a site are merged and deduplicated into one output row, along with the list of pages that were actually reachable.

Because the crawl walks a fixed, configurable list of paths rather than trying to render the whole site, it stays fast and predictable even on sites with large navigation menus: it looks exactly where contact information usually lives instead of exploring every link it finds.

### Input configuration

Single site, default paths:

```json
{
  "websites": ["stripe.com"]
}
```

Batch of sites for a lead list:

```json
{
  "websites": ["https://airbnb.com", "https://notion.so", "https://linear.app"]
}
```

Site with a non-standard contact page, using the residential proxy:

```json
{
  "websites": ["https://example-shop.com"],
  "extraPaths": "/pages/contact,/pages/about-us,/support",
  "useProxy": true
}
```

### Output sample

Real item from a production run (truncated for readability; the actual `phones` array can contain more raw matches than shown here):

```json
{
  "website": "https://stripe.com",
  "emails": ["jane.diaz@stripe.com"],
  "phones": ["+1 888 926 2289"],
  "addresses": [],
  "linkedin": ["https://www.linkedin.com/company/stripe"],
  "twitter": ["https://twitter.com/stripe"],
  "instagram": ["https://www.instagram.com/stripehq"],
  "facebook": ["https://www.facebook.com/StripeHQ"],
  "youtube": ["https://youtube.com/@stripe", "https://youtube.com/@StripeDev"],
  "github": ["https://github.com/stripe"],
  "pagesScraped": ["https://stripe.com"],
  "scrapedAt": "2026-09-21T19:13:00.651Z"
}
```

### Key output fields

| Field | Type | Description |
|---|---|---|
| `website` | string | The input website, echoed back |
| `emails[]` | array | Deduplicated email addresses found across all pages checked |
| `phones[]` | array | Phone-shaped number strings found on the page; see limitations below |
| `addresses[]` | array | Postal addresses detected, when the site publishes one in a recognizable format |
| `linkedin[]` / `twitter[]` / `instagram[]` / `facebook[]` / `youtube[]` / `github[]` | array | Links to that platform found on the site |
| `pagesScraped[]` | array | Which of the homepage + extra paths actually responded and were scanned |
| `scrapedAt` | string | ISO timestamp of the crawl |

### Pricing

| Event | Price |
|---|---|
| Website processed (`website-processed`) | $0.01 per website crawled and deduplicated |

Sites that fail entirely (no page loads) are not charged.

### What makes this richer than the competition

- **`thenetaji/website-email-scraper`** (117 users/30d) charges $0.005 per result on the free tier down to $0.002 on higher tiers, cheaper than this actor's flat $0.01, but returns emails and phones without the six-platform social link set (LinkedIn, Twitter, Instagram, Facebook, YouTube, GitHub) this actor consolidates into every row.
- **`jurassic_jove/website-email-extractor`** (83 users/30d) charges $0.006 per URL and follows Linktree/bio-page links, but covers a narrower set of social platforms than the six this actor returns per site.

This actor's differentiator is breadth per row: one call returns emails, phones, addresses and six social platforms merged from up to six pages per site, rather than requiring a second actor or a manual pass to fill in the social links. For a sales team building a lead list, that means one output column set feeds the CRM directly instead of stitching together two tools' results.

### Notes & limitations

- Phone detection is pattern-based and can pick up other numeric strings on pages dense with numbers (prices, dates, order IDs), alongside real phone numbers. Treat the `phones` array as candidates to verify, not a guaranteed-clean list, and prefer `emails` and the social links when you need the highest-confidence fields.
- Sites that require JavaScript to render their contact page, or that block simple crawlers, may return empty results with `useProxy` off; try turning it on for those.
- The actor only visits the homepage and the configured `extraPaths`; a contact page at an unlisted path will be missed unless you add it.
- `addresses` detection is best-effort and depends on the site publishing an address in a common, machine-readable format.
- A site behind a hard bot-block (Cloudflare challenge pages and similar) may return zero pages scraped even with the proxy on; those sites are out of scope for this crawler and would need a browser-based tool instead.

### FAQ

**Does this handle a list of thousands of domains?** Yes, pass them all in `websites`; each is billed and processed independently.

**What if a site has no contact page at all?** The actor still returns whatever it found on the homepage; `pagesScraped` shows exactly which pages responded.

**Can I extract from a single page URL instead of a domain?** Yes, pass the exact URL; the actor will still also try the configured `extraPaths` relative to that host.

**Why are some phone numbers obviously wrong?** See Notes & limitations: the phone matcher is intentionally broad to avoid missing real numbers, which means it also catches some non-phone numeric strings.

**Does it require login or an API key for the target sites?** No, it only reads publicly available pages.

**Will it find personal emails of employees, not just a general company address?** Only if those emails are published somewhere on the crawled pages (a team page, an about page with staff bios); the actor does not search beyond the site itself.

**How is this different from just Googling the company?** It processes an entire list of companies in one run and returns the results as structured data, instead of a page-by-page manual search per company.

**Can I re-run the same list later to catch updates?** Yes, each run is independent; re-run the same `websites` list periodically to refresh contact info as companies update their pages.

### For AI Agents & LLM Apps

Call this actor from an MCP client via `mcp.apify.com`, or synchronously from a backend enriching a lead list:

```bash
curl "https://api.apify.com/v2/acts/gio21~website-contact-extractor/run-sync-get-dataset-items?token=$APIFY_TOKEN" \
  -X POST -H "Content-Type: application/json" \
  -d '{"websites": ["stripe.com", "airbnb.com"]}'
```

The response is the dataset items directly, ready to merge into a CRM record or agent-driven outreach workflow, with each site's socials and emails already deduplicated so the agent does not need a separate cleanup step before acting on them.

### SEO Keywords

website contact scraper, email extractor API, company contact finder, bulk email scraper, lead enrichment API, website social links scraper

# Actor input Schema

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

List of website URLs (or just domains) to extract contact info from.

## `extraPaths` (type: `string`):

Comma-separated paths (in addition to homepage) to look for contact info.

## `useProxy` (type: `boolean`):

Slower but bypasses simple bot blocks. Off by default.

## Actor input object example

```json
{
  "websites": [
    "https://stripe.com",
    "https://airbnb.com"
  ],
  "extraPaths": "/contact,/contact-us,/about,/about-us,/impressum,/legal",
  "useProxy": false
}
```

# Actor output Schema

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

Dataset items

# 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": [
        "https://stripe.com",
        "https://airbnb.com"
    ]
};

// Run the Actor and wait for it to finish
const run = await client.actor("gio21/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 = { "websites": [
        "https://stripe.com",
        "https://airbnb.com",
    ] }

# Run the Actor and wait for it to finish
run = client.actor("gio21/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 '{
  "websites": [
    "https://stripe.com",
    "https://airbnb.com"
  ]
}' |
apify call gio21/website-contact-extractor --silent --output-dataset

```

## MCP server setup

```json
{
    "mcpServers": {
        "apify": {
            "type": "http",
            "url": "https://mcp.apify.com/?tools=fetch-actor-details,gio21/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/lfPYZ3GKOu3YFpdQO/builds/9wY7XOaD5pwC04ng6/openapi.json
