# Impressum Extractor — HRB, Court, VAT ID (DE/AT/CH) (`northwestsouth/impressum-legal-entity-extractor`) Actor

Turns German, Austrian and Swiss imprints into structured legal identity: company name, legal form, register number, normalised register court, VAT ID with verified check digit, address and a § 5 DDG completeness check.

- **URL**: https://apify.com/northwestsouth/impressum-legal-entity-extractor.md
- **Developed by:** [NorthWestSouth Data](https://apify.com/northwestsouth) (community)
- **Categories:** Lead generation, Developer tools
- **Stats:** 2 total users, 1 monthly users, 100.0% runs succeeded, 1 bookmarks
- **User rating**: No ratings yet

## Pricing

from $20.00 / 1,000 imprint extracteds

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.

- **AI agents and MCP clients** — the [Apify MCP server](https://docs.apify.com/integrations/mcp.md) at `https://mcp.apify.com` (remote, streamable HTTP, OAuth on first use).
- **Agentic workflows and local Actor development** — [Agent Skills](https://apify.com/.well-known/agent-skills/index.json) with the [Apify CLI](https://docs.apify.com/cli/docs.md): `npm install -g apify-cli`, then `apify login`.
- **JavaScript/TypeScript projects** — the official [JS/TS client](https://docs.apify.com/api/client/js/docs.md): `npm install apify-client`.
- **Python projects** — the official [Python client](https://docs.apify.com/api/client/python/docs.md): `pip install apify-client`.
- **Any other language** — the [REST API](https://docs.apify.com/api/v2.md).

For usage examples, see the [API](#api) section below.

For more details, see Apify documentation as [Markdown index](https://docs.apify.com/llms.txt) and [Markdown full-text](https://docs.apify.com/llms-full.txt).

# README

## Impressum → Legal Entity Extractor (DE / AT / CH)

Give it German, Austrian or Swiss websites. Get back **who legally operates them** — company name, legal form, commercial register number, register court, VAT ID with a verified check digit, and the registered address.

Every other imprint tool in this store returns *contact details*: an email, a phone number, a "decision maker". This one returns the **legal identity** — the part a KYB check, an invoice, a supplier onboarding or a compliance review actually needs.

### What you get per site

| Field | Example |
|---|---|
| `company_name` | Händlerbund Marketplace GmbH |
| `legal_form` | GmbH · UG (haftungsbeschränkt) · GmbH & Co. KG · AG · e.K. · GbR · eG · e.V. … |
| `register_type` / `register_number` | `HRB` / `HRB 36368` |
| `register_court` | Leipzig — **normalised against the official list of ~120 German registry courts**, so "AG Charlottenburg" and "Amtsgericht Berlin-Charlottenburg" become the same value |
| `register_court_verified` | `true` when the court matched the official list |
| `vat_id` + `vat_id_checksum_valid` | `DE324949675`, check digit computed offline |
| `street`, `postal_code`, `city`, `country` | Kohlgartenstraße 11-13, 04315 Leipzig, DE |
| `represented_by` | Managing director / board (see the personal-data section below) |
| `email`, `emails`, `phone` | Contact channels from the imprint |
| `supervisory_authority`, `chamber` | For regulated trades |
| `ddg_compliance` | Which § 5 DDG disclosures are present, which are missing |
| `imprint_confidence` | `high` / `medium` / `low`, so you can filter |

### Measured coverage — read this before you run it

Tested against **25 real German websites**:

- **60% yielded a complete legal-entity record.** The other 40% failed and **cost nothing**.
- Of the successful extractions: **legal form 100%, register number 100%, street and city 100%, company name 93%, VAT ID 93%, register court 80%** (92% of those verified against the official court list), represented\_by 53%, email 80%, phone 33%.
- **All 14 German VAT IDs found passed the offline check-digit test.**

**Why the 40% fail:** large retailers increasingly render their legal pages with JavaScript. Sites like dm.de and rossmann.de serve a 3–11 KB shell containing no legal text at all; conrad.de serves a 150 KB page whose imprint data is loaded afterwards. This actor reads static HTML — no browser, no proxies — so those sites are reported as failures rather than guessed at. If you need JS rendering, use a browser-based tool; it will cost more per site and run far slower.

**Shopify stores are excluded by default.** They keep their imprint under `/policies/`, which Shopify's own robots.txt disallows crawling. With `respectRobotsTxt` on (the default), those sites are reported as failures. That is a deliberate choice, not an oversight.

### You are never charged twice — and never for a failure

- A domain extracted in an earlier run is skipped and **not charged again**, across all runs.
- A site with no reachable imprint, or one where no legal-entity data could be extracted, goes to a separate `FAILED-URLS` dataset with the reason — **free**.
- No hidden row limits.

### Personal data: the default is restraint

An imprint for a GmbH names a managing director acting in a professional capacity. An imprint for a **sole trader** names a private individual, frequently at a home address. Those are not the same risk, so this actor treats them differently:

- Companies: `represented_by` is included.
- Sole traders (`e.K.`, Einzelunternehmen): the personal name is **suppressed by default**, and the record is flagged `natural_person_suppressed: true`.
- Set `includeNaturalPersons: true` only if you have a lawful basis under GDPR Art. 6 and can meet the Art. 14 information duty. Regulators have fined bulk extraction of this exact kind of data.

### Why this data is fair to use

§ 5 DDG (Germany), § 5 ECG (Austria) and Art. 3(1)(s) UWG (Switzerland) **require** every commercial website to publish these details permanently and without barriers, precisely so the operator can be identified. There is no register to license, no database right, no third-party terms of service. The company publishes this about itself, by law.

This actor reads each site's own imprint page, respects `robots.txt` by default, and sends one polite request per site.

### Input

```json
{
  "urls": ["haendlerbund.de", "thomann.de", "mymuesli.com"],
  "includeNaturalPersons": false,
  "respectRobotsTxt": true
}
```

### Example output

```json
{
  "url": "haendlerbund.de",
  "company_name": "Händlerbund Marketplace GmbH",
  "legal_form": "GmbH",
  "register_type": "HRB",
  "register_number": "HRB 36368",
  "register_court": "Leipzig",
  "register_court_verified": true,
  "vat_id": "DE324949675",
  "vat_id_checksum_valid": true,
  "street": "Kohlgartenstraße 11-13",
  "postal_code": "04315",
  "city": "Leipzig",
  "represented_by": "Tim Arlt",
  "email": "info@haendlerbund.de",
  "imprint_confidence": "high",
  "ddg_compliance": { "complete": false, "missing_fields": ["contact_phone_or_form"] }
}
```

### A note on the VAT check digit

The check digit is computed **offline** using the official German algorithm. That confirms the number is structurally valid — it does **not** confirm the ID is registered and active. The EU's VIES service, which could confirm that, forbids retransmission of its results, so it is deliberately not used here.

### Pricing

Pay per **successfully extracted imprint**. Failures and repeats are free.

### Support

A site that should work but doesn't, or a field parsed wrongly? [Open an issue](https://console.apify.com/actors) — parsing errors are treated as bugs and fixed.

# Actor input Schema

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

Bare domains (thomann.de), full URLs or subdomains. Duplicates and www variants are merged, so you never pay twice for the same site.

## `includeNaturalPersons` (type: `boolean`):

OFF by default. When the imprint identifies a sole trader (e.K., Einzelunternehmen), the personal name is suppressed — that is a private individual, often at a home address. Managing directors of companies are always included, since they are named in a professional capacity. Turn this on only if you have a lawful basis under GDPR Art. 6 and can meet the Art. 14 information duty.

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

ON by default. Note that Shopify's standard robots.txt disallows /policies/, where Shopify stores keep their imprint — those sites will be reported as failures (and not charged) while this is on.

## `outputFields` (type: `array`):

Leave empty for everything. Otherwise name the fields you want, e.g. company\_name, register\_number, vat\_id.

## `chargeForPreviouslyAnalyzed` (type: `boolean`):

OFF by default: domains extracted in an earlier run are skipped and NOT charged again.

## Actor input object example

```json
{
  "urls": [
    "haendlerbund.de",
    "mymuesli.com"
  ],
  "includeNaturalPersons": false,
  "respectRobotsTxt": true,
  "outputFields": [],
  "chargeForPreviouslyAnalyzed": false
}
```

# 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 = {
    "urls": [
        "haendlerbund.de",
        "mymuesli.com"
    ],
    "outputFields": []
};

// Run the Actor and wait for it to finish
const run = await client.actor("northwestsouth/impressum-legal-entity-extractor").call(input);

// Fetch and print Actor results from the run's dataset (if any)
console.log('Results from dataset');
console.log(`💾 Check your data here: https://console.apify.com/storage/datasets/${run.defaultDatasetId}`);
const { items } = await client.dataset(run.defaultDatasetId).listItems();
items.forEach((item) => {
    console.dir(item);
});

// 📚 Want to learn more 📖? Go to → https://docs.apify.com/api/client/js/docs

```

## Python example

```python
from apify_client import ApifyClient

# Initialize the ApifyClient with your Apify API token
# Replace '<YOUR_API_TOKEN>' with your token.
client = ApifyClient("<YOUR_API_TOKEN>")

# Prepare the Actor input
run_input = {
    "urls": [
        "haendlerbund.de",
        "mymuesli.com",
    ],
    "outputFields": [],
}

# Run the Actor and wait for it to finish
run = client.actor("northwestsouth/impressum-legal-entity-extractor").call(run_input=run_input)

# Fetch and print Actor results from the run's dataset (if there are any)
print("💾 Check your data here: https://console.apify.com/storage/datasets/" + run["defaultDatasetId"])
for item in client.dataset(run["defaultDatasetId"]).iterate_items():
    print(item)

# 📚 Want to learn more 📖? Go to → https://docs.apify.com/api/client/python/docs/quick-start

```

## CLI example

```bash
echo '{
  "urls": [
    "haendlerbund.de",
    "mymuesli.com"
  ],
  "outputFields": []
}' |
apify call northwestsouth/impressum-legal-entity-extractor --silent --output-dataset

```

## MCP server setup

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

```

## OpenAPI specification

Download the OpenAPI definition: https://api.apify.com/v2/actors/vZGykNwUiLGmkUk63/builds/TS5ccmYN3iG4YaCFw/openapi.json
