# Website Contact Scraper: Emails, Phones & Social Links (`steadyline/website-contact-extractor`) Actor

Bulk contact info scraper: give it company websites, get the publicly listed business emails, phone numbers, LinkedIn/X/Facebook/Instagram/YouTube/GitHub/TikTok links and the contact page URL. Checks contact/about/imprint pages, respects robots.txt, $2 per 1,000 sites. By Steadyline Data.

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

## Pricing

from $2.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 Scraper: public emails, phones & social links from any list of websites

Give it a list of websites. For each one it reads the page you supplied and, optionally, a few same-site **Contact / About / Imprint / Team** pages linked from it. It returns the **publicly listed business contact details**: email addresses, phone numbers, social profile links and the contact page URL. One row per site.

- **Respects robots.txt.** Pages disallowed for our crawler are skipped and listed in `skippedByRobots`.
- **No logins, no search engines, no third-party data brokers.** Only the public pages of the sites you supply are read.
- **Small footprint.** At most 20 pages per site (5 by default), no headless browser.

### Use cases

- **Lead list enrichment:** add the public info@/sales@ address, switchboard phone and LinkedIn page to a list of company domains.
- **CRM clean-up:** fill missing company phone numbers and social links in HubSpot, Salesforce or Pipedrive.
- **Agency prospecting:** combine with Tech Stack Detector to find, e.g., Shopify stores and how to reach them.
- **Partner and supplier research:** collect contact pages for a list of vendors in one run.
- **Social profile discovery:** find a brand's official LinkedIn, X, Instagram, YouTube, GitHub and TikTok accounts.

### Input

```json
{ "startUrls": ["https://apify.com", "python.org"], "followContactPages": true, "maxPagesPerSite": 5 }
```

### Output sample

```json
{
  "site": "https://www.acme-example.com",
  "status": "ok",
  "emails": ["info@acme-example.com", "sales@acme-example.com"],
  "phones": ["+1 (555) 010-2000"],
  "linkedin": "https://www.linkedin.com/company/acme-example",
  "twitter": "https://x.com/acmeexample",
  "contactPage": "https://www.acme-example.com/contact",
  "pagesScanned": 4,
  "scannedUrls": ["https://www.acme-example.com/", "https://www.acme-example.com/contact"],
  "skippedByRobots": [],
  "error": null
}
```

`status` is `ok`, `unreachable` or `blocked-by-robots`. Other social keys: `facebook`, `instagram`, `youtube`, `github`, `tiktok`.

### Pricing (pay per event)

| Event | Price | When |
|---|---|---|
| `site-processed` | $0.002 | One website fetched and scanned successfully |

Invalid URLs, duplicates, unreachable sites and sites fully blocked by robots.txt are **never charged**. A site where no contacts are found is still charged, because the scan was done.

**Cost example:** 1,000 websites = **$2.00** plus a small amount of platform usage (in our tests about $0.0001 per site).

### Use it from AI agents (MCP), Zapier, Make, n8n or the API

**AI agents (Claude, Cursor, VS Code, ChatGPT and other MCP clients).** Add Apify's hosted MCP server with just this Actor as a tool:

```json
{
  "mcpServers": {
    "apify": {
      "url": "https://mcp.apify.com?tools=steadyline/website-contact-extractor"
    }
  }
}
```

Sign in with Apify (OAuth) on first connect, or add an `Authorization: Bearer <APIFY_TOKEN>` header. Then ask your agent, for example:

> Use steadyline/website-contact-extractor to find the public contact email, phone number and LinkedIn page for these 20 company websites, and return a table.

The agent sees this Actor's input schema and output fields, so it can call it without extra prompting. Agents that use the general Apify MCP server can also find it with `search-actors`.

This Actor uses pay-per-event pricing with limited permissions, so it can also be run through Apify's agentic payments (no Apify account needed for the agent). See the [Apify docs](https://docs.apify.com/platform/integrations/mcp#agentic-payments).

**Zapier, Make and n8n.** Use the official Apify app: Zapier "Run Actor" action, Make "Run an Actor" module, or the n8n Apify node. Choose `steadyline/website-contact-extractor`, paste the input below, then use "Get dataset items" (or the run's dataset) to send results to Google Sheets, Slack, a CRM or a database.

**API (any language).** Run it and get the results in one call:

```bash
curl -X POST "https://api.apify.com/v2/acts/steadyline~website-contact-extractor/run-sync-get-dataset-items?token=$APIFY_TOKEN" \
  -H "Content-Type: application/json" \
  -d '{"startUrls": ["https://apify.com", "https://www.python.org"], "followContactPages": true, "maxPagesPerSite": 5}'
```

Or with the Python client (`pip install apify-client`):

```python
from apify_client import ApifyClient
client = ApifyClient("<APIFY_TOKEN>")
run = client.actor("steadyline/website-contact-extractor").call(run_input={"startUrls": ["https://apify.com", "https://www.python.org"], "followContactPages": true, "maxPagesPerSite": 5})
for item in client.dataset(run["defaultDatasetId"]).iterate_items():
    print(item)
```

### Works well with other Steadyline Data tools

- **Tech-targeted lead list:** filter domains with [Tech Stack Detector](https://apify.com/steadyline/tech-stack-detector) (e.g. Shopify + Klaviyo), run this Actor on the matches, then clean the emails with [Email Deliverability Checker](https://apify.com/steadyline/email-deliverability-checker). About $2.83 for 1,000 domains.
- **Map, profile, contact:** [Site Discovery](https://apify.com/steadyline/site-discovery) → [Tech Stack Detector](https://apify.com/steadyline/tech-stack-detector) → this Actor, about $0.006 per domain.
- Related: [Tech Stack Detector](https://apify.com/steadyline/tech-stack-detector), [Email Deliverability Checker](https://apify.com/steadyline/email-deliverability-checker), [Site Discovery (sitemaps, robots.txt, llms.txt)](https://apify.com/steadyline/site-discovery).

### FAQ

**Is this an email scraper?**
It extracts e-mail addresses that a website publishes on its own pages (homepage plus up to 19 same-site contact/about/imprint/team pages). It does not guess addresses, query search engines or buy data from brokers.

**Does it find personal emails?**
Only what the site itself publishes. It's meant for business contact points. If you keep personal data such as a named employee's address, you need a lawful basis under GDPR/CCPA. See Acceptable use below.

**What happens with sites that block bots or are down?**
They are returned with `status` = `unreachable` or `blocked-by-robots` and are **not charged**.

**Can I pass bare domains?**
Yes. `python.org`, `https://python.org` and a deep page URL all work; one row is returned per site.

**Can I run it on a schedule?** Yes. Create an Apify Schedule (or a saved Task with a schedule) and connect a webhook or integration to receive results.

**Need a feature or found a bug?** Open an issue on the Issues tab of this page or email steadylinedata@proton.me. Built and maintained by **Steadyline Data**.

### Acceptable use and GDPR

This tool is for finding **business** contact points that organizations publish on purpose, such as info@, sales@ or a switchboard number. You are responsible for how you use the results:

- Personal data (for example a named employee's email address) is protected under GDPR, UK GDPR, CCPA and similar laws. You need a lawful basis, such as legitimate interest with a documented balancing test, to store or contact it. You must honor opt-outs and data-subject requests.
- Follow anti-spam laws (CAN-SPAM, PECR, ePrivacy, CASL). Do not send bulk unsolicited messages.
- Only supply sites that you are allowed to process, and follow each site's terms of use.
- Don't use the results for harassment, profiling of individuals or reselling personal data.

Steadyline Data provides this tool as is and does not give legal advice.

### Limits

Contacts that only appear after JavaScript runs, inside images, or behind forms or logins are not found. Obfuscated emails (e.g. "name \[at] domain") are not decoded.

# Actor input Schema

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

Website or page URLs you have a legitimate reason to process. One result per site. Duplicates and invalid URLs are skipped and never charged.

## `followContactPages` (type: `boolean`):

Follow links on the start page that look like Contact, About, Imprint or Team pages on the same site.

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

Includes the start page.

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

Always on; pages disallowed by robots.txt are skipped.

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

Sites processed in parallel.

## Actor input object example

```json
{
  "startUrls": [
    "https://apify.com",
    "https://www.python.org"
  ],
  "followContactPages": true,
  "maxPagesPerSite": 5,
  "respectRobotsTxt": true,
  "maxConcurrency": 5
}
```

# Actor output Schema

## `overview` (type: `string`):

One row per site.

# 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": [
        "https://apify.com",
        "https://www.python.org"
    ]
};

// Run the Actor and wait for it to finish
const run = await client.actor("steadyline/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 = { "startUrls": [
        "https://apify.com",
        "https://www.python.org",
    ] }

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

```

## MCP server setup

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