German Impressum Contact Scraper avatar

German Impressum Contact Scraper

Pricing

from $3.87 / 1,000 imprint record returneds

Go to Apify Store
German Impressum Contact Scraper

German Impressum Contact Scraper

German Impressum Contact Scraper reads a list of company websites, or you can provide a search-API key to find them, and returns each site's Impressum/legal notice: company name, address, register court and number, VAT ID, directors, email, phone. Proxy and headless-browser fallback.

Pricing

from $3.87 / 1,000 imprint record returneds

Rating

0.0

(0)

Developer

Pradio Actors

Pradio Actors

Maintained by Community

Actor stats

0

Bookmarked

2

Total users

1

Monthly active users

2 days ago

Last modified

Share

German Impressum Contact Scraper reads the Impressum of every company website you give it and returns one row per site: the registered company name, address, register court and number, VAT ID, managing directors, email and phone. Paste a list of domains or type search terms with your own search-API key, press Start, and the rows land in your dataset as they are read. A site that yields nothing costs nothing, and its row says why.

On 100 German company sites it had never seen, run where a buyer runs it, 60% came back filled, at $0.00496 a row and no start fee of its own.

Who uses German Impressum Contact Scraper

BuyerWhat they run it for
Contact-data buildersTurn a list of domains into legal entity names, emails and phone numbers pulled from each company's own legal page.
Compliance and due-diligence teamsCollect register court, register number and managing directors, the disclosures an imprint is required to carry, without opening each site by hand.
B2B sales and outreach teamsFind the real legal entity and a working contact behind a website before writing to it.
Data teams enriching company listsAdd registered address and registration identifiers to rows that only hold a domain.

Features

  • Automatic imprint discovery. The site's own impressum, imprint or legal-notice link is followed up to two hops: homepage to legal hub to notice. The contact page is tried when the homepage carries no link. A related host is followed across a locale redirect. The conventional paths (/impressum, /imprint…) are probed when the footer only exists after hydration.
  • Dual fetching. A plain request first, then a headless browser pass when the page needs one (useBrowser, on by default).
  • Proxy escalation a site has to earn. Datacenter requests first. A page that answers with a block is retried once through residential, never before. Configure RESIDENTIAL groups yourself to proxy everything.
  • Search mode, bring-your-own-key. Type terms instead of pasting URLs. They resolve to domains through the Brave or Google Custom Search API with your key, then read like any start URL.
  • Legal-notice vocabulary, German- and English-first. Impressum, imprint, legal notice/information, Anbieterkennzeichnung, mentions légales, colophon, disclaimer.
  • Exclusion that is honoured, not promised. The exclude input and the Actor's own exclusion list are read at the start of every run. A domain skips its start URLs before any fetch. A company or person name drops the row that carries it. See Personal data.

What you can count on

  • You pay only for rows whose status is ok. A site that refused the request, hid its imprint behind JavaScript, or publishes none is pushed as an uncharged ITEM_STATUS row. The dataset still tells you what happened.
  • Every billed row is charged only after it is written to your dataset. A row you cannot see is never billed.
  • A run that finds nothing returns one PROFILE_NOT_FOUND row that says so, never an empty dataset.
  • A spending limit stops the run cleanly. A STOPPED_EARLY row says how many rows were returned and how many were not.
  • Every run writes RUN_SUMMARY to the key-value store: rowsFetched, rowsPushed, rowsCharged, duplicatesDropped, excluded. A short run and a broken one are told apart.
  • No value is invented. A field the page does not show is null, and the field table below says which.

What data does German Impressum Contact Scraper return?

One row per start URL. This is a real row from a captured run, slightly shortened:

{
"pageId": "trigema.de",
"domain": "trigema.de",
"website": "https://trigema.de",
"pageUrl": "https://www.trigema.de/kundenservice/rechtliches/impressum/",
"title": "Impressum | trigema",
"email": "bestellservice@trigema.de",
"phone": "+497475880",
"websites": [
"https://trigema.de"
],
"imprint_url": "https://www.trigema.de/kundenservice/rechtliches/impressum/",
"company_name": "Trigema W. Grupp KG",
"street": "Josef-Mayer-Str. 31-35",
"postal_code": "72393",
"city": "Burladingen",
"country": "DE",
"managing_director": "Wolfgang Grupp, Trigema Verwaltung GmbH",
"register_court": "Stuttgart",
"register_number": "HRA 740365",
"vat_id": "DE144846566",
"social_profiles": [
"https://facebook.com/trigema",
"https://www.instagram.com/trigema_de/",
"https://www.tiktok.com/@trigema_de",
"https://www.linkedin.com/company/trigema-w-grupp-kg",
"https://www.youtube.com/@TRIGEMAtv",
"https://instagram.com/trigemafashion",
"http://www.facebook.com/TRIGEMA",
"https://www.youtube.com/user/TRIGEMAtv",
"https://twitter.com/TRIGEMA"
],
"status": "ok",
"legal_form": "KG",
"result": "ROW"
}

Every field, and where it is read from:

FieldWhat it is
pageIdThe site's bare domain, taken from the start URL's hostname. Also the key rows are de-duplicated on.
pageUrlThe page actually read for this site: the imprint/legal-notice URL when one was found, else the start page that was fetched.
titleThe <title> text of the page that was read.
emailThe page's own-domain contact mailbox. Department mailboxes (privacy, press, careers, accessibility) and regulator addresses are never returned: they answer a function, not a contact. A page that lists only those yields null.
phoneThe page's tel: link normalised to E.164 (+497475880), else a Tel:/Phone: line in the text.
websiteThe site's root URL (https://<domain>), derived from the start URL's hostname. Never null.
websitesThe site root plus every non-social URL the page's JSON-LD Organization lists under sameAs. Social links never land here; they go to social_profiles.
domainThe site's hostname without www., taken from the start URL.
imprint_urlThe URL of the imprint/legal-notice page the site links to, followed from the fetched page and read for the company fields. Null when none was found.
company_nameThe registered company name: the first company-shaped line in the imprint body (GmbH, AG, SE, Ltd. …), else the page's JSON-LD Organization name. Never invented from the domain; null when nothing qualifies.
streetThe street-and-number line of the postal address stated in the imprint body.
postal_codeThe postal code in the address block of the imprint body. Only counted near the street or register lines, so a price like "1398" elsewhere on the page is not mistaken for one.
cityThe city named beside the postal code in the imprint body's address.
countryThe country the imprint body names, as a two-letter code (DE, AT, CH …), or taken from the VAT ID prefix. Never guessed from the domain, so it is null on pages that do not name one.
managing_directorThe managing director(s) or other legally responsible person(s) named on the imprint's Geschäftsführer: / Vertreten durch: / Vorstand / Managing Director: line. Multi-line lists are kept whole, so one name is never mistaken for the list.
register_courtThe commercial-register court the imprint names (Registergericht / Amtsgericht / "registered at").
register_numberThe commercial-register number the imprint carries (HRB / HRA …).
vat_idThe VAT identification number the imprint states (USt-IdNr / VAT ID), whitespace stripped. For example DE144846566.
social_profilesEvery social-media profile linked anywhere on the page: anchors to known social hosts plus the JSON-LD Organization's sameAs links. Null when none are linked.
statusThis source's per-URL verdict: ok, no_imprint_found, fetch_failed, bad_url, timeout, js_required, search_failed or aborted, meaning why a row has no company data. Any verdict but ok is free (see result).
legal_formThe entity's registered legal form parsed from the company name: AG, GmbH, SE, KGaA, SE & Co. KGaA, e.V.… Null when the name declares none.
resultROW on a filled row (billed); ITEM_STATUS on a per-site miss (pushed so you see the verdict, never billed); PROFILE_NOT_FOUND and STOPPED_EARLY on the run-level status rows described under Output.

Fields that appear only on a status row:

FieldWhat it is
reasonWhy the run returned no rows, why it stopped early, or, on a per-site miss, the detail behind status (for example fetch_failed carries HTTP 403).
rowsFetchedHow many rows the source handed over before de-duplication and the cap.
rowsReturnedHow many data rows are in the dataset (0 on an empty result; the count before the charge limit on STOPPED_EARLY).
rowsRemainingHow many fetched rows were not returned (0 on an empty result).

In the Console, the dataset's Overview view shows the columns a buyer reads first. The "All fields" view and every export carry the full contract. A null cell means that site did not publish the value, not that the field is missing.

How much does it cost?

This Actor bills per profile-returned event: $0.00496. One profile-returned event is one site row written to your dataset whose status is ok.

A row reporting no_imprint_found, fetch_failed, timeout, js_required, bad_url or search_failed is pushed as ITEM_STATUS: visible in the dataset, never billed. You do not pay for this Actor's inability to read a site.

What that looks like in sites, at the measured 60% fill rate:

  • 100 sites → ~60 filled rows → ~$0.30
  • 1,000 sites → ~600 filled rows → ~$2.98
Filled rows (status: ok)profile-returned charge
100$0.496
1,000$4.96
10,000$49.60

Why this one

Measured against the most-used alternative on this shelf, run on 2026-09-12:

  • A row costs $0.00496. The most-used alternative on this shelf charges $0.005 a row plus $0.04 to start.
  • A run costs $0.00005 to start. The sellers on this shelf that bill a start fee charge $0.04–$0.08.
  • A miss is free and explained. The row says why the site yielded nothing, and it is never billed.
  • The fill rate is measured, not promised: 60% of 100 sites this Actor had never seen, on the platform build a buyer's run uses. No seller on this shelf publishes one.
  • Every row carries imprint_url and pageUrl. The page each value was read from is on the row.

Search mode is bring-your-own-key: searchQueries with your own searchApiKey (and searchCx for Google) pay your own API quota and nothing on this side. When the Actor's configured key resolves the query instead, the run bills one search-page event: $0.005, one official search-API call at its list price. A query with no key returns a free search_failed row.

Apify also bills its own apify-actor-start event once per gigabyte of memory allocated: $0.00005 at this Actor's size. A single-domain lookup costs about half a cent total.

What is not charged:

  • ITEM_STATUS miss rows, PROFILE_NOT_FOUND and STOPPED_EARLY status rows.
  • Start URLs skipped and rows dropped by the exclusion list (excluded in RUN_SUMMARY).
  • Duplicate rows dropped on pageId before anything is pushed.
  • The RUN_SUMMARY entry in the key-value store.

How do I use German Impressum Contact Scraper?

  1. Open the Actor's Store page and press Try for free / Start.
  2. In Start Urls, list the sites to read: one URL per line, a site's root or its imprint page itself. Or skip the list entirely. Put terms in Search queries and the Actor resolves them to domains through an official search API.
  3. Optionally lower or raise Maximum items (default 100). Adjust the proxy (datacenter by default; a site that blocks it is retried once through residential). Switch the headless-browser fallback off for cheap list runs. Fill Exclude with domains and names this run must not return.
  4. Press Start. Rows land in the dataset as they are written. The key-value store's RUN_SUMMARY entry carries the run's counts when it finishes.

Example input:

{
"startUrls": [
{ "url": "https://www.trigema.de" },
{ "url": "https://www.mymuesli.com" },
{ "url": "https://www.bosch.de" }
],
"maxItems": 100
}

Or search mode, with no list required:

{
"searchQueries": ["site:.de GmbH Impressum Maschinenbau"],
"searchEngine": "brave",
"searchApiKey": "<your Brave Search API key, required — you bring your own>"
}

Or run it through the Apify API:

curl "https://api.apify.com/v2/acts/Pradio~imprint-contact/run-sync-get-dataset-items?token=<YOUR_APIFY_TOKEN>" \
-X POST -H "Content-Type: application/json" \
-d '{"startUrls":[{"url":"https://www.trigema.de"}]}'

Input

InputTypeDefaultWhat it does
startUrlsarrayprefilled with https://www.trigema.deThe sites to read, one output row per entry.
searchQueriesarraySearch terms resolved to domains through an official search API, then read like startUrls entries.
searchEnginestringbravebrave (Brave Search API) or google (Google Custom Search JSON API; needs searchCx).
searchApiKeystringYour own key for the chosen engine, required for searchQueries. No key is configured for you, so a query with no key returns a free search_failed row.
searchCxstringGoogle programmable engine ID, required only for searchEngine: "google".
proxyConfigurationobjectdatacenter Apify proxyHow site requests are proxied. Datacenter first; a site that answers with a block page is retried once through residential. Configure RESIDENTIAL groups to proxy every request that way.
useBrowserbooleantrueRender pages that answer plain requests with a JavaScript shell. Costs more memory and seconds per hit.
maxItemsinteger100The most rows one run returns. Fetching and pushing stop there and the log notes the cap. Minimum 1.
maxDomainsPerSearchQueryinteger20The most domains one searchQueries entry may resolve to, so a broad query cannot starve the ones after it.
excludearrayDomains and names this run must not return, one entry per line. A domain skips its start URLs before any fetch; a company or person name drops the row that carries it. Counted under excluded in RUN_SUMMARY.

startUrls

Each entry is { "url": "…" } or a bare string; https:// is added when it is missing. Give it a site's root. The Actor fetches that page. If it is not itself an imprint, the Actor finds the site's own imprint link (same domain, by URL or by link label) and reads that page instead. It follows up to two hops, and tries the contact page when the homepage carries no link. You can also hand it the imprint URL directly. One row comes back per start URL, whatever the outcome.

exclude

One entry per line. An entry that is a domain, like dm.de or a full URL, skips every start URL on that host or a subdomain of it, before any request is made. Any other entry is read as a name. A fetched row whose company_name or managing_director carries it is dropped: not pushed, not billed. The Actor's own exclusion list is applied the same way on every run. See Personal data for how a person or company joins it.

Output

A run writes two kinds of things:

  • Data rows in the default dataset, one per start URL. Each carries every contract field and result: "ROW". The per-row status field tells a filled row (ok) from a site that yielded nothing (no_imprint_found, fetch_failed, timeout, js_required, bad_url, search_failed, aborted). A miss row carries result: "ITEM_STATUS" and is never billed. Rows are de-duplicated by pageId: two start URLs on the same domain return one row.
  • One status row, only when there is something to report. A run that pushes no data rows ends with one PROFILE_NOT_FOUND row carrying reason, rowsFetched, rowsReturned and rowsRemaining, never an empty dataset that could mean "nothing found" or "it broke". A run cut short by the charge limit ends with a STOPPED_EARLY row saying how many rows were returned and how many were not. Neither is charged.

The key-value store's RUN_SUMMARY entry carries rowsFetched, rowsPushed, rowsCharged, duplicatesDropped, excluded and stoppedEarly for every run, alongside the input and start/finish timestamps. That is how a short run and a broken one are told apart.

A zero result is an answer, not silence: one PROFILE_NOT_FOUND row, uncharged, with rowsFetched telling you whether the source handed over anything at all.

What can you do with the data?

  • Build a B2B contact list you can defend. Every email and phone number comes off the company's own legally required disclosure page, not a third-party guess. The row keeps imprint_url, so you can show where each value was read.
  • Verify who is behind a site before you pay it. company_name, register_court and register_number are the identifiers a court or a contracts team asks for. A supplier list of domains becomes a list of registered entities in one run.
  • Enrich a domain list into company records. Feed a CRM export of websites in, get legal names, registered addresses and managing directors out, and join back on domain.
  • Find the real contact for outreach. status separates sites that answered from sites that did not. The follow-up list is only the rows where there is something to follow up.

Use German Impressum Contact Scraper with AI agents

$claude mcp add --transport http apify "https://mcp.apify.com?tools=Pradio/imprint-contact"

Paste that line to give an MCP-capable agent this Actor as a tool. It can then hand the agent a list of sites and get imprint rows back.

Personal data

A row can name a person: a managing director printed on a company's own legal-notice page. This section says plainly what the product is for, where the data comes from, and how removal works.

  • Purpose. For identifying and verifying a company and reaching it through the business contact details it publishes. Not for building people databases, profiling, or marketing to individuals. You supply the domains. You are the controller of the rows your runs collect, you owe your own privacy notice, and each named site's own terms still apply to you.
  • Transparency and source. Every row comes from the company's own legal-notice page, published under its duty to identify itself and its representatives. A row may carry a representative's name and role exactly as printed there, plus the company's published contact channels. Every row carries imprint_url and pageUrl, so the source of every value is visible. The publisher keeps no rows: runs and datasets live in your Apify account and belong to you.
  • Exclusion. A person or company that wants its imprint left out can ask: open an issue on this Actor's Issues tab in the Apify Console. A request is honoured through the Actor's exclusion list, which every run reads at start. The domain is skipped before any fetch, and a fetched row naming the company or person is dropped. The exclude input applies the same mechanism to your own list. Every skip and drop is counted in RUN_SUMMARY under excluded.

Release notes

  • 0.2.34: harder reads on app-shell sites — a render that returns only the shell waits for hydration once, then escalates to residential like a refused request does.
  • 0.2.20: the exclude input and the Actor's own exclusion list, read at the start of every run. Domains skip their start URLs; names drop the row that carries them. Counted under excluded in RUN_SUMMARY.
  • 0.2.17: country now fills from the VAT-ID prefix when the page names no country. Register filings no longer appear inside director names.
  • 0.2.15: a per-query domain cap in search mode, so one broad query cannot starve the ones after it.
  • 0.2.14: the drawn listing icon.
  • 0.2.12: a separate contact_person field was reviewed and declined. Representatives appear only as printed on the page, inside managing_director.
  • 0.2.6: client-redirect shims, a tighter register-court boundary, name and address parsing polish.
  • 0.2.4: parser fixes measured on a second, larger run over German company sites; datacenter-first proxy with residential only when a site earns it; bring-your-own-key search made honest.
  • 0.2: unbilled misses, search mode, proxy escalation and the browser fallback.

Limits

  • Coverage is measured on the platform, not total: 60%. On 100 German company sites (DAX, MDAX and SDAX members, every one new to this build), run as the deployed build through the same proxied egress a buyer's run uses: 60 came back filled; 20% refused the fetch outright — bot walls, dead domains; 14% answered but exposed no notice; 6% timed out on the proxied path. Each such row says its status and is unbilled. Of the rows that resolved: company name 98%, register number 75%, register court 62%, VAT ID 42%, email 60%, directors 68%.
  • The vocabulary is German- and English-first. A site that names its notice something outside the list under Features is reported no_imprint_found, not misread.
  • A field the page does not publish is null; nothing is invented. company_name is null rather than guessed from the domain. country needs a named country or a VAT-ID prefix. email is the site's own-domain general mailbox or null, because a department's mailbox is not a contact.
  • One notice page per domain, and a refusal ends it. The Actor reads a site's imprint page, plus the homepage to locate it, and nothing else on the host. A refused request is the answer, not a prompt for more attempts or a way around. An input with no usable URL fails the run loudly, so you always learn which of the two happened.

Troubleshooting

I passed 50 URLs and got 47 rows. Where did three go? Rows are de-duplicated by pageId, the site's domain. Two start URLs on the same domain, say dm.de and www.dm.de/shop, return one row between them. RUN_SUMMARY.duplicatesDropped says how many went that way. maxItems caps the total. RUN_SUMMARY.excluded counts any that your exclude list skipped.

A row has result: "ITEM_STATUS" and almost every field is null. Look at status and reason. no_imprint_found means the site answered but no imprint page was found on it. fetch_failed means the page could not be retrieved (the HTTP status is in reason). js_required means the page only renders in a browser (turn useBrowser on; it is on by default). timeout means the host never answered. bad_url means the entry could not be parsed. These rows are returned free. Filter on status: ok or result: ROW when you only want billed rows.

The dataset holds a single row saying PROFILE_NOT_FOUND. The run pushed no data rows, for example because it was aborted before the first site answered. reason and rowsFetched on that row say what the source handed over. The row is not charged. It is the difference between "nothing was there" and an empty dataset you would have to second-guess.

The last row says STOPPED_EARLY. Your charge limit was reached mid-run. rowsReturned and rowsRemaining say how many fetched rows made it out and how many did not. Raise the limit and re-run to see the rest. Only the returned rows were billed.

FAQ

Can I use integrations with German Impressum Contact Scraper? Yes. Like every Apify Actor it plugs into Apify's integrations: Zapier, Make, Google Sheets, webhooks. It can also run on a schedule. A scheduled run over the same site list re-reads each imprint page and hands you the fresh rows.

Can I use German Impressum Contact Scraper with the Apify API? Yes. The curl line under "How do I use" is the whole call: POST the input to acts/Pradio~imprint-contact/run-sync-get-dataset-items with your token and the dataset rows come back in the response. The apify-client libraries for JavaScript and Python wrap the same call.

Can I use German Impressum Contact Scraper through an MCP server? Yes. The line in "Use with AI agents" registers it with an MCP-capable agent through Apify's hosted MCP server, no local install needed.

Is it legal to scrape imprint pages? Imprint and Impressum pages are disclosures companies are legally required to publish. Each page is fetched only on a path its site's robots.txt allows, and there is a 400 ms gap between requests to the same host. That said, the contact data you collect is yours to handle lawfully. GDPR and local rules still apply to how you store and use it. The Personal data section above says what this product is for and how a company or person can ask to be left out.

Report a problem

Something off, a site that parses wrong, a field that should be there? Open an issue on this Actor's Issues tab in the Apify Console. That is the fastest way to get it fixed, and the report is never a bother.

Not affiliated

This Actor is not affiliated with, endorsed by, or sponsored by any of the sites it reads. Imprint and legal-notice pages belong to their operators. The tool reads what each site publishes and nothing more.