# German Website Check for Impressum, Datenschutz, Cookies, BFSG (`infinit_bubulus/german-website-compliance-check`) Actor

Checks German websites for Impressum details, a privacy policy link, cookie consent and trackers, outdated legal references and basic accessibility signals. Each website gets a score and its top findings in German and English. No personal data in the output.

- **URL**: https://apify.com/infinit\_bubulus/german-website-compliance-check.md
- **Developed by:** [Infinityware](https://apify.com/infinit_bubulus) (community)
- **Stats:** 2 total users, 1 monthly users, 100.0% runs succeeded, 0 bookmarks
- **User rating**: No ratings yet

## Pricing

from $10.00 / 1,000 website checkeds

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

## German Website Check: Impressum, Datenschutz, Cookies, BFSG

Check a list of German websites for the legal and technical basics in one run: **Impressum** signals (§ 5 DDG), **Datenschutzerklärung**, **cookie consent and trackers**, **outdated legal references** (TMG, OS platform, Privacy Shield and more), the **accessibility statement** under the BFSG and basic **WCAG accessibility signals**. Every website gets a score, its three most important findings in German and English, and a list of issues with severity and evidence.

**No personal data in the output.** Names, addresses, e-mail addresses and phone numbers on a page are only used to set yes/no flags. They never appear in the results.

### What it checks

| Area | Checks |
|---|---|
| Impressum | Link on the start page (also an Impressum section on a one-pager), page loads (no 404), postal code and city, e-mail (also obfuscated or behind Cloudflare e-mail protection), phone or contact form, register details and authorised representative for the legal form found on the provider line |
| Datenschutz | Link on the start page (cookie-settings buttons do not count), page loads |
| Unlinked legal pages | If the start page has no link: sitemap and usual addresses such as `/impressum`, so you see "page exists but is not linked" instead of "missing" |
| Outdated references | § 5 TMG and other TMG citations, § 55 RStV, TTDSG, link or notice to the EU online dispute resolution platform (repealed with effect from 20 July 2025), Privacy Shield, Safe Harbor, old standard contractual clauses, Directive 95/46/EC |
| Cookies and third parties | Consent tool (Usercentrics, Cookiebot, Borlabs, Complianz, CCM19, Real Cookie Banner, consentmanager, Klaro and more), trackers that run on page load versus trackers blocked until consent, fonts loaded from Google servers |
| BFSG | Link to accessibility information (Erklärung zur Barrierefreiheit) |
| Accessibility signals | Subset of WCAG 2.1 that static HTML shows: page language (3.1.1), title (2.4.2), image alternatives (1.1.1), form labels (1.3.1, 4.1.2), link and button names (2.4.4, 4.1.2), iframe titles (4.1.2), zoom lock (1.4.4), meta refresh (2.2.1), autoplay (1.4.2), bypass blocks (2.4.1); best practices without points |
| Security and AI | HTTPS; robots.txt rules for AI crawlers (GPTBot, ClaudeBot, PerplexityBot, Google-Extended, CCBot) and `llms.txt` |

### Output

One item per website. The table view shows the most important fields; the "Issues" view lists one row per finding. All fields are flat enough for CSV and Excel export.

```json
{
  "url": "https://www.example.com/",
  "status": "ok",
  "score": 72,
  "summaryDe": "1 hoch, 1 mittel, 2 niedrig",
  "topIssuesDe": [
    "Auf der Impressum-Seite wurde keine Postleitzahl mit Ort gefunden (§ 5 Abs. 1 Nr. 1 DDG: Name und Anschrift).",
    "Im HTML erscheinen aktive Tracking-Skripte von Drittanbietern, aber kein Einwilligungstool und kein Cookie-Hinweis wurde erkannt. …",
    "Zitiert das Telemediengesetz (TMG). …"
  ],
  "issueCodes": ["impressum_no_address", "tracker_without_consent_tool", "outdated_tmg", "external_google_fonts"],
  "impressumLinkFound": true,
  "datenschutzLinkFound": true,
  "consentTool": null,
  "trackersActive": "Google Tag Manager",
  "outdatedReferences": "§ 5 TMG",
  "issues": [
    { "code": "outdated_tmg", "category": "outdated", "severity": "low", "evidence": "§ 5 TMG", "message": "…", "messageDe": "…" }
  ]
}
```

Severity: high 25, medium 10, low 4 points off a score of 100; info and best practices cost nothing.

### Status values and billing

You pay per website with status `ok` only. Websites that cannot be checked are listed with their reason and are **free**:

| Status | Meaning |
|---|---|
| `ok` | Checked. Charged once. |
| `blocked` | HTTP 401, 403, 429 or 503, or a bot-protection or CAPTCHA page |
| `blocked_by_robots` | robots.txt disallows the start page, or robots.txt answers with a server error (RFC 9309: complete disallow) |
| `unreachable` | Network error or HTTP error |
| `inconclusive` | No legal link and no legal page found on a page that builds its content with JavaScript |
| `error` | Unexpected error |

The run stops before your spending limit: a website is only checked if it can still be charged. The run summary is stored in the key-value store as `OUTPUT`.

### Good to know

- The checks are heuristics on the static HTML of a few pages. A good score is not a legal opinion, and a finding needs a human look before you act on it. This is not legal advice and no replacement for a full accessibility audit (automatic checks find only a part of all barriers).
- The Actor follows robots.txt (RFC 9309) by default, sends at most 14 requests per website and pauses between them (400 ms by default). It never logs in, never solves CAPTCHAs and never bypasses access restrictions.
- Using the results for outreach: in Germany, advertising by e-mail requires the recipient's prior express consent (§ 7 (2) No. 2 UWG), towards businesses too. Use the results lawfully.

### Input

| Field | Default | Description |
|---|---|---|
| `urls` | – | Start pages, one per line. Each website is checked once. |
| `maxConcurrency` | 5 | Websites checked at the same time |
| `requestTimeoutSecs` | 15 | Timeout per request |
| `delayBetweenRequestsMs` | 400 | Pause between two requests to the same website |
| `checkPrivacyPage` | true | Open the privacy page (outdated references, broken link) |
| `probeStandardPaths` | true | Look for unlinked legal pages in the sitemap and at usual addresses |
| `respectRobotsTxt` | true | Follow robots.txt |

### Kurz auf Deutsch

Prüft deutsche Websites auf Impressum (§ 5 DDG), Datenschutzerklärung, Cookie-Einwilligung und Tracker, veraltete Verweise (TMG, OS-Plattform, Privacy Shield), Erklärung zur Barrierefreiheit (BFSG) und Barrierefreiheits-Signale nach WCAG 2.1. Je Website gibt es einen Score, die drei wichtigsten Mängel auf Deutsch und eine Liste aller Befunde mit Beleg. Berechnet wird nur eine erfolgreich geprüfte Website. Das Ergebnis ist eine technische Prüfung, keine Rechtsberatung.

### Feedback

Missing a check, or a finding that is wrong for your website? Open an issue on the Actor page with the URL and what you expected.

# Actor input Schema

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

Start page of each website to check, one per line, for example https://www.example.com. Each website is checked once, even if several of its pages are listed.

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

How many different websites are checked at the same time. Each website gets only a few requests with a pause between them.

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

Maximum wait time per request.

## `delayBetweenRequestsMs` (type: `integer`):

Politeness pause between two requests to the same website.

## `checkPrivacyPage` (type: `boolean`):

Fetch the linked privacy page to confirm it loads and to find outdated references (one extra request).

## `probeStandardPaths` (type: `boolean`):

If the start page does not link an Impressum or privacy page, look in the sitemap and at usual addresses such as /impressum (up to five extra requests, robots.txt respected).

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

Skip pages that robots.txt disallows for automated access (RFC 9309). Recommended.

## Actor input object example

```json
{
  "urls": [
    "https://www.bundestag.de"
  ],
  "maxConcurrency": 5,
  "requestTimeoutSecs": 15,
  "delayBetweenRequestsMs": 400,
  "checkPrivacyPage": true,
  "probeStandardPaths": true,
  "respectRobotsTxt": true
}
```

# 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 = {
    "urls": [
        "https://www.bundestag.de"
    ]
};

// Run the Actor and wait for it to finish
const run = await client.actor("infinit_bubulus/german-website-compliance-check").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": ["https://www.bundestag.de"] }

# Run the Actor and wait for it to finish
run = client.actor("infinit_bubulus/german-website-compliance-check").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 '{
  "urls": [
    "https://www.bundestag.de"
  ]
}' |
apify call infinit_bubulus/german-website-compliance-check --silent --output-dataset

```

## MCP server setup

```json
{
    "mcpServers": {
        "apify": {
            "type": "http",
            "url": "https://mcp.apify.com/?tools=fetch-actor-details,infinit_bubulus/german-website-compliance-check"
        }
    }
}
```

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/0mVexmM37dttUHH7f/builds/PwSTmiB70iMC7Uy8K/openapi.json
