# Website Contact Extractor - Email, Phone & Social Scraper (`webdata_labs/website-contact-extractor`) Actor

\[💵 $1.00 / 1K websites, no start fee] Bulk-extract emails, phones and social profiles from company websites. Ranks contact/impressum/kontakt pages in 12+ languages, decodes Cloudflare-protected and (at)-obfuscated addresses, MX-verifies for free, and scores every address 0-100. CSV/JSON.

- **URL**: https://apify.com/webdata\_labs/website-contact-extractor.md
- **Developed by:** [WebData Labs](https://apify.com/webdata_labs) (community)
- **Categories:** Lead generation, SEO tools, Automation
- **Stats:** 2 total users, 2 monthly users, 100.0% runs succeeded, 1 bookmarks
- **User rating**: No ratings yet

## Pricing

from $0.65 / 1,000 website scanneds

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/platform/actors/running/actors-in-store#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 Extractor - Email, Phone & Social Scraper

**Turn a list of company websites into verified emails, dialable phone numbers and social profiles - one row per website, $1.00 per 1,000 websites, no start fee.**

**New Apify accounts can scan about 5,000 websites with the included $5 platform credit.**

Most website **email scrapers** hand you a text dump and call it a lead list. You get `noreply@`, `logo@2x.png`, someone else's Facebook share button, and a "phone number" that is actually a date on a blog post. Then you spend an afternoon cleaning it before a single email goes out. This Actor does the cleaning as part of the extraction: every address is classified and deliverability-checked, every phone is validated against its country's real numbering plan, and every social link is resolved to the company's actual profile. What lands in your spreadsheet is what you can use.

### ✅ What you get / ❌ what this isn't

| ✅ What you get | ❌ What this isn't |
|---|---|
| Emails scored **0-100** from independent signals (mailto link, schema.org, page type, MX) | Not a flat list where a footer `noreply@` looks as good as the founder's address |
| **Cloudflare-protected and (at)-obfuscated** addresses decoded | Not a raw-body regex that reports "no email found" on every Cloudflare site |
| Contact pages found in **12+ languages** - `kontakt`, `impressum`, `contacto`, `contatti`, `contato`, `nous-contacter` | Not an English-only `/contact` guess that misses most of Europe |
| Phones returned in **E.164, validated** against the real numbering plan | Not every 10-digit string on the page, dates and VAT numbers included |
| Social links resolved to the **company profile** | Not `facebook.com/sharer.php` and `twitter.com/intent/tweet` from the share widget |
| **Free MX verification** on every address, in the base price | Not a per-email verification surcharge for a DNS lookup |
| **No start fee** - one website costs $0.001 | Not a run fee that makes a single lookup cost 30x the data |
| Unreachable websites are **not charged** | Not billed regardless of whether anything was reachable |

### 🔎 Why use this Actor

- **Confidence score, not a guess.** Each address gets 0-100 from signals that have to agree: was it in a `mailto:` link, was it in the site's schema.org markup, was it found on a contact page, is it on the company's own domain, does that domain publish mail servers. One boolean, `outreachReady`, collapses it for filtering.
- **Cloudflare de-obfuscation.** A large share of small-business sites hide addresses behind Cloudflare Email Protection or write them as `jane (at) acme (dot) com`. Both are decoded. Sites that other scrapers report as empty come back with a working address.
- **Multilingual page ranking.** The crawl budget goes to the pages that actually hold contacts. `impressum`, `kontakt`, `contacto`, `contatti`, `contato`, `iletisim` and `yhteystiedot` rank as high as `contact`, so a German or Italian list yields like an English one.
- **Real phone validation.** Numbers are parsed with the country inferred from the ccTLD, or from any international-format number on the page, and dropped unless they are valid for that numbering plan. Output is E.164, ready for a dialer.
- **Junk filtering at the source.** `noreply@`, `postmaster@`, `youremail@`, `info@example.com`, image filenames, npm scopes and Sentry keys never reach your dataset.
- **Catch-all aware SMTP.** If you enable the mailbox probe, a domain that accepts every address is flagged as catch-all instead of being sold to you as "verified".
- **Priced per website, not per page.** Crawling 50 pages of a site costs the same as crawling 3. Depth is a quality dial, not a cost dial.

### 👥 Who it's for

Sales, growth and agency teams who already have a list of company websites and need the contacts behind them.

- Enrich a Google Maps, directory or trade-association export with the email that is actually on the site.
- Clean an inherited list before a cold campaign, so bounces do not burn your sending domain.
- Build a call list from validated E.164 numbers instead of a scrape of every digit string.
- Find the LinkedIn company page for a few thousand domains in one run.
- Feed one row per contact straight into a CRM import or a mail-merge tool.

### Example tasks

- [Find emails from company websites](https://apify.com/webdata_labs/website-contact-extractor/examples/find-emails-from-company-websites)
- [Enrich Google Maps leads with emails](https://apify.com/webdata_labs/website-contact-extractor/examples/enrich-google-maps-leads-with-emails)
- [Extract social profiles from websites](https://apify.com/webdata_labs/website-contact-extractor/examples/extract-social-profiles-from-websites)
- [Bulk Email Finder for a List of Company Websites](https://apify.com/webdata_labs/website-contact-extractor/examples/bulk-email-finder-for-website-list)
- [Extract Emails from German Websites (Impressum & Kontakt)](https://apify.com/webdata_labs/website-contact-extractor/examples/german-website-emails-impressum)
- [Export Website Contacts to CRM (One Row per Email)](https://apify.com/webdata_labs/website-contact-extractor/examples/website-contacts-to-crm-import)
- [Verified Email Finder with SMTP Mailbox Check](https://apify.com/webdata_labs/website-contact-extractor/examples/verified-email-finder-smtp-check)
- [Agency Prospecting: Contact Emails for a Prospect List](https://apify.com/webdata_labs/website-contact-extractor/examples/agency-prospecting-contact-finder)
- [Fast Bulk Scan for Large Website Lists](https://apify.com/webdata_labs/website-contact-extractor/examples/fast-bulk-scan-large-lists)

### ⚙️ How to extract contacts from a list of websites

1. Open the Actor and paste your websites into **Websites**. Bare domains (`acme.com`) and full URLs both work, and duplicates are removed for you.
2. Leave **Max pages per website** at 12. It costs the same at 1 or at 100, so only lower it if you want faster runs.
3. Leave **Email verification** on `MX check`. It is free and it is what flags dead domains. Switch to `MX + SMTP mailbox probe` only when you need mailbox-level proof and accept the extra charge.
4. Pick your **Output shape**: one row per website for enrichment and spreadsheets, or one row per contact email for a CRM import.
5. Click **Start**. Results appear on the Output tab, exportable as CSV, JSON or Excel.

#### Getting more out of a stubborn list

If a batch comes back with many `unreachable` rows on sites that clearly load in your browser, turn on **Use a proxy** and re-run just those domains. If you need every address on a site rather than the best one, leave **Stop early** off (the default) and raise **Max pages per website**.

### 📥 Input

```json
{
  "websites": ["basecamp.com", "sipgate.de", "https://www.cluster.gr"],
  "maxPagesPerSite": 12,
  "verificationLevel": "mx",
  "outputMode": "website",
  "respectRobotsTxt": true
}
```

- `websites` - the canonical list of company websites. Domains or URLs are deduplicated automatically.
- `urls`, `domains`, `startUrls` - compatibility aliases for `websites`. Lists are merged and deduplicated, so inputs copied from other contact Actors and agent tools work without remapping.
- `maxPagesPerSite` - crawl budget per site, 1-100, default `12`. Does not affect price.
- `stopWhenEmailFound` - speed switch for very large lists, default `false`. Stops a site once an on-domain email turns up, at the cost of its phones and socials.
- `respectRobotsTxt` - default `true`. Skips paths the site disallows for generic crawlers.
- `verificationLevel` - `none`, `mx` (default, free) or `smtp` (billed per probe).
- `outputMode` - `website` (default, one row per site) or `contact` (one row per email).
- `maxWebsites` - safety cap per run, default `1000`.
- `websiteConcurrency` / `pageConcurrency` / `requestTimeoutSecs` - advanced tuning. Defaults are fine unless a target rate-limits you.
- `useProxy` / `proxyConfiguration` - advanced. Off by default; most company sites do not need a proxy.

### 📤 Output

| domain | status | bestEmail | bestEmailConfidence | phones | linkedin | contactPageUrl |
|---|---|---|---|---|---|---|
| wpbeginner.com | ok | support@wpbeginner.com | 100 | | https://www.linkedin.com/company/wpbeginner | https://www.wpbeginner.com/contact/ |
| sipgate.de | ok | info@sipgate.de | 69 | +492116355550 | https://www.linkedin.com/company/sipgate | https://www.sipgate.de/kontakt |
| monzo.com | ok | help@monzo.com | 92 | +442038720620, +448000884040 | https://www.linkedin.com/company/monzo-bank | |

Each website row also carries `emails` (every address found), `emailDetails` (per address: `type` personal/role/junk, `confidence`, `mxValid`, `smtpAccepted`, `provider`, `isFreeProvider`, `isDisposable`, `onSiteDomain`, `source` showing how it was found, and `foundOn` linking the exact page), `socialLinks` for LinkedIn, X, Facebook, Instagram, YouTube, TikTok, GitHub, Telegram, Pinterest and WhatsApp, plus `outreachReadyEmails`, `pagesCrawled`, `finalUrl`, `crawledAt` and `error`. In `contact` output mode the same fields arrive flattened, one row per email address, ready for a CRM import.

### 💵 How much does it cost?

**$1.00 per 1,000 websites scanned, and no start fee.** One website costs $0.001, a hundred cost $0.10, ten thousand cost $10.00 - the price scales linearly from the very first lookup, which matters if you call this from an agent or a workflow one domain at a time. Crawl depth does not change the price: a 50-page crawl of one site costs the same $0.001 as a 3-page crawl. MX verification is included. Only the optional SMTP mailbox probe is billed on top, at $0.002 per probe, and it is off by default. Websites that cannot be reached at all are not charged. Expect a company email on roughly 65-75% of ordinary business websites; the rest are contact-form-only, JavaScript-rendered, or genuinely publish no address.

| Run size | This Actor - no start fee | A tool with a $0.035 start fee plus $0.001/site |
|---:|---:|---:|
| 1 website | **$0.001** | $0.036 |
| 10 websites | **$0.010** | $0.045 |

#### Pricing tiers

| Apify plan | Price per 1,000 websites |
|---|---:|
| Free | $1.00 |
| Starter | $0.90 |
| Scale | $0.80 |
| Business | $0.65 |
| Platinum | $0.65 |
| Diamond | $0.65 |

### Use with AI agents via MCP

Apify's MCP server lets an AI agent discover this Actor, run it, and read the resulting dataset without custom glue code. The Actor accepts the canonical `websites` field plus `urls`, `domains`, and `startUrls`, so agents can reuse common email-finder payloads.

#### Setup for Claude Code

Add the Apify MCP server to Claude Code, authenticate it with your Apify account, then ask:

> Run `webdata_labs/website-contact-extractor` for these domains, return only outreach-ready emails with confidence at least 70, and include the source page.

#### Claude Desktop, Cursor and VS Code

Add `https://mcp.apify.com` as an MCP server in your client, complete Apify authentication, and select this Actor by its full ID: `webdata_labs/website-contact-extractor`.

Example prompts:

- "Find verified contact emails for these 20 company domains and return a CSV."
- "Enrich this Google Maps export, keep only on-domain emails, and explain every low-confidence result."
- "Scan this one website and return the best email, phone and LinkedIn page."

### Use this Actor in n8n

Create an Apify credential in n8n, add the Apify node, choose **Run an Actor**, and enter `webdata_labs/website-contact-extractor`. Map your incoming domain column to `websites` or `domains`, wait for the run to finish, then read the default dataset. A common workflow is:

`Google Maps or CRM -> Website Contact Extractor -> filter outreachReady -> Lead List Deduplicator -> CRM`

The same input/output pattern works in Make and Zapier. For one-domain automations, the absence of a start fee keeps each event at $0.001 instead of turning a tiny lookup into a run-fee purchase.

### API usage - Using the Apify API

Start a run and return its dataset items in one request:

```bash
curl "https://api.apify.com/v2/acts/webdata_labs~website-contact-extractor/run-sync-get-dataset-items?token=$APIFY_TOKEN" \
  -H "Content-Type: application/json" \
  -d '{"domains":["basecamp.com","sipgate.de"],"verificationLevel":"mx","outputMode":"website"}'
```

Keep `APIFY_TOKEN` in an environment variable or secret manager. Do not place it in source code, public tasks, screenshots, or shared workflow exports.

### Is it legal to scrape website contact information?

This Actor reads contact details that organizations publish on public web pages. Whether you may collect, retain, or use a particular address depends on your jurisdiction, purpose, lawful basis, and outreach method. GDPR, UK GDPR/PECR, CAN-SPAM and local privacy or marketing rules may apply. Respect `robots.txt`, site terms, opt-outs, suppression lists, purpose limitation and retention requirements. This is product information, not legal advice.

### Benchmark - same domains, same job

Release validation uses a fixed 50-domain list with English, German, Italian, Spanish, Portuguese and Cloudflare-fronted sites. The current cloud build produced:

| Build | Domains requested | Reachable / charged | Domains with email | Domains with outreach-ready email | Obvious false positives | Listed data charge |
|---|---:|---:|---:|---:|---:|---:|
| `0.2.6` | 50 | 41 | 23 | 20 | **0** | **$0.041** |

The automated false-positive audit checks malformed addresses, asset filenames, junk mailboxes and localized placeholder domains, followed by manual inspection of every low-confidence result. The run completed in 56 seconds. Run ID: `Rhq4aTR6FrQDLVbLV`; dataset ID: `ddkIfBZGLjkYLDLJD`.

We do not publish a competitor comparison until both Actors have completed the same list under the same settings. This prevents a failed or blocked comparison run from being presented as a product result.

### 🔁 Run it on the Apify platform

Schedule a run to re-check a domain list weekly and catch contacts that appeared since last time, or call the Actor from the API and get results back as JSON. Every run's dataset exports to CSV, JSON, XML or Excel, and integrates with Make, Zapier, n8n, Google Sheets and webhooks, so enriched rows can land directly in your CRM without a manual download step.

### ⚠️ Limits and caveats

- **JavaScript-rendered contacts are not visible.** This Actor fetches HTML, which is what makes it fast and cheap. An address injected by a script after page load will not be found.
- **Contact forms return no email.** A site whose only contact route is a form has nothing to extract; you get `status: ok` with zero emails and the `contactPageUrl` so a human can follow up.
- **Addresses rendered as images are unreadable.** Some sites publish contact details as a PNG specifically to defeat scrapers. That works on this one too.
- **SMTP probes are frequently inconclusive.** Google Workspace, Microsoft 365, Proton and Yandex accept every recipient at SMTP time, so mailbox existence cannot be proven; those come back with an explanatory `note` and the MX result rather than a fabricated verdict. Some hosts also block outbound port 25 entirely.
- **`respectRobotsTxt` costs yield.** It is on by default. Sites with a blanket `Disallow: /` will return fewer pages until you turn it off, which is your call to make.
- **Phone validation is strict by design.** A national-format number on a `.com` site with no other international number anywhere on the page is dropped rather than guessed at. Some German and Austrian registry numbers still pass validation because those numbering plans genuinely allow such shapes.
- **Roughly a quarter to a third of business websites publish no email at all.** No extractor changes that. You are charged for the scan, so use `maxWebsites` on a first run to sanity-check yield on your specific list before committing a large batch.

### 🧩 Related Actors

Build a lead-generation pipeline: **find businesses -> extract contacts -> dedupe -> enrich and prioritize**.

- [**Google Maps Email Leads Scraper**](https://apify.com/webdata_labs/google-maps-email-leads-scraper) - find local businesses and extract their published emails in one run.
- [**Google Maps No-Website Leads Scraper**](https://apify.com/webdata_labs/google-maps-no-website-leads-scraper) - find businesses that need a website before contact enrichment.
- [**Google Maps No Social Media Leads**](https://apify.com/webdata_labs/google-maps-no-social-media-leads) - find businesses missing social profiles.
- [**Google Maps Reputation Leads Scraper**](https://apify.com/webdata_labs/google-maps-reputation-leads-scraper) - prioritize businesses with reputation gaps.
- [**Lead List Deduplicator**](https://apify.com/webdata_labs/lead-list-deduplicator) - merge and deduplicate enriched exports before CRM import.
- [**Website Tech Stack Detector**](https://apify.com/webdata_labs/website-tech-stack-detector) - enrich the same domains with technology signals for relevant outreach.
- [**Company Career Page Jobs API**](https://apify.com/webdata_labs/company-career-page-jobs-api) - add hiring signals to prioritize companies with active demand.

### ❓ FAQ

**Am I charged for websites where nothing is found?**
Yes, if the site was reachable and scanned - the work was done. Websites that could not be reached at all are not charged.

**Does the price go up if I crawl more pages?**
No. Billing is per website. `maxPagesPerSite` changes run time and yield, never cost.

**Is email verification extra?**
MX verification is included in the per-website price. Only the optional SMTP mailbox probe is billed separately, at $0.002 per probe, and it is off unless you turn it on.

**What does `confidence` actually mean?**
It combines how the address was found (a `mailto:` link and schema.org markup count for much more than loose text), whether it sits on the company's own domain, whether it came from a contact page, and what verification returned. A junk mailbox is always 0. A dead MX record caps the score at 10. Filtering on `outreachReady` or `confidence >= 70` is the intended use.

**Which languages does the contact-page detection cover?**
English, German, Spanish, Portuguese, Italian, French, Dutch, Polish, Czech, Swedish, Finnish, Hungarian, Turkish, Lithuanian and Catalan keywords are ranked, plus the well-known unlinked paths every CMS creates.

**Can I get one row per email instead of one per website?**
Yes. Set `outputMode` to `contact`.

**Is this legal?**
It reads publicly published contact details from public web pages, which is what a person visiting the site would see. How you use those details is governed by GDPR, CAN-SPAM, PECR and their equivalents in your market. Have a lawful basis before you send.

### Changelog

#### 2026-07-27

- Added `urls`, `domains`, and `startUrls` input aliases for agent and workflow compatibility.
- Added MCP, n8n/Make/Zapier, API, pricing comparison, legal, benchmark-method and lead-pipeline documentation.
- Published the free-credit comparison and exact six-tier pricing table.
- Added regression filters for retina asset names such as `search-icon@2x.aspx` and localized placeholder domains such as `ejemplo.com`.

#### 2026-07-25

- Added multilingual page ranking, Cloudflare and written-address de-obfuscation, E.164 phone validation, confidence scoring, catch-all detection, and website/contact output modes.

### 🛠️ Support

Something wrong or missing? Open an issue on the Actor's Issues tab with the run URL, the input you used, and what you expected. That is the fastest path to a fix.

### ⭐ Rate this Actor

If this saved you an afternoon of list cleaning, please leave a rating on the Reviews tab. Reviews are the main trust signal other buyers have, and they decide what gets built next - requests that arrive alongside a review are the ones that get prioritised. If something is broken, please open an issue first so it can be fixed; a low rating on a bug that could have been resolved in a day helps nobody.

# Actor input Schema

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

Company websites to scan. Accepts bare domains (acme.com) or full URLs (https://acme.com/about). Paste a column straight from a Google Maps export, a directory scrape, or your CRM - duplicates are removed automatically.

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

Compatibility alias for websites. Use this when an agent, workflow, or copied Actor input provides a urls array.

## `domains` (type: `array`):

Compatibility alias for websites. Bare domains and full URLs are both accepted and deduplicated with every other input list.

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

Compatibility alias for websites. Accepts URL strings and Apify request objects such as {"url":"https://acme.com"}.

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

Crawl budget per site. Pages are ranked by how likely they are to hold contacts (contact, kontakt, impressum, contacto, about, team, ...) in 12+ languages, so a small budget still lands on the right pages. Cost does not change with this number - you pay per website, not per page.

## `stopWhenEmailFound` (type: `boolean`):

Speed switch for very large lists: stop crawling a site the moment an email on that company's own domain turns up. Off by default, because the price is per website and not per page - so the full crawl costs the same and also returns phones, social profiles and the contact page URL.

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

Skip paths the site disallows for generic crawlers. On by default. Turning it off can raise yield on sites with blanket Disallow rules - that choice, and its compliance implications, are yours.

## `verificationLevel` (type: `string`):

none: extract only. mx (default, free): check the address domain actually publishes mail servers, so dead domains are flagged. smtp: additionally ask the mail server whether the mailbox exists, with catch-all detection so a meaningless 'accepted' is never sold as proof. SMTP checks are slower and billed separately.

## `outputMode` (type: `string`):

website: one row per website, with every email in an array (best for enrichment and spreadsheets). contact: one row per email address (best for importing straight into a CRM or a mail-merge tool).

## `maxWebsites` (type: `integer`):

Safety cap on how many websites one run processes, in case a huge list is pasted by mistake.

## `websiteConcurrency` (type: `integer`):

How many websites are scanned at the same time.

## `pageConcurrency` (type: `integer`):

How many pages of a single site are fetched at the same time. Lower this if a target rate-limits you.

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

Give up on a single page after this long. Raise it only if slow sites come back empty.

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

Route page fetches through Apify Proxy. Off by default because most company sites do not need it. Turn on if you see many 403s or unreachable results on sites that clearly work in a browser.

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

Which proxy group to use when 'Use a proxy' is on. Residential is the most reliable against WAFs; datacenter is cheaper.

## Actor input object example

```json
{
  "websites": [
    "acme.com",
    "https://www.example-agency.co.uk"
  ],
  "urls": [],
  "domains": [],
  "startUrls": [],
  "maxPagesPerSite": 12,
  "stopWhenEmailFound": false,
  "respectRobotsTxt": true,
  "verificationLevel": "mx",
  "outputMode": "website",
  "maxWebsites": 1000,
  "websiteConcurrency": 8,
  "pageConcurrency": 5,
  "requestTimeoutSecs": 15,
  "useProxy": false,
  "proxyConfiguration": {
    "useApifyProxy": true,
    "apifyProxyGroups": [
      "RESIDENTIAL"
    ]
  }
}
```

# Actor output Schema

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

No description

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

No description

## `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 = {
    "websites": [
        "basecamp.com",
        "ycombinator.com"
    ]
};

// Run the Actor and wait for it to finish
const run = await client.actor("webdata_labs/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": [
        "basecamp.com",
        "ycombinator.com",
    ] }

# Run the Actor and wait for it to finish
run = client.actor("webdata_labs/website-contact-extractor").call(run_input=run_input)

# Fetch and print Actor results from the run's dataset (if there are any)
print("💾 Check your data here: https://console.apify.com/storage/datasets/" + run["defaultDatasetId"])
for item in client.dataset(run["defaultDatasetId"]).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": [
    "basecamp.com",
    "ycombinator.com"
  ]
}' |
apify call webdata_labs/website-contact-extractor --silent --output-dataset

```

## MCP server setup

```json
{
    "mcpServers": {
        "apify": {
            "command": "npx",
            "args": [
                "mcp-remote",
                "https://mcp.apify.com/?tools=webdata_labs/website-contact-extractor",
                "--header",
                "Authorization: Bearer <YOUR_API_TOKEN>"
            ]
        }
    }
}

```

## OpenAPI specification

Download the OpenAPI definition: https://api.apify.com/v2/acts/hXPK1eWc2TPL8xXMq/builds/oYXNQnXOac3IoGMGm/openapi.json
