# Contact Details Scraper (`dami_studio/contact-details-scraper`) Actor

Extract public emails, phones, social profiles, addresses, contact forms, and organization or person data from one or many websites. Fast HTTP crawling, same-site limits, robots.txt support, optional proxy, and no charges for empty or failed sites.

- **URL**: https://apify.com/dami\_studio/contact-details-scraper.md
- **Developed by:** [Dami's Studio](https://apify.com/dami_studio) (community)
- **Categories:** Lead generation, Automation, Developer tools
- **Stats:** 2 total users, 1 monthly users, 100.0% runs succeeded, 0 bookmarks
- **User rating**: No ratings yet

## Pricing

$1.50 / 1,000 websites

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/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.

In JavaScript/TypeScript projects, use official [JavaScript/TypeScript client](https://docs.apify.com/api/client/js/docs.md):

```bash
npm install apify-client
```

In Python projects, use official [Python client library](https://docs.apify.com/api/client/python/docs.md):

```bash
pip install apify-client
```

In shell scripts, use [Apify CLI](https://docs.apify.com/cli/docs.md):

````bash
# MacOS / Linux
curl -fsSL https://apify.com/install-cli.sh | bash
# Windows
irm https://apify.com/install-cli.ps1 | iex
```bash

In AI frameworks, you might use the [Apify MCP server](https://docs.apify.com/integrations/mcp.md).

If your project is in a different language, use 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

## Contact Details Scraper

Extract public contact information from one website or a list of websites. The Actor follows a small set of high-value, same-site pages and returns one consolidated record per site.

The default crawler uses fast HTTP requests rather than a browser. It is designed for predictable cost at a planned pay-per-result price of **$0.0015 per successful site**, below the current $0.002 competitor baseline. Empty, blocked, invalid, robots-disallowed, and no-contact sites produce an uncharged diagnostic row.

### What it extracts

- Public email addresses, including `mailto:` links and common `[at]` / `[dot]` obfuscation
- Phone numbers from `tel:` links and visible page text, with optional country normalization
- LinkedIn, Facebook, Instagram, X, YouTube, TikTok, Pinterest, GitHub, Threads, and Bluesky links
- Visible and JSON-LD postal addresses
- Contact forms with action, method, field names, and field types
- JSON-LD Organization, LocalBusiness, and Person data
- Website title and meta description
- Every source page for every extracted value
- Per-page crawl metadata and clear error diagnostics

The crawler prioritizes the home, contact, about, team, company, legal, privacy, terms, and impressum pages. It also discovers equivalent pages from link text and paths.

### Input

| Field | Type | Default | Description |
|---|---|---:|---|
| `websites` | string array | Apify website in UI | Domains or full URLs. Values without a scheme use HTTPS. |
| `startUrls` | request-list sources | empty | Alternative Apify-compatible URL input. Can be combined with `websites`. |
| `maxPagesPerSite` | integer | `6` | Maximum page attempts per site, from 1 to 20. |
| `maxConcurrency` | integer | `5` | Websites processed in parallel, from 1 to 20. |
| `requestTimeoutSecs` | integer | `12` | Timeout for each HTTP request. |
| `maxResponseSizeKb` | integer | `1536` | Maximum downloaded HTML size per page. |
| `respectRobotsTxt` | boolean | `true` | Skip pages disallowed for the Actor user agent. |
| `defaultCountry` | string | empty | Optional two-letter country code for local phone numbers, such as `US`, `GB`, or `CA`. |
| `proxyConfiguration` | proxy | off | Optional Apify or custom proxy. Direct HTTP is the profitable default. |

Example:

```json
{
  "websites": [
    "apify.com",
    "https://www.example.org"
  ],
  "maxPagesPerSite": 6,
  "respectRobotsTxt": true,
  "proxyConfiguration": {
    "useApifyProxy": false
  }
}
````

`startUrls` also accepts objects:

```json
{
  "startUrls": [
    { "url": "https://www.apify.com" },
    { "url": "https://example.org/contact" }
  ]
}
```

### Output

One successful row is stored for each site with useful public contact data:

```json
{
  "ok": true,
  "siteUrl": "https://example.org/",
  "requestedUrl": "https://example.org/",
  "domain": "example.org",
  "title": "Example Organization",
  "description": "Example website description.",
  "emails": [
    {
      "email": "hello@example.org",
      "sourcePages": [
        "https://example.org/contact"
      ]
    }
  ],
  "phones": [
    {
      "phone": "+1 202 555 0100",
      "e164": "+12025550100",
      "country": "US",
      "sourcePages": [
        "https://example.org/contact"
      ]
    }
  ],
  "socialLinks": [
    {
      "platform": "linkedin",
      "url": "https://www.linkedin.com/company/example",
      "sourcePages": [
        "https://example.org/about"
      ]
    }
  ],
  "addresses": [],
  "contactForms": [],
  "jsonLdOrganizations": [],
  "jsonLdPeople": [],
  "sourcePages": [
    "https://example.org/contact",
    "https://example.org/about"
  ],
  "crawledPages": [
    {
      "url": "https://example.org/",
      "status": 200,
      "title": "Example Organization",
      "contactsFound": 3
    }
  ],
  "pagesCrawled": 4,
  "pagesAttempted": 6,
  "emailCount": 1,
  "phoneCount": 1,
  "socialLinkCount": 1,
  "addressCount": 0,
  "contactFormCount": 0,
  "robotsTxtRespected": true,
  "pageErrors": []
}
```

Values contain their own `sourcePages`, which makes the result easier to verify than a flat list of contacts.

### Billing and diagnostics

The code emits the pay-per-event event `site` once, and only after a real successful row has been stored. The intended future event price is **$0.0015 per site**.

These rows are never charged:

- `_sample: true`: empty input preview used by Apify automated tests
- `BAD_INPUT` or `UNSAFE_URL`: invalid or blocked target
- `NO_CONTACTS`: pages loaded, but no useful public contact signal was found
- `ROBOTS_DENIED`: relevant pages were excluded by robots.txt
- `BLOCKED`, `RATE_LIMITED`, `TIMEOUT`, `NETWORK`, or other request errors

Each requested site is isolated. One blocked or invalid site does not fail the rest of the run, and expected per-site failures exit successfully with diagnostic data.

### Security

The Actor is designed for user-supplied URLs:

- Only `http://` and `https://` are accepted.
- URL credentials are rejected.
- Localhost and local network hostnames are rejected.
- Loopback, private, link-local, carrier-grade NAT, multicast, documentation, benchmark, unspecified, and reserved IP ranges are rejected.
- Every hostname and every redirect is resolved and validated.
- Direct requests use a DNS lookup guard at connection time.
- Redirects are manual, revalidated, and limited to the requested site.
- Crawling is limited by site, page count, timeout, and response body size.
- Binary and common document URLs are not crawled.

When a proxy is enabled, the destination is still resolved and validated before the proxy request. Direct mode provides the strongest DNS pinning and is the recommended default.

### Robots.txt

`respectRobotsTxt` is enabled by default. The Actor fetches each site's `robots.txt` and checks every candidate URL against its own user agent. If robots.txt is unavailable, normal public-page crawling continues. Set the option to `false` only when you have permission and a specific reason.

### Proxies and profitability

Most public company sites do not need residential proxies, so proxy use is off by default. This keeps the planned `$0.0015/site` price profitable:

- 512 MiB default memory
- no browser startup
- bounded HTTP responses
- six page attempts by default
- site-level concurrency
- successful-result-only billing

Enable a datacenter or residential proxy only for sites that block direct cloud requests. Residential proxy bandwidth can cost more than the result price on heavy pages, so it should not be the default for this Actor.

### JavaScript-heavy websites

This version intentionally does not launch a browser. Browser rendering would make the planned `$0.0015/site` price unreliable when several pages need JavaScript and residential bandwidth. Many modern sites still expose contact details in server-rendered HTML, metadata, JSON-LD, or footer links, which this Actor extracts.

For a fully client-rendered site, use its public contact page as the start URL or enable a proxy if the issue is IP blocking rather than rendering. A browser fallback should only be added with a separate higher-priced event after measured cloud cost proves it remains profitable.

### Run locally

Requires Node.js 20 or newer:

```bash
npm ci
npm test
npm start
```

For local Actor input, place `INPUT.json` in the default Apify key-value store or run with the Apify CLI. Results are written to the default dataset.

### Responsible use

Extract only public business contact information you are allowed to collect and process. Follow website terms, robots rules, privacy law, anti-spam law, and data retention requirements applicable to your use case. The Actor does not bypass logins or access controls.

# Actor input Schema

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

Domain names or full website URLs, one per line. Values without a scheme use HTTPS.

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

Alternative URL input compatible with Apify request-list sources. You can combine it with Websites.

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

Maximum same-site HTML pages to fetch for each website. Contact, about, team, and legal pages are prioritized.

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

How many websites to process in parallel. Each website is crawled sequentially to stay polite and predictable.

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

Maximum time for an individual HTTP request, in seconds.

## `maxResponseSizeKb` (type: `integer`):

Maximum HTML response body size per page in KiB. Oversized pages are skipped without charging.

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

When enabled, pages disallowed for this Actor's user agent are not crawled.

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

Optional ISO 3166-1 alpha-2 country code used to normalize local phone numbers, for example US, GB, or CA.

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

Optional. Proxy use is off by default because most public business websites work over direct HTTP. Enable Apify Proxy when target sites block cloud IPs.

## Actor input object example

```json
{
  "websites": [
    "example.com",
    "https://www.apify.com"
  ],
  "startUrls": [
    {
      "url": "https://www.apify.com"
    }
  ],
  "maxPagesPerSite": 6,
  "maxConcurrency": 5,
  "requestTimeoutSecs": 12,
  "maxResponseSizeKb": 1536,
  "respectRobotsTxt": true,
  "proxyConfiguration": {
    "useApifyProxy": false
  }
}
```

# Actor output Schema

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

Consolidated site records in the default 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 = {
    "websites": [
        "https://www.apify.com"
    ]
};

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

# Run the Actor and wait for it to finish
run = client.actor("dami_studio/contact-details-scraper").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": [
    "https://www.apify.com"
  ]
}' |
apify call dami_studio/contact-details-scraper --silent --output-dataset

```

## MCP server setup

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

```

## OpenAPI specification

```json
{
    "openapi": "3.0.1",
    "info": {
        "title": "Contact Details Scraper",
        "description": "Extract public emails, phones, social profiles, addresses, contact forms, and organization or person data from one or many websites. Fast HTTP crawling, same-site limits, robots.txt support, optional proxy, and no charges for empty or failed sites.",
        "version": "0.1",
        "x-build-id": "rxw0KyaYwDPrBTpCk"
    },
    "servers": [
        {
            "url": "https://api.apify.com/v2"
        }
    ],
    "paths": {
        "/acts/dami_studio~contact-details-scraper/run-sync-get-dataset-items": {
            "post": {
                "operationId": "run-sync-get-dataset-items-dami_studio-contact-details-scraper",
                "x-openai-isConsequential": false,
                "summary": "Executes an Actor, waits for its completion, and returns Actor's dataset items in response.",
                "tags": [
                    "Run Actor"
                ],
                "requestBody": {
                    "required": true,
                    "content": {
                        "application/json": {
                            "schema": {
                                "$ref": "#/components/schemas/inputSchema"
                            }
                        }
                    }
                },
                "parameters": [
                    {
                        "name": "token",
                        "in": "query",
                        "required": true,
                        "schema": {
                            "type": "string"
                        },
                        "description": "Enter your Apify token here"
                    }
                ],
                "responses": {
                    "200": {
                        "description": "OK"
                    }
                }
            }
        },
        "/acts/dami_studio~contact-details-scraper/runs": {
            "post": {
                "operationId": "runs-sync-dami_studio-contact-details-scraper",
                "x-openai-isConsequential": false,
                "summary": "Executes an Actor and returns information about the initiated run in response.",
                "tags": [
                    "Run Actor"
                ],
                "requestBody": {
                    "required": true,
                    "content": {
                        "application/json": {
                            "schema": {
                                "$ref": "#/components/schemas/inputSchema"
                            }
                        }
                    }
                },
                "parameters": [
                    {
                        "name": "token",
                        "in": "query",
                        "required": true,
                        "schema": {
                            "type": "string"
                        },
                        "description": "Enter your Apify token here"
                    }
                ],
                "responses": {
                    "200": {
                        "description": "OK",
                        "content": {
                            "application/json": {
                                "schema": {
                                    "$ref": "#/components/schemas/runsResponseSchema"
                                }
                            }
                        }
                    }
                }
            }
        },
        "/acts/dami_studio~contact-details-scraper/run-sync": {
            "post": {
                "operationId": "run-sync-dami_studio-contact-details-scraper",
                "x-openai-isConsequential": false,
                "summary": "Executes an Actor, waits for completion, and returns the OUTPUT from Key-value store in response.",
                "tags": [
                    "Run Actor"
                ],
                "requestBody": {
                    "required": true,
                    "content": {
                        "application/json": {
                            "schema": {
                                "$ref": "#/components/schemas/inputSchema"
                            }
                        }
                    }
                },
                "parameters": [
                    {
                        "name": "token",
                        "in": "query",
                        "required": true,
                        "schema": {
                            "type": "string"
                        },
                        "description": "Enter your Apify token here"
                    }
                ],
                "responses": {
                    "200": {
                        "description": "OK"
                    }
                }
            }
        }
    },
    "components": {
        "schemas": {
            "inputSchema": {
                "type": "object",
                "properties": {
                    "websites": {
                        "title": "Websites",
                        "type": "array",
                        "description": "Domain names or full website URLs, one per line. Values without a scheme use HTTPS.",
                        "items": {
                            "type": "string"
                        }
                    },
                    "startUrls": {
                        "title": "Start URLs",
                        "type": "array",
                        "description": "Alternative URL input compatible with Apify request-list sources. You can combine it with Websites.",
                        "items": {
                            "type": "object",
                            "required": [
                                "url"
                            ],
                            "properties": {
                                "url": {
                                    "type": "string",
                                    "title": "URL of a web page",
                                    "format": "uri"
                                }
                            }
                        }
                    },
                    "maxPagesPerSite": {
                        "title": "Maximum pages per site",
                        "minimum": 1,
                        "maximum": 20,
                        "type": "integer",
                        "description": "Maximum same-site HTML pages to fetch for each website. Contact, about, team, and legal pages are prioritized.",
                        "default": 6
                    },
                    "maxConcurrency": {
                        "title": "Maximum concurrent sites",
                        "minimum": 1,
                        "maximum": 20,
                        "type": "integer",
                        "description": "How many websites to process in parallel. Each website is crawled sequentially to stay polite and predictable.",
                        "default": 5
                    },
                    "requestTimeoutSecs": {
                        "title": "Request timeout",
                        "minimum": 3,
                        "maximum": 45,
                        "type": "integer",
                        "description": "Maximum time for an individual HTTP request, in seconds.",
                        "default": 12
                    },
                    "maxResponseSizeKb": {
                        "title": "Maximum response size",
                        "minimum": 128,
                        "maximum": 5120,
                        "type": "integer",
                        "description": "Maximum HTML response body size per page in KiB. Oversized pages are skipped without charging.",
                        "default": 1536
                    },
                    "respectRobotsTxt": {
                        "title": "Respect robots.txt",
                        "type": "boolean",
                        "description": "When enabled, pages disallowed for this Actor's user agent are not crawled.",
                        "default": true
                    },
                    "defaultCountry": {
                        "title": "Default phone country",
                        "pattern": "^[A-Za-z]{2}$",
                        "type": "string",
                        "description": "Optional ISO 3166-1 alpha-2 country code used to normalize local phone numbers, for example US, GB, or CA."
                    },
                    "proxyConfiguration": {
                        "title": "Proxy",
                        "type": "object",
                        "description": "Optional. Proxy use is off by default because most public business websites work over direct HTTP. Enable Apify Proxy when target sites block cloud IPs.",
                        "default": {
                            "useApifyProxy": false
                        }
                    }
                }
            },
            "runsResponseSchema": {
                "type": "object",
                "properties": {
                    "data": {
                        "type": "object",
                        "properties": {
                            "id": {
                                "type": "string"
                            },
                            "actId": {
                                "type": "string"
                            },
                            "userId": {
                                "type": "string"
                            },
                            "startedAt": {
                                "type": "string",
                                "format": "date-time",
                                "example": "2025-01-08T00:00:00.000Z"
                            },
                            "finishedAt": {
                                "type": "string",
                                "format": "date-time",
                                "example": "2025-01-08T00:00:00.000Z"
                            },
                            "status": {
                                "type": "string",
                                "example": "READY"
                            },
                            "meta": {
                                "type": "object",
                                "properties": {
                                    "origin": {
                                        "type": "string",
                                        "example": "API"
                                    },
                                    "userAgent": {
                                        "type": "string"
                                    }
                                }
                            },
                            "stats": {
                                "type": "object",
                                "properties": {
                                    "inputBodyLen": {
                                        "type": "integer",
                                        "example": 2000
                                    },
                                    "rebootCount": {
                                        "type": "integer",
                                        "example": 0
                                    },
                                    "restartCount": {
                                        "type": "integer",
                                        "example": 0
                                    },
                                    "resurrectCount": {
                                        "type": "integer",
                                        "example": 0
                                    },
                                    "computeUnits": {
                                        "type": "integer",
                                        "example": 0
                                    }
                                }
                            },
                            "options": {
                                "type": "object",
                                "properties": {
                                    "build": {
                                        "type": "string",
                                        "example": "latest"
                                    },
                                    "timeoutSecs": {
                                        "type": "integer",
                                        "example": 300
                                    },
                                    "memoryMbytes": {
                                        "type": "integer",
                                        "example": 1024
                                    },
                                    "diskMbytes": {
                                        "type": "integer",
                                        "example": 2048
                                    }
                                }
                            },
                            "buildId": {
                                "type": "string"
                            },
                            "defaultKeyValueStoreId": {
                                "type": "string"
                            },
                            "defaultDatasetId": {
                                "type": "string"
                            },
                            "defaultRequestQueueId": {
                                "type": "string"
                            },
                            "buildNumber": {
                                "type": "string",
                                "example": "1.0.0"
                            },
                            "containerUrl": {
                                "type": "string"
                            },
                            "usage": {
                                "type": "object",
                                "properties": {
                                    "ACTOR_COMPUTE_UNITS": {
                                        "type": "integer",
                                        "example": 0
                                    },
                                    "DATASET_READS": {
                                        "type": "integer",
                                        "example": 0
                                    },
                                    "DATASET_WRITES": {
                                        "type": "integer",
                                        "example": 0
                                    },
                                    "KEY_VALUE_STORE_READS": {
                                        "type": "integer",
                                        "example": 0
                                    },
                                    "KEY_VALUE_STORE_WRITES": {
                                        "type": "integer",
                                        "example": 1
                                    },
                                    "KEY_VALUE_STORE_LISTS": {
                                        "type": "integer",
                                        "example": 0
                                    },
                                    "REQUEST_QUEUE_READS": {
                                        "type": "integer",
                                        "example": 0
                                    },
                                    "REQUEST_QUEUE_WRITES": {
                                        "type": "integer",
                                        "example": 0
                                    },
                                    "DATA_TRANSFER_INTERNAL_GBYTES": {
                                        "type": "integer",
                                        "example": 0
                                    },
                                    "DATA_TRANSFER_EXTERNAL_GBYTES": {
                                        "type": "integer",
                                        "example": 0
                                    },
                                    "PROXY_RESIDENTIAL_TRANSFER_GBYTES": {
                                        "type": "integer",
                                        "example": 0
                                    },
                                    "PROXY_SERPS": {
                                        "type": "integer",
                                        "example": 0
                                    }
                                }
                            },
                            "usageTotalUsd": {
                                "type": "number",
                                "example": 0.00005
                            },
                            "usageUsd": {
                                "type": "object",
                                "properties": {
                                    "ACTOR_COMPUTE_UNITS": {
                                        "type": "integer",
                                        "example": 0
                                    },
                                    "DATASET_READS": {
                                        "type": "integer",
                                        "example": 0
                                    },
                                    "DATASET_WRITES": {
                                        "type": "integer",
                                        "example": 0
                                    },
                                    "KEY_VALUE_STORE_READS": {
                                        "type": "integer",
                                        "example": 0
                                    },
                                    "KEY_VALUE_STORE_WRITES": {
                                        "type": "number",
                                        "example": 0.00005
                                    },
                                    "KEY_VALUE_STORE_LISTS": {
                                        "type": "integer",
                                        "example": 0
                                    },
                                    "REQUEST_QUEUE_READS": {
                                        "type": "integer",
                                        "example": 0
                                    },
                                    "REQUEST_QUEUE_WRITES": {
                                        "type": "integer",
                                        "example": 0
                                    },
                                    "DATA_TRANSFER_INTERNAL_GBYTES": {
                                        "type": "integer",
                                        "example": 0
                                    },
                                    "DATA_TRANSFER_EXTERNAL_GBYTES": {
                                        "type": "integer",
                                        "example": 0
                                    },
                                    "PROXY_RESIDENTIAL_TRANSFER_GBYTES": {
                                        "type": "integer",
                                        "example": 0
                                    },
                                    "PROXY_SERPS": {
                                        "type": "integer",
                                        "example": 0
                                    }
                                }
                            }
                        }
                    }
                }
            }
        }
    }
}
```
