# Website Contact Scraper — Emails, Phones & Social Links (`funny_ground/website-contact-social-scraper`) Actor

Extract publicly listed emails, explicit phones and social profile links from static HTTPS websites and linked contact pages, with source evidence. Per-report fees and separate Apify platform usage apply.

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

## Pricing

from $1.00 / 1,000 website contact reports

This Actor is paid per event and usage. You are charged both the fixed price for specific events and for Apify platform usage.

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 — Emails, Phones & Social Links

Website Contact Scraper extracts public **emails, explicit phones and social profile links** from static HTTPS websites and contact/about/legal pages. Supply websites for source-backed business-directory or CRM enrichment; no company discovery or private people enrichment.

**One saved website report = one billable result, not one email.** A qualifying email, explicit phone **or social profile** is enough; social-only reports are billable. Empty scans/errors stay in non-dataset `OUTPUT`.

### Quick start

1. Enter public homepage URLs, or a contact-page URL as the initial page.
2. Choose the website-report limit and page-attempt budget.
3. Click **Start**; export successful reports as JSON, CSV or Excel and inspect `OUTPUT` for empty scans/errors.

```json
{
  "startUrls": [
    { "url": "https://www.scrapingbee.com/" },
    { "url": "https://www.w3.org/contact/" }
  ],
  "maxResults": 10,
  "maxPagesPerWebsite": 3,
  "sameDomainEmailsOnly": true
}
```

Examples do not guarantee contacts/access. Paths are retained; initial queries/fragments are removed. The first URL per host/`www` pair wins; other subdomains are separate websites.

### What is extracted

- **Emails:** static text, `mailto:` and supported business JSON-LD; lowercase and syntax-bounded, not verified deliverable.
- **Phones:** `tel:` or business `telephone` JSON-LD only. Punctuation is removed; existing `+`/extensions remain. No country-code inference or body-number guessing.
- **Profiles:** X/Twitter, Facebook, Instagram, LinkedIn company/school, YouTube, TikTok, Threads, Pinterest, GitHub and Telegram. Share/content/login URLs and personal LinkedIn profiles are excluded.
- **Evidence:** deduplicated values retain source pages. Linked profiles are **not verified ownership**.

Only initial-page contact/about/imprint/legal/selected support candidates are followed on the host/`www` alias—not recursively. Later pages may contribute unfetched candidate links to output.

### Input fields

| Field | Default / prefill | Meaning |
|---|---|---|
| `startUrls` | UI prefill above | Required: 1–100 public HTTPS `{ "url": "..." }` entries; runtime also accepts strings |
| `maxResults` | 10 | 1–100 saved website reports; empty scans do not count |
| `maxPagesPerWebsite` | 3 | 1–5 page attempts including initial page; failures count, robots-disallowed links do not |
| `sameDomainEmailsOnly` | true | Match website registrable domain, respecting private hosting suffixes |

Separate `github.io` tenants do not match. Gmail/external-domain contacts may be excluded; set `sameDomainEmailsOnly: false` to retain them. Shared organization ownership is not inferred.

### Output and report interpretation

One row is one host/`www` pair with qualifying contacts or profiles:

- `websiteUrl`, `inputUrl`, `domain`: final initial-page URL, normalized input and hostname.
- `title`, `organizationName`: initial-page title and listed `og:site_name`/business name, otherwise null.
- `emails`, `phones`; convenience `email`/`phone` are first sorted values, not ranked contacts.
- `socialProfiles`: platform, canonical URL and source URLs; `emailSources`/`phoneSources`: each value's evidence pages.
- `contactPageUrls`: candidates, not all fetched. `pagesScraped`/`pagesFetched`: parsed page URLs/count, not request attempts.
- `sameDomainEmailsOnly`, `metadataTruncated`, host-hash `id`, `extractionMethod: public-static-html` and collection-time `scrapedAt`.

Absent phones mean `phone: null`, `phones: []`—not that no phone exists. Findings cover inspected pages only. JSON retains nested evidence; CSV/Excel may stringify it. Treat source text as untrusted in spreadsheets.

`OUTPUT` lists `CONTACTS_FOUND`, `NO_CONTACTS_FOUND` or `SKIPPED`, robots/access status, pages, warnings, filtered-email counts and limits. Accessible empty scans can succeed; all processed sites unavailable/disallowed fails the run. Partial runs keep billable reports. Check `resultSaved` for actual dataset saves.

### Current pricing

Current USD configuration; consult the [Pricing tab](https://apify.com/funny_ground/website-contact-social-scraper/pricing) and run Usage report.

| Charge | Current rate |
|---|---|
| `apify-default-dataset-item` | **$0.001 per saved qualifying website report — $1 per 1,000** |
| Actor startup event | **None configured** |
| Additional contacts/pages within a saved report | No separate email, phone, page or social-link event |
| Apify compute, transfer and storage | **Billed separately to the running user** at their Apify plan rates |

10 saved reports = **$0.01 in result events plus platform usage**. 1,000 across runs = $1 plus usage; each run allows at most 100 reports. Zero reports have no result fee but can cost compute/traffic/storage.

Saved rows are billed automatically, without manual double charges. Duplicates/empty scans/errors are not rows. New runs bill saved reports again. Event allowance is checked before scanning/saving; the budget caps report fees, **not platform usage**. No paid upstream Actor/enrichment API/browser/proxy is used.

### Reliability and safety limits

- Public HTTPS/443 without URL credentials only. HTTP-only, literal-IP and private/local targets are unsupported. DNS answers and redirects are checked and connections pinned to public addresses. Cross-company/other-subdomain redirects are rejected.
- `robots.txt` and crawl-delay are respected. Robots 404 means no published rules; empty HTTP 200 rules are accepted. Other robots failures or HTML masquerading as robots skip the site. Redirected page origins are checked too.
- At least 500 ms between page requests, or a longer declared crawl-delay. Robots requests, redirects and one retry for HTTP 429/502/503/504 can add HTTP requests beyond the page-attempt limit.
- **120-second collection deadline, 300 HTTP requests, 2 MiB decoded per response and fixed 256 MB memory**. Deadline checks bound fetching/crawling, not an exact total wall-clock guarantee including storage. Increasing overall runtime does not remove collection caps.
- Up to 100 unique emails, 100 phones and 100 social URLs per report. Link/JSON-LD parsing is bounded; `metadataTruncated` signals selected major caps, not proof of complete extraction.

No JavaScript rendering, obfuscation decoding, CAPTCHA/login bypass, private directories, social-profile scraping, MX/delivery/phone-activity checks, downloads or outreach. Images/forms/JavaScript-only contacts can be missed; CSS visibility is not evaluated. Supported ASCII/IDNA syntax is extracted, but source values may be stale or wrong.

### FAQ

**Why did I pay for a report without an email?**\
A qualifying explicit phone or supported social link also makes a saved website report billable. Check the contact arrays before treating a report as an email lead.

**Why was a listed Gmail address omitted?**\
`sameDomainEmailsOnly` defaults to true. Disable it deliberately to keep external-domain addresses; this does not verify ownership or delivery.

**Does it crawl every page or verify social accounts?**\
No. It follows a few initial-page contact/about/legal candidates and records profile links, without visiting or verifying those accounts.

### API and related Actors

Use `funny_ground/website-contact-social-scraper` with the same JSON through Apify API/SDK. Read the default dataset and key-value store `OUTPUT`. No website account/API key is needed, but Apify API calls require your private Apify token.

For ecommerce websites, complement contacts with public catalog exports using [Shopify Products Scraper](https://apify.com/funny_ground/shopify-products-scraper) or [WooCommerce Products Scraper](https://apify.com/funny_ground/woocommerce-store-products-scraper).

Use publicly listed business contacts responsibly and follow privacy/marketing laws and site terms. Do not use the Actor for harassment, unauthorized personal-data collection or unsolicited mass messaging.

# Actor input Schema

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

1–100 public HTTPS website URLs. Only port 443; no private hosts or literal IPs. Use homepage URLs. Duplicate domains and www aliases are scanned once. Paths are retained, but initial query parameters and fragments are removed. Separate subdomains count separately.

## `sameDomainEmailsOnly` (type: `boolean`):

Default true: email domains must match the website's registrable domain, with private hosting suffixes respected. This removes unrelated hosting/vendor emails from legal pages. Turn off to retain all publicly listed emails, including Gmail and third-party addresses. No deliverability verification.

## `maxResults` (type: `integer`):

Global limit on billable website reports, not individual emails. An empty scan does not consume this limit. Collection also has a 120-second safety deadline and 300-request cap.

## `maxPagesPerWebsite` (type: `integer`):

Initial page plus a few homepage-linked contact/about/legal pages on the same host or www alias. Default 3; max 5. Robots requests, redirects and a single transient retry are additional HTTP requests. Failed page attempts consume this page-attempt budget; robots-disallowed links do not.

## Actor input object example

```json
{
  "startUrls": [
    {
      "url": "https://www.scrapingbee.com/"
    },
    {
      "url": "https://www.w3.org/contact/"
    }
  ],
  "sameDomainEmailsOnly": true,
  "maxResults": 10,
  "maxPagesPerWebsite": 3
}
```

# Actor output Schema

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

One unique website with at least one publicly listed email, explicit phone or supported social profile. Includes source-page evidence. Export JSON, CSV or Excel.

## `summary` (type: `string`):

Per-website robots/access status, pages, warnings, counts and safety stops. Stored outside the billable dataset.

# 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": [
        {
            "url": "https://www.scrapingbee.com/"
        },
        {
            "url": "https://www.w3.org/contact/"
        }
    ]
};

// Run the Actor and wait for it to finish
const run = await client.actor("funny_ground/website-contact-social-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": [
        { "url": "https://www.scrapingbee.com/" },
        { "url": "https://www.w3.org/contact/" },
    ] }

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

```

## MCP server setup

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