# DACH Company Enrichment: Impressum, Register, VAT & Tech (`webify-lab/dach-company-enrichment`) Actor

Enrich German, Austrian and Swiss domains: company name, legal form, address, register number, VAT ID checked in VIES, tech stack and mail setup. One row per domain.

- **URL**: https://apify.com/webify-lab/dach-company-enrichment.md
- **Developed by:** [Batu T.](https://apify.com/webify-lab) (community)
- **Categories:** Lead generation, Business
- **Security:** Limited permissions
- **Stats:** 2 total users, 1 monthly users, 100.0% runs succeeded, 0 bookmarks
- **User rating**: No ratings yet

## Pricing

from $4.20 / 1,000 company enricheds

This Actor is paid per event. You are not charged for the Apify platform usage, but only a fixed price for specific events.
Since this Actor supports Apify Store discounts, the price gets lower the higher subscription plan you have.

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

## What's an Apify Actor?

An Actor is a serverless cloud program that runs on the Apify platform. It has two run modes.
In Batch mode, an Actor accepts a well-defined JSON input, performs an action which can take anything from a few seconds to a few hours,
and optionally produces a well-defined JSON output, datasets with results, or files in key-value store.
In Standby mode, an Actor provides a web server which can be used as a website, API, or an MCP server.

Apify vocabulary and the platform model are defined once, in the agent quickstart at https://apify.com/agents.md.

## How to integrate an Actor?

If asked about integration, you help developers integrate Actors into their projects.
You adapt to their stack and deliver integrations that are safe, well-documented, and production-ready.

Do not guess an integration path. Every one of them is in the agent quickstart at https://apify.com/agents.md: the Apify MCP server, Agent Skills with the Apify CLI, the JavaScript and Python clients, the REST API, and the account-free path for an agent with no human to sign in. It also carries the rule on stating cost before the first paid run.

For examples already wired to this Actor's own input schema, see the [API](#api) section below.

Each client library has reference documentation the quickstart does not restate: [JavaScript/TypeScript](https://docs.apify.com/api/client/js/docs.md) (`npm install apify-client`) and [Python](https://docs.apify.com/api/client/python/docs.md) (`pip install apify-client`).

# README

## DACH Company Enrichment: Impressum, Register, VAT & Tech

Give it a list of German, Austrian or Swiss domains and get back one flat company record per domain. The record combines the legal notice (Impressum) of the website, a live VAT ID check in the official EU VIES service, a tech stack summary of the homepage and the basic mail setup of the domain (MX, SPF, DMARC).

No directories, no commercial registers, no data brokers: every field comes from the company's own website, from EU VIES or from public DNS. That keeps results fresh and runs cheap.

### Output per domain

| field | example |
|---|---|
| `companyName`, `legalForm` | Muster Technik GmbH, GmbH |
| `street`, `postalCode`, `city`, `country` | Hauptstrasse 12, 63739, Aschaffenburg, DE |
| `managingDirectors` | \["Anna Beispiel"] |
| `phone`, `fax`, `email`, `emails` | as published in the Impressum |
| `registerType`, `registerNumber`, `registerCourt` | HRB, HRB 12345, Aschaffenburg |
| `uid` | Swiss company UID (CHE-...) |
| `vatId`, `vatStatus`, `vatRegisteredName`, `vatRegisteredAddress` | DE123456789, valid, name and address from VIES |
| `taxNumber`, `smallBusiness` | tax number, small business note (Paragraph 19 UStG) |
| `completeness` | share of core imprint fields found, 0 to 100 |
| `cms` | WordPress, TYPO3, Wix, Jimdo, Webflow and more |
| `shopSystem` | Shopify, Shopware, WooCommerce, JTL-Shop and more |
| `analytics`, `advertising` | for example Google Analytics 4, Meta Pixel |
| `consentTool` | Cookiebot, Usercentrics, Borlabs and more |
| `trackingWithoutConsentTool` | true when tracking or ad tags run but no consent tool was detected |
| `mxPresent`, `mxHosts` | whether the domain receives mail, and where |
| `spfPresent`, `spfPolicy` | SPF record and its all mechanism (-all, ~all, ?all, +all) |
| `dmarcPresent`, `dmarcPolicy` | none, quarantine or reject |
| `partial`, `partialReason` | see below |
| `error` | why a domain could not be processed |

### How a domain is processed

1. The homepage is fetched once. It is used both to find the Impressum link and to detect the tech stack.
2. The Impressum is fetched (or found under common paths such as `/impressum` and `/imprint`) and parsed. Third parties named on the same page, such as the hosting provider, are ignored.
3. A found DE or AT VAT ID is checked in EU VIES.
4. MX, SPF and DMARC are read with three DNS over HTTPS lookups.

No browser is used. A typical domain needs 6 to 8 small requests.

### Results, partial results and errors

- Complete record (`partial: false`): a company name or a register number was found. Only these are charged.
- Partial record (`partial: true`, with `partialReason`): the website answered, but no company could be identified, for example because there is no Impressum or it is rendered by JavaScript. Tech stack and mail fields are still included. Not charged.
- Error item (`error`): the input is not a valid domain or the website could not be reached. Not charged.

### Inputs

- `domains`: domains or URLs, duplicates are removed.
- `checkTechStack`, `checkMail`, `validateVat`: switch parts off if you do not need them.
- `respectRobotsTxt`: on by default.
- `proxyConfiguration`: optional, used only when a website blocks the direct request.

```json
{ "domains": ["webifysystems.de", "https://www.example.at"], "checkMail": true }
```

### Pricing

You pay per enriched company: a domain where a company name or register number was found. Partial records and errors are not charged.

### Limits

- Imprints that are only rendered by JavaScript, or published as an image or PDF, return a partial record.
- Register data is read as published in the Impressum. It is not checked against the commercial register.
- Swiss UIDs are returned but not validated, because Switzerland is not part of EU VIES.
- DKIM, TLS and security headers are not checked, to keep runs cheap.

### Data protection

Only public legal notices are read. Names and contact details in an Impressum are published by law, but your own use must still comply with GDPR, for example for direct marketing.

Not affiliated with the European Commission (VIES) or any company whose website is processed.

### FAQ

**What am I charged for?** One event per domain where a company name or a register number was found in the Impressum (`partial: false`). Partial records, error items and duplicate domains are not charged.

**Where does the data come from?** Only from the company's own website (homepage and Impressum), the EU VIES REST service for DE and AT VAT IDs, and public DNS over HTTPS (Google, Cloudflare as fallback) for MX, SPF and DMARC. No commercial register or data broker is queried.

**Do I need a proxy?** No. Requests go direct. If you set `proxyConfiguration`, a request that fails with HTTP 403, 429, 503 or a connection error is retried once through the proxy.

**What happens when a website cannot be read?** You get an error item with `input`, `domain`, `error` and `checkedAt`, for example when the website is not reachable or its robots.txt answers with a server error (treated as disallow all). If the site answers but no company can be identified, you get a partial record with `partialReason` instead.

**How many domains can one run handle?** Up to `maxDomains` (default 1000) after duplicates are removed, processed with `concurrency` 1 to 10 (default 5). No browser is used.

### Use with AI agents (MCP)

This Actor works as a tool for Claude, ChatGPT, Cursor and other MCP clients through the [Apify MCP server](https://docs.apify.com/platform/integrations/mcp). Add only this Actor:

```
https://mcp.apify.com?tools=webify-lab/dach-company-enrichment
```

On first use the server signs you in with OAuth. Alternatively send the header `Authorization: Bearer <APIFY_TOKEN>`. Agents on the default Apify MCP setup can also find this Actor with `search-actors` and run it with `call-actor`. Pricing is the same as in Apify Console: you pay per result.

# Actor input Schema

## `domains` (type: `array`):

Domains or URLs of German, Austrian or Swiss businesses, for example example.de or https://www.example.at/kontakt. Each domain is processed once.

## `checkTechStack` (type: `boolean`):

CMS or site builder, shop system, analytics, consent tool and ad pixels, read from the homepage that is fetched anyway. No extra request.

## `checkMail` (type: `boolean`):

Three DNS over HTTPS lookups per domain: MX records, SPF record and DMARC policy.

## `validateVat` (type: `boolean`):

Checks a found DE or AT VAT ID against the official EU VIES service. Swiss UIDs are not part of VIES. German VIES has short nightly maintenance windows, reported as unavailable.

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

Reads the site's robots.txt once and skips the homepage or imprint page when they are disallowed for all crawlers.

## `maxDomains` (type: `integer`):

Safety limit per run.

## `concurrency` (type: `integer`):

Domains processed at the same time.

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

Optional. Requests go out directly first; a website request that is blocked (HTTP 403, 429, 503 or a connection error) is retried once through this proxy.

## Actor input object example

```json
{
  "domains": [
    "webifysystems.de",
    "fastkey-schluesseldienst.de"
  ],
  "checkTechStack": true,
  "checkMail": true,
  "validateVat": true,
  "respectRobotsTxt": true,
  "maxDomains": 1000,
  "concurrency": 5,
  "proxyConfiguration": {
    "useApifyProxy": false
  }
}
```

# Actor output Schema

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

One flat item per domain: input, domain, website, impressumUrl, companyName, legalForm, street, postalCode, city, country, phone, fax, email, emails, managingDirectors, registerType, registerNumber, registerCourt, uid, vatId, vatStatus, vatRegisteredName, vatRegisteredAddress, taxNumber, smallBusiness, completeness, cms, shopSystem, analytics, advertising, consentTool, trackingWithoutConsentTool, mxPresent, mxHosts, spfPresent, spfPolicy, dmarcPresent, dmarcPolicy, partial, partialReason, checkedAt; or input, domain, error.

# 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 = {
    "domains": [
        "webifysystems.de",
        "fastkey-schluesseldienst.de"
    ],
    "proxyConfiguration": {
        "useApifyProxy": false
    }
};

// Run the Actor and wait for it to finish
const run = await client.actor("webify-lab/dach-company-enrichment").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 = {
    "domains": [
        "webifysystems.de",
        "fastkey-schluesseldienst.de",
    ],
    "proxyConfiguration": { "useApifyProxy": False },
}

# Run the Actor and wait for it to finish
run = client.actor("webify-lab/dach-company-enrichment").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 '{
  "domains": [
    "webifysystems.de",
    "fastkey-schluesseldienst.de"
  ],
  "proxyConfiguration": {
    "useApifyProxy": false
  }
}' |
apify call webify-lab/dach-company-enrichment --silent --output-dataset

```

## MCP server setup

```json
{
    "mcpServers": {
        "apify": {
            "type": "http",
            "url": "https://mcp.apify.com/?tools=fetch-actor-details,webify-lab/dach-company-enrichment"
        }
    }
}
```

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/XE2dhIDNkR60CIfJk/builds/7do7GE4EjjN7D8deg/openapi.json
