# ✨ German Imprint Scraper & Leads Finder (Google Search) (`winningsolutions/german-imprint-scraper`) Actor

AI-powered Apify Actor that scrapes Impressum pages on German websites and extracts decision-makers (Geschäftsführer, Vorstand), validated B2B emails, company addresses, VAT IDs, and Handelsregister numbers. Structured JSON output for B2B lead generation, sales prospecting, and CRM enrichment.

- **URL**: https://apify.com/winningsolutions/german-imprint-scraper.md
- **Developed by:** [Winning Solutions](https://apify.com/winningsolutions) (community)
- **Categories:** Lead generation, Developer tools
- **Stats:** 201 total users, 32 monthly users, 100.0% runs succeeded, 11 bookmarks
- **User rating**: 5.00 out of 5 stars

## Pricing

from $3.90 / 1,000 successful data extractions

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

## German Impressum Scraper & Leads Finder – Decision Makers, Email Verification & Company Data

An **AI-powered** Apify Actor that finds and scrapes German website Impressum pages to extract **contact details** at scale. Start from your own **URL list** or simply enter **Google search terms** - the built-in **Lead Finder** turns queries like `marketing agency berlin` into ready-to-scrape leads automatically.

It detects **imprint links**, navigates pages reliably, and returns **structured JSON** with **company name**, **all decision-makers** (Geschäftsführer, Vorstand, Inhaber, ...), **address**, **phone**, **email** (with optional **validation**), **social media profile URLs** (Facebook, Instagram, LinkedIn, and more), **VAT ID**, and **Handelsregister numbers**.

Designed for **lead generation**, **CRM enrichment**, and **compliance workflows**, the scraper ensures high **data accuracy** through intelligent **page detection**, robust **parsing** logic, and optional **email validation**. It supports **batch processing**, handles **edge cases** like non-standard layouts, and includes **retry mechanisms** for scalable **data extraction**.

> ## 🚀 New in version 2.0: Lead Finder
>
> **No URL list? No problem.**
>
> Just type Google search terms like `marketing agency berlin` or `steuerberater münchen` and the Actor turns them into ready-to-use leads. It pulls the organic Google results for each query, visits every website, and extracts the full Impressum contact data automatically - **from keyword to verified B2B lead in a single run.**

### Use Cases

- Generate **B2B leads** with **verified contact data**
- Enrich your **CRM** with **German company information**
- Build **outreach lists** with **validated emails**
- Run **market** and **competitor research**
- Automate **data collection** workflows

### Index

- [Release Notes](#release-notes)
- [Features](#features)
- [Use Cases](#use-cases)
- [Lead Discovery with Google Search](#lead-discovery-with-google-search)
- [Advanced Email Validation](#advanced-email-validation)
- [Pricing](#pricing)
- [Input](#input)
- [Input Example](#input-example)
- [API and MCP usage](#api-and-mcp-usage)
- [Output Structure](#output-structure)
- [Output Example](#output-example)

### Release Notes

#### v2.3.1 - fixed an issue where the actor could time-out when scraping 800+ domains

#### v2.3 - Social media link extraction

- **New `social_media_links` field** - an object with keys `facebook`, `instagram`, `linkedin`, `xing`, `youtube`, `twitter`, `tiktok`, `pinterest`, `whatsapp`. Each key holds the first profile URL found on the homepage or imprint page; empty string when not found.
- **New `disableSocialMediaLinks` input flag** - set to `true` to omit `social_media_links` from each dataset row.

#### v2.2.1 - fixed an issue where the actor could time-out

#### v2.2 - All decision makers extracted

- **New `decision_makers` array** - every responsible person found in the imprint (Geschäftsführer, Gesellschafter, Vorstand, Vertretungsberechtigte, Inhaber, Ansprechpartner, ...) is now returned as a structured array. Each entry contains `first_name`, `last_name`, `salutation`, `academic_title` (e.g. Dr., Prof. Dr.), `profession` (e.g. Steuerberater, Rechtsanwalt), and `roles` (array of section headings that person appears under).
- **Backward compatible** - the existing singular `contact_person` field is unchanged and always contains the highest-priority person (Geschäftsführer → Verantwortlicher → Ansprechpartner → Inhaber).
- **New `disableDecisionMakers` input flag** - set to `true` to omit the `decision_makers` array from output rows.
- **New `All Decision Makers` dataset view** - shows the full array per company in the Apify Console.

#### v2.1 - Domain blacklist for lead discovery

- **Domain blacklist** - new `domainBlacklist` input field (comma-separated domains) for Google Search lead discovery mode; matching discovered URLs are still charged (`website-processed`) but not scraped or written to the dataset

#### 🚀 v2.0 - Lead discovery via Google Search

- **Lead discovery via Google Search** - new `inputMode: searchTerms` mode to discover URLs from Google queries, then scrape their imprints automatically
- **New input fields** - `searchTerms`, `resultsPerSearchTerm`, `locationName`, `languageCode`, `device`
- **New output field** - `search_term` on every row (null when using Target URLs mode)
- **New pay-per-event** - `serp-search-page` at **$0.005 per SERP page** ($5.00 / 1,000 pages, approximately 10 results per page)

#### v1.3 - API and MCP readiness

- **API and MCP usage guide** - new README section with copyable `curl`, `apify-client` (JavaScript), and Apify MCP examples
- **Improved schema descriptions** - input, output, and dataset descriptions sharpened for programmatic and AI tool callers; no field names or runtime behavior changed

#### v1.2 - Faster processing & smarter AI analysis

- **Improved parallel processing** - Actor is now 50% faster
- **Improved imprint analysis with fallbacks** - LLM is always used for the best result
- **Added "PerformanceMax" option** - for faster processing (requires at least 2 GB RAM)
- **Improved log formatting**
- `**imprint_url` is `null` when not found\*\* - if the imprint URL is not found, it will now show as `null`
- **New `imprint_status` field** - indicates the outcome of imprint URL discovery (`FOUND`, `NOT_FOUND`, `FETCH_ERROR`, `URL_ERROR`, `ERROR`, `UNKNOWN`)

#### v1.1 - Bug fixes & reliability improvements

- **Reliability fixes** - graceful charge-limit handling under concurrency, input-schema cleanup, and several scraper edge-case fixes
- **Improved AI analysis reliability** - more robust handling of LLM responses with multi-provider fallback
- **Slimmer Build image** - faster cold starts and smaller pulls

#### 🎉 v1.0 - Initial public release

- **AI-powered imprint detection** - finds *Impressum* links even when traditional parsing fails
- **Intelligent scraping engine** - automatically switches between a lightweight fast mode and a full browser mode depending on the website's complexity
- **Comprehensive email validation** - syntax, MX records, disposable filter, role-based detection, alias resolution, typo suggestions and live status tracking
- **Per-field privacy toggles** - disable any output field you don't need (e.g. `disableEmail`, `disableVatId`)
- **Pay-per-event pricing** - only pay for processed websites and (optionally) validated emails

### Lead Discovery with Google Search

Instead of providing URLs manually, you can let the Actor discover leads automatically via Google Search. Set **Input Mode** to **Google Search Terms** and enter one search query per line (e.g. `zahnarzt berlin`, `rechtsanwalt münchen`). The Actor fetches organic Google results for each term and scrapes the imprint of every discovered website.

Each SERP page returned (approximately 10 organic results per page) is billed as one **Google SERP page (Lead Discovery)** pay-per-event charge of **$0.005 per page** ($5.00 / 1,000 pages) on top of the usual imprint-scraping fees.

### Features

🤖 **AI-Powered Link Detection:** Uses AI to find imprint page links when traditional parsing fails

🧠 **Smart Contact Extraction:** Extracts comprehensive contact and company information

🇩🇪 **German Website Optimization:** Specifically optimized for German website structures and imprint pages

🛡️ **Robust Error Handling:** Built-in retry mechanisms and comprehensive error handling

📊 **Detailed Output:** Structured data with contact person, company details, and legal information

📱 **Social Media Profiles:** Extracts profile URLs for nine platforms from the homepage and imprint page

🌐 **Proxy Support:** Optional proxy configuration for enhanced reliability

#### Advanced Email Validation

When enabled, the Actor performs comprehensive email validation using multiple verification methods:

- **Syntax validation** - Ensures proper email format
- **Domain existence check** - Verifies the domain is active and reachable
- **MX record validation** - Confirms the domain can receive emails
- **Disposable email detection** - Filters out temporary/disposable email addresses
- **Role-based email detection** - Identifies generic addresses (info@, admin@, etc.)
- **Email alias detection** - Detects aliases for major providers (Gmail, Yahoo, Outlook/Hotmail)
- **Typo suggestions** - Provides corrections for common email typos
- **Real-time monitoring** - Live validation status tracking

This ensures you only get high-quality, deliverable email addresses for your lead generation campaigns.

### Pricing

| Cost item                         | Rate                                     |
| --------------------------------- | ---------------------------------------- |
| Successful data extraction        | $4.50 / 1,000 results                    |
| Website processing fee            | $0.60 / 1,000 websites                   |
| Email validation service          | $2.50 / 1,000 validations                |
| Google SERP page (Lead Discovery) | $5.00 / 1,000 SERP pages (~10 results each) |
| Actor start                       | $0.04 (infrequent)                       |
| Apify platform compute (RAM/time) | Billed by Apify platform pricing         |

> **Cost per lead: ~$0.005** - stays constant regardless of run size.

Email validation is billed separately at **$0.0025** per validated address when `validateEmail` is enabled.

#### Cost Examples

**Scenario A: 100 URLs, ~90 successful imprints**

- Actor start: $0.04
- 100 websites processed: $0.06
- 90 successful results: $0.41
- **Total: ~$0.51**

**Scenario B: 500 URLs, ~430 successful imprints**

- Actor start: $0.04
- 500 websites processed: $0.30
- 430 successful results: $1.94
- **Total: ~$2.28**

**Scenario C: Lead Discovery, 50 search terms (10 results each), ~350 successful imprints**

- Actor start: $0.04
- 50 SERP pages: $0.25
- \~500 websites processed: $0.30
- 350 successful results: $1.58
- **Total: ~$2.17**

### Input

The Actor accepts the following input parameters (see the **Input** tab in the Apify Console for the full, interactive schema):

| Parameter                 | Type    | Required                     | Default   | Description                                                                                                                                                             |
| ------------------------- | ------- | ---------------------------- | --------- | ----------------------------------------------------------------------------------------------------------------------------------------------------------------------- |
| `inputMode`               | string  | no                           | `urls`    | Input mode: `urls` (Target URLs) or `searchTerms` (Google Search lead discovery).                                                                                       |
| `targetUrls`              | array   | when `inputMode=urls`        | -         | Array of `{ "url": "..." }` objects. Invalid URLs are skipped and reported as input warnings.                                                                           |
| `searchTerms`             | string  | when `inputMode=searchTerms` | -         | One Google query per line. Used only in searchTerms mode.                                                                                                               |
| `resultsPerSearchTerm`    | integer | no                           | `10`      | Organic results to fetch per search term (1–100).                                                                                                                       |
| `locationName`            | string  | no                           | `Germany` | Region for Google search results. Enter a country or city spelled out in full, e.g. `Germany` or `Berlin`.                                                              |
| `languageCode`            | string  | no                           | `de`      | ISO language code for Google results.                                                                                                                                   |
| `device`                  | string  | no                           | `desktop` | Device for SERP requests: `desktop` or `mobile`.                                                                                                                        |
| `domainBlacklist`         | string  | no                           | -         | Comma-separated domains to exclude from output in searchTerms mode. Matching URLs are still charged but not written to the dataset. Ignored when `inputMode` is `urls`. |
| `skipResultsWithoutEmail` | boolean | no                           | `false`   | When enabled, results without an email address are not written to the dataset.                                                                                          |
| `maxRetries`              | integer | no                           | `3`       | Maximum retry attempts for failed requests (0–10).                                                                                                                      |
| `timeout`                 | integer | no                           | `5`       | Per-request timeout in seconds (5–60).                                                                                                                                  |
| `validateEmail`           | boolean | no                           | `false`   | Enable email validation; extra usage fees apply when on.                                                                                                                |
| `proxyConfiguration`      | object  | no                           | -         | Apify Proxy or custom proxy URLs (`useApifyProxy`, optional `proxyUrls`, `groups`, `countryCode`).                                                                      |
| `performanceMax`          | boolean | no                           | `false`   | Higher parallelism; use only with at least 2 GB Actor memory.                                                                                                           |
| `disableImprintUrl`       | boolean | no                           | `false`   | Omit `imprint_url` and `imprint_status` from each row.                                                                                                                  |
| `disableContactPerson`    | boolean | no                           | `false`   | Omit `contact_person` from each row.                                                                                                                                    |
| `disableDecisionMakers`   | boolean | no                           | `false`   | Omit `decision_makers` array from each row. Does not affect `contact_person`.                                                                                           |
| `disableCompanyName`      | boolean | no                           | `false`   | Omit `company_name` from each row.                                                                                                                                      |
| `disableCompanyAddress`   | boolean | no                           | `false`   | Omit `company_address` from each row.                                                                                                                                   |
| `disablePhoneNumber`      | boolean | no                           | `false`   | Omit `phone_number` from each row.                                                                                                                                      |
| `disableEmail`            | boolean | no                           | `false`   | Omit `email` and `email_status` from each row.                                                                                                                          |
| `disableRegisterNumber`   | boolean | no                           | `false`   | Omit `register_number` from each row.                                                                                                                                   |
| `disableVatId`            | boolean | no                           | `false`   | Omit `vat_id` from each row.                                                                                                                                            |
| `disableSocialMediaLinks` | boolean | no                           | `false`   | Omit `social_media_links` from each row.                                                                                                                                |
| `useHeadlessBrowser`      | boolean | no                           | `false`   | Not shown in Console. If true, force browser-based scraping for all URLs.                                                                                               |
| `enableAxiosRetry`        | boolean | no                           | `true`    | Not shown in Console. If true, axios-first scraping with browser fallback.                                                                                              |
| `retryOptions`            | object  | no                           | -         | Not shown in Console. Retry trigger criteria for axios-first mode (`requireEmail`, `requireContactPerson`, `requireAnyField`, `minFieldsRequired`).                     |

#### Input Example (Target URLs)

```json
{
  "inputMode": "urls",
  "targetUrls": [
    {"url": "https://example.de"},
    {"url": "https://another-site.de"}
  ],
  "skipResultsWithoutEmail": false,
  "maxRetries": 1,
  "timeout": 5,
  "validateEmail": true,
  "proxyConfiguration": {
    "useApifyProxy": false
  }
}
```

#### Input Example (Lead Discovery)

```json
{
  "inputMode": "searchTerms",
  "searchTerms": "zahnarzt berlin\nrechtsanwalt münchen",
  "resultsPerSearchTerm": 10,
  "locationName": "Germany",
  "languageCode": "de",
  "device": "desktop",
  "validateEmail": false
}
```

### API and MCP usage

Runs write dataset rows for each **valid input URL** that reaches processing. Every row includes `target_url` for deterministic input-output mapping. The Actor does not write a separate key-value `OUTPUT` record. Fetch rows from the default dataset after the run succeeds (or use the synchronous endpoint below).

**REST (sync, returns dataset items):** replace `YOUR_USERNAME`, `YOUR_API_TOKEN`, and use the same JSON body as in [Input Example](#input-example).

```bash
curl "https://api.apify.com/v2/acts/YOUR_USERNAME~german-imprint-scraper/run-sync-get-dataset-items?token=YOUR_API_TOKEN" \
  -X POST \
  -H "Content-Type: application/json" \
  -d '{"targetUrls":[{"url":"https://www.winning-solutions.de"}],"validateEmail":false}'
```

**JavaScript (`apify-client`):**

```javascript
import { ApifyClient } from 'apify-client';

const client = new ApifyClient({ token: process.env.APIFY_TOKEN });
const input = {
  targetUrls: [{ url: 'https://www.winning-solutions.de' }],
  validateEmail: false,
};
const run = await client.actor('YOUR_USERNAME~german-imprint-scraper').call(input);
const { items } = await client.dataset(run.defaultDatasetId).listItems();
console.log(items);
```

**Apify MCP server (AI agents):** configure your MCP client with URL `https://mcp.apify.com?tools=YOUR_USERNAME~german-imprint-scraper` (you can combine multiple tools per [Apify MCP docs](https://docs.apify.com/platform/integrations/mcp)). Pass the API token via your client (for example an `Authorization: Bearer ...` header), not inside the Actor input JSON.

### Output Structure

The Actor returns structured data for each processed URL. The table below lists the main fields. Optional dataset views in the Apify Console may show a subset or flattened columns. When **disable** options are enabled, the corresponding keys are omitted from each row.

| Field                          | Type          | Description                                                                                                                                                                                                                                      | Example Value                    |
| ------------------------------ | ------------- | ------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------ | -------------------------------- |
| `search_term`                  | string | null | Google query that surfaced this URL; null in Target URLs mode                                                                                                                                                                                    | `"zahnarzt berlin"`              |
| `target_url`                   | string        | Original input URL that produced this row                                                                                                                                                                                                        | `"https://example.de"`           |
| `imprint_url`                  | string        | Found impressum page URL, `null` when not found or an error occurred                                                                                                                                                                             | `"https://example.de/impressum"` |
| `imprint_status`               | string        | Result of imprint URL discovery: `FOUND`, `NOT_FOUND`, `FETCH_ERROR`, `URL_ERROR`, `ERROR`, or `UNKNOWN`                                                                                                                                         | `"FOUND"`                        |
| `contact_person.first_name`    | string        | First name of the primary contact (backward compatible, always present)                                                                                                                                                                          | `"Max"`                          |
| `contact_person.last_name`     | string        | Last name of the primary contact                                                                                                                                                                                                                 | `"Mustermann"`                   |
| `contact_person.salutation`    | string        | Salutation (Herr/Frau)                                                                                                                                                                                                                           | `"Herr"`                         |
| `decision_makers`              | array         | All responsible persons found in the imprint. Each entry has `first_name`, `last_name`, `salutation`, `academic_title` (e.g. `"Dr."`), `profession` (e.g. `"Steuerberater"`), and `roles` (array, e.g. `["Geschäftsführer", "Gesellschafter"]`). | see below                        |
| `company_name`                 | string        | Full official company name                                                                                                                                                                                                                       | `"Example GmbH"`                 |
| `company_address.street`       | string        | Street name                                                                                                                                                                                                                                      | `"Musterstraße"`                 |
| `company_address.house_number` | string        | House number                                                                                                                                                                                                                                     | `"123"`                          |
| `company_address.postalcode`   | string        | Postal code                                                                                                                                                                                                                                      | `"12345"`                        |
| `company_address.city`         | string        | City name                                                                                                                                                                                                                                        | `"Musterstadt"`                  |
| `phone_number`                 | string        | Contact phone number                                                                                                                                                                                                                             | `"+49 123 456789"`               |
| `email`                        | string        | Contact email address                                                                                                                                                                                                                            | `"info@example.de"`              |
| `email_status`                 | string        | With validation: `DELIVERABLE`, `UNDELIVERABLE`, `UNKNOWN`, or `MISSING_EMAIL` if no email was found                                                                                                                                             | `"DELIVERABLE"`                  |
| `register_number`              | string        | Commercial register number / Handelsregisternummer                                                                                                                                                                                               | `"HRB 12345"`                    |
| `vat_id`                       | string        | VAT ID number / Umsatzsteuer-Id                                                                                                                                                                                                                  | `"DE123456789"`                  |
| `social_media_links`           | object        | Profile URLs for `facebook`, `instagram`, `linkedin`, `xing`, `youtube`, `twitter`, `tiktok`, `pinterest`, `whatsapp`. Empty string per key when not found. Detected from homepage and imprint HTML - no extra AI cost.                         | see below                        |
| `retryTriggered`               | boolean       | Whether retry was triggered during scraping                                                                                                                                                                                                      | `false`                          |
| `retryReasons`                 | array         | Array of reasons why retry was triggered (optional)                                                                                                                                                                                              | `["email is empty"]`             |
| `_metadata.websiteProcessed`   | boolean       | Whether the website was successfully processed                                                                                                                                                                                                   | `true`                           |
| `_metadata.resultCharged`      | boolean       | Whether this result was charged                                                                                                                                                                                                                  | `true`                           |
| `_metadata.emailValidated`     | boolean       | Whether email validation was performed                                                                                                                                                                                                           | `true`                           |
| `_metadata.limitReached`       | boolean       | Whether usage limit was reached                                                                                                                                                                                                                  | `false`                          |
| `_metadata.error`              | string        | Present when the row records a top-level run failure                                                                                                                                                                                             | *(varies)*                       |
| `_metadata.errorContext`       | mixed         | Extra debugging context when `error` is set                                                                                                                                                                                                      | *(varies)*                       |

#### Output Example

```json
{
  "search_term": "steuerberater münchen",
  "target_url": "https://example.de",
  "imprint_url": "https://example.de/impressum",
  "imprint_status": "FOUND",
  "contact_person": {
    "first_name": "Felix",
    "last_name": "Keß",
    "salutation": "Herr"
  },
  "decision_makers": [
    {
      "first_name": "Felix",
      "last_name": "Keß",
      "salutation": "Herr",
      "academic_title": "",
      "profession": "Steuerberater",
      "roles": ["Vertretungsberechtigter", "Gesellschafter"]
    },
    {
      "first_name": "Marcus",
      "last_name": "Stein",
      "salutation": "Herr",
      "academic_title": "Dr.",
      "profession": "Steuerberater",
      "roles": ["Vertretungsberechtigter", "Gesellschafter"]
    },
    {
      "first_name": "Jutta",
      "last_name": "Keß",
      "salutation": "Frau",
      "academic_title": "",
      "profession": "Steuerberaterin",
      "roles": ["Gesellschafterin"]
    }
  ],
  "company_name": "Keß & Partner Steuerberatungsgesellschaft mbB",
  "company_address": {
    "street": "Musterstraße",
    "house_number": "123",
    "postalcode": "80331",
    "city": "München"
  },
  "phone_number": "+49 89 123456",
  "email": "info@example.de",
  "email_status": "DELIVERABLE",
  "register_number": "HRB 12345",
  "vat_id": "DE123456789",
  "social_media_links": {
    "facebook": "https://www.facebook.com/example",
    "instagram": "https://www.instagram.com/example",
    "linkedin": "https://www.linkedin.com/company/example",
    "xing": "",
    "youtube": "",
    "twitter": "",
    "tiktok": "",
    "pinterest": "",
    "whatsapp": ""
  },
  "retryTriggered": false,
  "retryReasons": [],
  "_metadata": {
    "websiteProcessed": true,
    "resultCharged": true,
    "emailValidated": true,
    "limitReached": false
  }
}
```

# Actor input Schema

## `targetUrls` (type: `array`):

Websites to scrape. Each item must be an object with a `url` key, for example `{ "url": "https://example.de" }`. The Console uses the request-list editor; API and MCP callers should use the same JSON shape. Required when Input Mode is Target URLs.

## `inputMode` (type: `string`):

Choose how to feed websites into the scraper. Target URLs: provide a list of websites directly. Google Search Terms: discover URLs from Google search results, then scrape their imprints.

## `searchTerms` (type: `string`):

One Google query per line. Used only when Input Mode is Google Search Terms. Ignored when Input Mode is Target URLs.

## `resultsPerSearchTerm` (type: `integer`):

Number of organic Google results to fetch per search term (1–100). Each page of ~10 results counts as one serp-search-page charge ($0.005 per page).

## `locationName` (type: `string`):

Region for Google search results. Enter a country or city spelled out in full, e.g. Germany or Berlin.

## `languageCode` (type: `string`):

ISO language code for Google results (e.g. 'de', 'en').

## `device` (type: `string`):

Device type for Google SERP requests.

## `domainBlacklist` (type: `string`):

Comma-separated domains to exclude from output when using Google Search Terms lead discovery. Matching URLs are still charged but not written to the dataset. Ignored when Input Mode is Target URLs.

## `skipResultsWithoutEmail` (type: `boolean`):

If true, rows without a non-empty `email` are not written to the default dataset. Error rows are still saved. Use for lead lists where an email is mandatory.

## `maxRetries` (type: `integer`):

How many times to retry failed HTTP or scrape steps for a URL (0 to 10). Does not change which fields are extracted.

## `timeout` (type: `integer`):

Per-request timeout in seconds for HTTP-style steps (5 to 60).

## `validateEmail` (type: `boolean`):

If true, runs deliverability-oriented checks on extracted emails and sets `email_status` (e.g. DELIVERABLE, UNDELIVERABLE). Extra usage fees apply when enabled. If false, `email_status` may still be present but reflects no full validation pass.

## `disableImprintUrl` (type: `boolean`):

If true, omits `imprint_url` and `imprint_status` from each dataset row for privacy or leaner exports. Same business logic runs; only the stored fields change.

## `disableContactPerson` (type: `boolean`):

If true, omits the whole `contact_person` object from each dataset row.

## `disableDecisionMakers` (type: `boolean`):

If true, omits the `decision_makers` array from each dataset row. The singular `contact_person` field is not affected.

## `disableCompanyName` (type: `boolean`):

If true, omits `company_name` from each dataset row.

## `disableCompanyAddress` (type: `boolean`):

If true, omits `company_address` from each dataset row.

## `disablePhoneNumber` (type: `boolean`):

If true, omits `phone_number` from each dataset row.

## `disableEmail` (type: `boolean`):

If true, omits `email` and `email_status` from each dataset row.

## `disableRegisterNumber` (type: `boolean`):

If true, omits `register_number` (Handelsregister) from each dataset row.

## `disableVatId` (type: `boolean`):

If true, omits `vat_id` from each dataset row.

## `disableSocialMediaLinks` (type: `boolean`):

If true, omits the `social_media_links` object from each dataset row.

## `performanceMax` (type: `boolean`):

High-throughput mode: higher internal concurrency (about 3x faster for large lists). Requires at least 2 GB Actor memory. Leave false on the 1 GB memory tier to avoid out-of-memory failures.

## `useHeadlessBrowser` (type: `boolean`):

Programmatic flag. If true, force browser-based scraping path for all URLs instead of axios-first mode.

## `enableAxiosRetry` (type: `boolean`):

Programmatic flag. If true, run axios-first scraping with optional browser fallback retries.

## `retryOptions` (type: `object`):

Programmatic flag. Controls retry trigger criteria used by axios-first mode.

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

Optional Apify Proxy or custom proxy URLs. Use when sites block datacenter IPs. Shape matches Apify's proxy editor (`useApifyProxy`, optional `proxyUrls`, `groups`, `countryCode`). Proxy usage is included in the base cost as documented for this Actor.

## Actor input object example

```json
{
  "targetUrls": [
    {
      "url": "https://example.de"
    }
  ],
  "inputMode": "urls",
  "searchTerms": "zahnarzt berlin\nrechtsanwalt münchen",
  "resultsPerSearchTerm": 10,
  "locationName": "Germany",
  "languageCode": "de",
  "device": "desktop",
  "skipResultsWithoutEmail": false,
  "maxRetries": 3,
  "timeout": 5,
  "validateEmail": false,
  "disableImprintUrl": false,
  "disableContactPerson": false,
  "disableDecisionMakers": false,
  "disableCompanyName": false,
  "disableCompanyAddress": false,
  "disablePhoneNumber": false,
  "disableEmail": false,
  "disableRegisterNumber": false,
  "disableVatId": false,
  "disableSocialMediaLinks": false,
  "performanceMax": false,
  "useHeadlessBrowser": false,
  "enableAxiosRetry": true,
  "proxyConfiguration": {
    "useApifyProxy": false
  }
}
```

# Actor output Schema

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

HTTP URL of the default dataset items endpoint. Use this URL to fetch all result rows.

# 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 = {
    "targetUrls": [
        {
            "url": "https://example.de"
        }
    ],
    "searchTerms": `zahnarzt berlin
rechtsanwalt münchen`,
    "proxyConfiguration": {
        "useApifyProxy": false
    }
};

// Run the Actor and wait for it to finish
const run = await client.actor("winningsolutions/german-imprint-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 = {
    "targetUrls": [{ "url": "https://example.de" }],
    "searchTerms": """zahnarzt berlin
rechtsanwalt münchen""",
    "proxyConfiguration": { "useApifyProxy": False },
}

# Run the Actor and wait for it to finish
run = client.actor("winningsolutions/german-imprint-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 '{
  "targetUrls": [
    {
      "url": "https://example.de"
    }
  ],
  "searchTerms": "zahnarzt berlin\\nrechtsanwalt münchen",
  "proxyConfiguration": {
    "useApifyProxy": false
  }
}' |
apify call winningsolutions/german-imprint-scraper --silent --output-dataset

```

## MCP server setup

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

```

## OpenAPI specification

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