# Impressum Email Scraper (German Sites) (`sandy_yclept/impressum-email-scraper`) Actor

Scrape emails, phone numbers and social links from German websites' Impressum pages. Decodes obfuscated addresses, returns German phone numbers in E.164. Pay per contact found.

- **URL**: https://apify.com/sandy\_yclept/impressum-email-scraper.md
- **Developed by:** [Rafal Sav](https://apify.com/sandy_yclept) (community)
- **Categories:** Lead generation, Automation
- **Stats:** 2 total users, 1 monthly users, 100.0% runs succeeded, 0 bookmarks
- **User rating**: No ratings yet

## Pricing

Pay per event

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 a software tools running on the Apify platform, for all kinds of web data extraction and automation use cases.
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

### What does Impressum Email Scraper do?

**Impressum Email Scraper** extracts **emails, phone numbers and social profiles from German websites** by going straight to the page where German law puts them: the **Impressum**. Give it a list of `.de` domains and it returns one clean record per site — with **MX-validated emails**, **German phone numbers normalized to E.164** and de-duplicated social links.

German law (§ 5 TMG / § 18 MStV) requires almost every commercial website to publish a reachable contact — an address, a phone number and an email — on its Impressum page. That makes German sites the single richest source of business contact data on the web, and this Actor is tuned to read it.

It runs on the [Apify platform](https://apify.com): API access, scheduling, integrations (Make, Zapier, n8n), proxy rotation and run monitoring included.

### Why use it for German sites specifically?

- **The Impressum is crawled first.** Subpage discovery ranks `/impressum` above `/kontakt`, `/about` and everything else, so the legally mandated contact block is read even on sites whose homepage shows nothing.
- **German phone numbers come back usable.** Numbers written as `+49 (0)40 3007-0`, `040 30070` or `Tel.: 040/3007-0` are parsed with Google's libphonenumber into **E.164** (`+494030070`). The default phone region is preset to `DE`, so local-format numbers on `.com` domains of German companies are parsed correctly too.
- **Obfuscated addresses are decoded.** German publishers hide addresses aggressively: Cloudflare `data-cfemail` protection, HTML entities (`&#64;`), and `name [at] domain [dot] de`. All three are recovered.
- **Datenschutz as a fallback.** If a site has no usable Impressum, the privacy policy (`/datenschutz`) is crawled — the GDPR data-controller contact has to be published there.
- **You pay per contact found, not per page.** A site that yields nothing costs nothing.

### Use cases

- **B2B lead generation in the DACH market** — turn a list of German company domains into reachable inboxes and phone numbers.
- **Compliance and imprint checks** — verify that a portfolio of sites publishes a valid, reachable contact under § 5 TMG.
- **Agency prospecting** — scrape a niche (Handwerker, Kanzleien, Onlineshops) and get the details a directory listing does not carry.
- **Recruiting in DACH** — collect HR and careers contacts from employer sites.
- **Market research** — map which companies publish a phone number versus a form-only contact page.

### How to use it

1. Add your German domains under **Start URLs** (one record per URL is returned).
2. Optionally adjust **Max contact subpages** (default 6), the **Default phone region** (`DE`, or `AT` / `CH` for Austrian and Swiss sites), or switch **JavaScript rendering** to `auto` for sites that need a browser (raise run memory to 2048 MB first).
3. Click **Start** and download the results as JSON, CSV, Excel or HTML.

### Output

```json
{
  "domain": "https://www.beispiel.de",
  "status": "ok",
  "best_email": "kontakt@beispiel.de",
  "emails": [
    { "email": "kontakt@beispiel.de", "valid_mx": true, "role": true, "confidence": 0.85 },
    { "email": "datenschutz@beispiel.de", "valid_mx": true, "role": true, "confidence": 0.7 }
  ],
  "phones": ["+4940300700"],
  "socials": { "linkedin": ["https://linkedin.com/company/beispiel"] },
  "email_count": 2,
  "pages_crawled": 3,
  "rendered": false
}
````

| Field | Description |
|---|---|
| `domain` | The site the record is for. |
| `status` | `ok`, `no_contacts` (pages read, nothing published) or `unreachable` (site refused the request). |
| `best_email` | Highest-confidence address — a named person outranks a general inbox, which outranks a legal or technical mailbox. |
| `emails` | Every address found, each with `valid_mx`, `role` and a `confidence` score. |
| `phones` | Phone numbers in E.164. |
| `socials` | Profile URLs grouped by platform, de-duplicated (`twitter.com/x` counts once). |
| `pages_crawled` | How many pages were read for this site. |
| `rendered` | Whether a browser was needed. |

### Accuracy

The extraction engine is benchmarked against a hand-verified set of 32 real pages, German Impressum pages among them (heise.de, t3n.de, nazwa.pl and others), scored against ground truth read out of the raw HTML: **100% precision and 100% recall** on emails, phones and social profiles. Against the category incumbent on the same pages: emails 100% vs 94%, phone numbers 100% vs 0% usable (it returns unnormalized strings in an "uncertain" bucket).

On an uncurated list of 150 random company domains it returned an email for **73.3%** of them, against **54.0%** for the incumbent, at a lower cost per email found.

### How much does it cost?

You pay only for results:

- **Verified contact — $0.003** (~$3 per 1,000): one email or one phone number.
- **Social profile — $0.001** (~$1 per 1,000): one clean, de-duplicated profile link.
- **Empty sites — $0.** No contact, no charge.
- The Apify Free plan includes **$5 in monthly credits**, roughly a thousand domains.

### FAQ

#### Which sites does this work on?

Any website, but it is configured for German-language ones: Impressum-first crawling, `DE` phone parsing, `/datenschutz` fallback. For an international list use the general [Website Contact & Email Scraper](https://apify.com/sandy_yclept/website-contact-email-scraper) instead — same engine, neutral defaults.

#### Does it work for Austrian and Swiss sites?

Yes. Set **Default phone region** to `AT` or `CH` so local-format numbers are parsed correctly; the Impressum requirement exists in both countries.

#### Why did a site return nothing?

Check `status`. `no_contacts` means the pages were read and there was nothing to extract — rare for German sites, but it happens with form-only contact pages. `unreachable` means nothing could be downloaded; retry with `renderJs: auto` or a residential proxy. Neither is charged.

#### Is scraping Impressum data legal?

The Impressum exists precisely so that the contact is publicly reachable, and this Actor respects `robots.txt` and rate-limits its requests. What you do with the data is your responsibility: under GDPR you are the data controller, you need a lawful basis for outreach (§ 7 UWG restricts unsolicited commercial email in Germany), and you must honour opt-outs.

### Disclaimer

This Actor is a **tool**. You are the data controller for any personal data you collect and are responsible for complying with GDPR, UWG, the target site's Terms of Service and robots.txt. It does not build or sell contact databases.

### Support

Found a German site where contacts were missed? Open an issue on the **Issues** tab — accuracy reports shape the roadmap directly.

# Actor input Schema

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

List of German websites (domains or URLs) to pull Impressum contact details from. One record per URL is produced.

## `maxContactPages` (type: `integer`):

How many contact-like subpages to crawl per site on top of the homepage. German sites put the legally required contact on /impressum, and it is crawled first; the default leaves room for /kontakt and the privacy page too.

## `validateEmails` (type: `boolean`):

Check each discovered email against its domain's MX records and attach a confidence score. Turn off for a faster run without deliverability checks.

## `includeSocials` (type: `boolean`):

Extract LinkedIn, X/Twitter, Facebook, Instagram, YouTube and TikTok profile links (share/intent URLs are filtered out).

## `renderJs` (type: `string`):

Load pages in a real browser to reach contacts that are rendered by JavaScript. Off (default) is the fastest and cheapest. Auto scans without a browser first and only re-crawls a site in the browser when nothing was found — best accuracy/cost ratio. On always uses the browser. Auto and On require the run memory to be at least 2048 MB.

## `phoneRegion` (type: `string`):

ISO country code used to parse phone numbers written without an international prefix. Defaults to DE for German sites; change it for Austrian (AT) or Swiss (CH) targets.

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

Optional proxy for fetching pages. Apify Proxy requires a paid plan; when left disabled the Actor connects directly.

## Actor input object example

```json
{
  "startUrls": [
    {
      "url": "https://www.heise.de/"
    }
  ],
  "maxContactPages": 6,
  "validateEmails": true,
  "includeSocials": true,
  "renderJs": "off",
  "phoneRegion": "PL",
  "proxyConfiguration": {
    "useApifyProxy": false
  }
}
```

# Actor output Schema

## `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 = {
    "startUrls": [
        {
            "url": "https://www.heise.de/"
        }
    ]
};

// Run the Actor and wait for it to finish
const run = await client.actor("sandy_yclept/impressum-email-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.heise.de/" }] }

# Run the Actor and wait for it to finish
run = client.actor("sandy_yclept/impressum-email-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 '{
  "startUrls": [
    {
      "url": "https://www.heise.de/"
    }
  ]
}' |
apify call sandy_yclept/impressum-email-scraper --silent --output-dataset

```

## MCP server setup

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

```

## OpenAPI specification

```json
{
    "openapi": "3.0.1",
    "info": {
        "title": "Impressum Email Scraper (German Sites)",
        "description": "Scrape emails, phone numbers and social links from German websites' Impressum pages. Decodes obfuscated addresses, returns German phone numbers in E.164. Pay per contact found.",
        "version": "0.2",
        "x-build-id": "0t2UHSOTZbN0jVtV6"
    },
    "servers": [
        {
            "url": "https://api.apify.com/v2"
        }
    ],
    "paths": {
        "/acts/sandy_yclept~impressum-email-scraper/run-sync-get-dataset-items": {
            "post": {
                "operationId": "run-sync-get-dataset-items-sandy_yclept-impressum-email-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/sandy_yclept~impressum-email-scraper/runs": {
            "post": {
                "operationId": "runs-sync-sandy_yclept-impressum-email-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/sandy_yclept~impressum-email-scraper/run-sync": {
            "post": {
                "operationId": "run-sync-sandy_yclept-impressum-email-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",
                "required": [
                    "startUrls"
                ],
                "properties": {
                    "startUrls": {
                        "title": "Start URLs",
                        "type": "array",
                        "description": "List of German websites (domains or URLs) to pull Impressum contact details from. One record per URL is produced.",
                        "default": [
                            {
                                "url": "https://www.heise.de/"
                            }
                        ],
                        "items": {
                            "type": "object",
                            "required": [
                                "url"
                            ],
                            "properties": {
                                "url": {
                                    "type": "string",
                                    "title": "URL of a web page",
                                    "format": "uri"
                                }
                            }
                        }
                    },
                    "maxContactPages": {
                        "title": "Max contact subpages",
                        "minimum": 0,
                        "maximum": 20,
                        "type": "integer",
                        "description": "How many contact-like subpages to crawl per site on top of the homepage. German sites put the legally required contact on /impressum, and it is crawled first; the default leaves room for /kontakt and the privacy page too.",
                        "default": 6
                    },
                    "validateEmails": {
                        "title": "Validate emails (MX + scoring)",
                        "type": "boolean",
                        "description": "Check each discovered email against its domain's MX records and attach a confidence score. Turn off for a faster run without deliverability checks.",
                        "default": true
                    },
                    "includeSocials": {
                        "title": "Extract social profiles",
                        "type": "boolean",
                        "description": "Extract LinkedIn, X/Twitter, Facebook, Instagram, YouTube and TikTok profile links (share/intent URLs are filtered out).",
                        "default": true
                    },
                    "renderJs": {
                        "title": "JavaScript rendering",
                        "enum": [
                            "off",
                            "auto",
                            "on"
                        ],
                        "type": "string",
                        "description": "Load pages in a real browser to reach contacts that are rendered by JavaScript. Off (default) is the fastest and cheapest. Auto scans without a browser first and only re-crawls a site in the browser when nothing was found — best accuracy/cost ratio. On always uses the browser. Auto and On require the run memory to be at least 2048 MB.",
                        "default": "off"
                    },
                    "phoneRegion": {
                        "title": "Default phone region",
                        "type": "string",
                        "description": "ISO country code used to parse phone numbers written without an international prefix. Defaults to DE for German sites; change it for Austrian (AT) or Swiss (CH) targets.",
                        "default": "DE"
                    },
                    "proxyConfiguration": {
                        "title": "Proxy configuration",
                        "type": "object",
                        "description": "Optional proxy for fetching pages. Apify Proxy requires a paid plan; when left disabled the Actor connects directly.",
                        "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
                                    }
                                }
                            }
                        }
                    }
                }
            }
        }
    }
}
```
