# Impressum Scraper - German Company Data & B2B Leads (DE/AT/CH) (`paperlinenstudio/impressum-scraper`) Actor

Turn a list of German, Austrian or Swiss websites into structured company data from the legal notice (Impressum): company name, legal form, address, phone, email, VAT ID, commercial register court and number, managing directors. Finds the Impressum page automatically.

- **URL**: https://apify.com/paperlinenstudio/impressum-scraper.md
- **Developed by:** [Paper & Linen Studio](https://apify.com/paperlinenstudio) (community)
- **Categories:** Lead generation, Business, Automation
- **Stats:** 2 total users, 1 monthly users, 100.0% runs succeeded, 0 bookmarks
- **User rating**: No ratings yet

## Pricing

Pay per usage

This Actor is paid per platform usage. The Actor is free to use, and you only pay for the Apify platform usage, which gets cheaper the higher subscription plan you have.

Learn more: https://docs.apify.com/actors/running/actors-in-store.md#pay-per-usage

## 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

## Impressum Scraper – German Company Data & B2B Leads (DE/AT/CH)

Give it a list of **German, Austrian or Swiss websites** (or just domains) and get back **one clean row per company** with the data from its legal notice (*Impressum*): official company name, legal form, address, phone, email, VAT ID, commercial register court and number, and managing directors.

Every commercial website in Germany (§ 5 DDG), Austria (§ 5 ECG / § 25 MedienG) and Switzerland (UWG) must publish this information, so the Impressum is the most reliable public source for **verified company master data**, and much more accurate than guessing from the homepage.

### What you can use it for

- **B2B lead enrichment**: turn a list of domains from your CRM, a trade-fair exhibitor list or a Google Maps export into company records with the official name, address and VAT ID.
- **CRM data cleaning**: check that company names, legal forms and addresses in your CRM are current.
- **KYC / supplier checks**: collect VAT IDs (USt-IdNr. / UID) and register numbers (HRB, HRA, FN, CHE) to verify them later, e.g. with the EU VIES service.
- **Market research**: see which legal forms, cities or register courts are common in a niche.

### Features

- **Finds the Impressum automatically**: it scores links such as *Impressum*, *Imprint*, *Legal notice* and *Anbieterkennzeichnung* and falls back to common paths (`/impressum`, `/imprint`, …).
- **Cleans up the text first**: block-level line breaks, Cloudflare-protected emails and `(at)`/`(dot)` obfuscation are decoded, and wrong page encodings are fixed.
- **Extracts structured fields**: company name and legal form (GmbH, UG, AG, KG, GmbH & Co. KG, e.K., SE, e.V., Austrian and Swiss forms), street, ZIP, city, country, phone, fax, best email plus all emails, VAT ID (DE / ATU / CHE), register court, register type and number, and managing directors / board.
- **Skips sample and template data**, such as "Musterfirma" or DE123456789.
- **Detects bot-protection and challenge pages** and reports them in `error` instead of returning garbage.
- **Fast and cheap**: plain HTTP with no browser. About 10 websites take under 10 seconds at 256 MB memory.
- **Per-run SUMMARY** record with counts (found, with email, with VAT ID, …).

### Input

| Field | Description |
|---|---|
| `websites` | List of websites or domains, e.g. `tchibo.de`, `https://www.weleda.de` |
| `includePersonNames` | Extract managing director names (default `true`). Turn off for company-level data only. |
| `onlyFound` | Only save websites where an Impressum was found (default `false`) |
| `maxItems` | Stop after this many companies were found |
| `maxConcurrency` | Websites processed in parallel (default 10) |
| `timeoutSecs` | Timeout per request (default 20) |

```json
{"websites": ["tchibo.de", "weleda.de", "einhell.de"], "includePersonNames": true}
```

### Output (real example)

```json
{
  "website": "https://tchibo.de",
  "domain": "tchibo.de",
  "impressumUrl": "https://www.tchibo.de/c/service-impressum",
  "found": true,
  "companyName": "Tchibo GmbH",
  "legalForm": "GmbH",
  "street": "Überseering 18",
  "postalCode": "22297",
  "city": "Hamburg",
  "country": "DE",
  "phone": "+49 (0) 40 63 87 - 0",
  "fax": null,
  "email": "service@tchibo.de",
  "emails": [
    "service@tchibo.de"
  ],
  "vatId": "DE811164447",
  "registerCourt": "Amtsgericht Hamburg",
  "registerType": "HRB",
  "registerNumber": "43618",
  "managingDirectors": [
    "Erik Hofstädter",
    "Felix Albrecht",
    "Hamid Dastmalchian"
  ],
  "error": null,
  "scrapedAt": "2026-11-02T23:16:49+00:00"
}
```

When nothing is found, the row has `found: false` and an `error`, such as "No Impressum / legal notice page found (or the site needs JavaScript)" or "Blocked by bot protection".

Results can be exported as JSON, CSV, Excel or XML, or read through the Apify API.

In a test run on 12 well-known DACH brand websites, **10 of 12** were found, and almost all of those included an email, VAT ID and register number.

### Limitations

- Websites that render the Impressum **only with JavaScript**, or that block datacenter IPs, can return `found: false`.
- Impressum layouts vary a lot. Fields are extracted with heuristics, so check them before using them for anything legally relevant.
- The Actor does not verify VAT IDs or register entries. It only reads what the website publishes.

### Data protection (GDPR / DSGVO)

The Impressum is information that companies are **legally required to publish**. Managing director names are still personal data under the GDPR. If you do not need them, set `includePersonNames: false`. If you use the data for marketing, you are responsible for having a legal basis (e.g. Art. 6(1)(f) GDPR) and for respecting § 7 UWG: **no unsolicited advertising emails or calls without consent.** Use this tool for research, enrichment and verification, not for spam.

### Pricing

Free to use. You only pay for the Apify platform usage of your run, which is very low because no browser is used.

***

### Deutsch: Kurzbeschreibung

**Impressum Scraper**: Liste von Websites oder Domains rein, strukturierte Firmendaten aus dem Impressum raus:

- Firmenname und Rechtsform
- Straße, PLZ, Ort, Land
- Telefon, Fax, E-Mail
- USt-IdNr.
- Registergericht und Handelsregisternummer (HRB/HRA, FN, CHE)
- Geschäftsführer bzw. Vorstand

Typische Einsätze sind B2B-Lead-Anreicherung, CRM-Bereinigung, Lieferantenprüfung und Marktanalyse. Die Impressumsseite wird automatisch gefunden, und verschleierte E-Mails werden dekodiert. Personennamen lassen sich mit `includePersonNames: false` abschalten. Bitte beachten Sie DSGVO und § 7 UWG: keine unerlaubte Werbung.

# Actor input Schema

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

Company websites or bare domains (e.g. tchibo.de, https://www.weleda.de). The Actor opens the homepage, finds the Impressum / Imprint / Legal notice page and extracts the company data. One row per website.

## `includePersonNames` (type: `boolean`):

Extract names of managing directors / board members / owners (Geschäftsführer, Vorstand, Inhaber). Turn off if you only need company-level data and want to avoid processing personal names.

## `onlyFound` (type: `boolean`):

If on, websites where no Impressum could be found (or that block bots) are not saved to the dataset. They are still counted in the SUMMARY record.

## `maxItems` (type: `integer`):

Stop after this many websites with Impressum data have been found. Useful to limit cost on big lists.

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

How many websites are processed in parallel.

## `timeoutSecs` (type: `integer`):

Timeout for a single HTTP request.

## Actor input object example

```json
{
  "websites": [
    "tchibo.de",
    "weleda.de",
    "einhell.de"
  ],
  "includePersonNames": true,
  "onlyFound": false,
  "maxItems": 100000,
  "maxConcurrency": 10,
  "timeoutSecs": 20
}
```

# Actor output Schema

## `items` (type: `string`):

No description

## `summary` (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": [
        "tchibo.de",
        "weleda.de",
        "einhell.de"
    ]
};

// Run the Actor and wait for it to finish
const run = await client.actor("paperlinenstudio/impressum-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": [
        "tchibo.de",
        "weleda.de",
        "einhell.de",
    ] }

# Run the Actor and wait for it to finish
run = client.actor("paperlinenstudio/impressum-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 '{
  "websites": [
    "tchibo.de",
    "weleda.de",
    "einhell.de"
  ]
}' |
apify call paperlinenstudio/impressum-scraper --silent --output-dataset

```

## MCP server setup

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