Handelsregister Scraper: German Company Register avatar

Handelsregister Scraper: German Company Register

Pricing

from $3.75 / 1,000 company records

Go to Apify Store
Handelsregister Scraper: German Company Register

Handelsregister Scraper: German Company Register

Search the official German company register (handelsregister.de) by company name, keywords or register number. Returns registered name, legal form, court, register type and number, seat, status and former names. No officers, no sole traders, and never more than the portal's 60 requests an hour.

Pricing

from $3.75 / 1,000 company records

Rating

0.0

(0)

Developer

Enis Bodlli

Enis Bodlli

Maintained by Community

Actor stats

0

Bookmarked

2

Total users

1

Monthly active users

3 days ago

Last modified

Share

This Handelsregister scraper searches the official German company register portal (handelsregister.de) by company name, keywords or register number and returns one row per company: registered name, legal form, register court, HRB or HRA number, seat, status and former names. It is for teams that check German companies (KYC and supplier onboarding, CRM clean-up, lead lists) and want the register's identity data without personal data: no managing directors, no birth dates, no sole traders. To try it, leave the sample input and click Start: the run takes about ten seconds.

  • Company identity from the source of record. Every row comes from the register portal of the German federal states, not from a copy: court, register type and number, the full citation (Amtsgericht Berlin (Charlottenburg) HRB 158855), seat, federal state and whether the register sheet is current or closed.
  • Company-level data only. The output has no field for a person. Sole traders, whose registered name is a person's name, are left out and counted.
  • The portal's hourly limit is kept and shown. The portal's terms allow 60 searches an hour. The Actor counts every request it sends, waits when the hour is full, and reports the highest number of requests in any hour in the run summary.

What a record looks like

{
"query": "Brauerei",
"position": 4,
"found": true,
"name": "Brauerei Keesmann OHG",
"legalForm": "OHG",
"registerCourt": "Bamberg",
"registerType": "HRA",
"registerNumber": "8267",
"registerId": "Amtsgericht Bamberg HRA 8267",
"federalState": "Bayern",
"seat": "Bamberg",
"status": "active",
"formerNames": ["Brauerei Keesmann K.G."],
"availableDocuments": ["AD", "CD", "HD", "DK", "UT", "VÖ", "SI"],
"sourceUrl": "https://www.handelsregister.de/rp_web/normalesuche/welcome.xhtml",
"scrapedAt": "2026-10-07T21:39:37.670Z"
}

How to search the German company register

  1. Put company names or keywords under Company names or keywords, one search per line. Through the API, pass them as the array queries.
  2. Choose How to match the words. exactName finds a company by its full registered name, legal form included (Zalando SE). allWords and anyWord are keyword searches (Brauerei with seat Bamberg).
  3. Optionally narrow every search of the run by Register type, Register court or Seat, or switch Include closed entries on.
  4. To look up a register number instead, leave the names empty and fill Register number, Register type and Register court (158855, HRB, Berlin).
  5. Click Start. Each search's rows are saved as soon as that search is answered. Open the Output tab and export JSON, CSV or Excel, or read the dataset through the API.

How long a run takes

The portal's terms of use do not allow more than 60 searches or company retrievals an hour. The Actor is stricter with itself: it counts every HTTP request, and one search is two requests (the search and the result page it redirects to), plus one request to open a session. With the default maxRequestsPerHour of 55 that is about 27 searches an hour, 29 at the maximum of 60. Requests go out one at a time, at least 1.5 seconds apart.

Searches in one runDuration at the default setting
up to 27about 3 minutes
100about 3 hours, almost all of it waiting
1,000about 37 hours

One keyword search can return up to 100 companies, so a keyword run delivers far more records an hour than a list of exact names. When the hour is full the status message says so, with the time the next request goes out. When the list needs more time than the run's timeout allows, the first status message says how many searches fit and what timeout the whole list needs. The Actor starts no search with less than 20 seconds left and does not wait into the timeout. Searches the timeout leaves out are counted in searchesNotRun, and the run still ends as succeeded: everything it stored is complete. A resurrected run continues where it stopped; or raise the timeout in the run options and run the rest.

Pricing

You pay per company record: a dataset row with "found": true.

Apify planPer 1,000 company recordsPer record
Free, Bronze$5.00$0.005
Silver$4.40$0.0044
Gold$3.75$0.00375

Plus Apify's standard $0.00005 per run start. Platform usage is included, so there is nothing else to pay, also while a run waits for the portal's hourly limit.

  • 200 company records cost $1.00 on the Free and Bronze plans, $0.88 on Silver and $0.75 on Gold.
  • A list of 100 exact names, of which 92 are found, 5 are not in the register and 3 are sole traders: 92 charges, $0.46 on the Free and Bronze plans. The other 8 searches each get a row with "found": false at no cost.
  • One keyword search that returns 100 companies costs $0.50 on the Free and Bronze plans. Set maxResultsPerQuery or maxResults to cap it.

Not charged: a search without a match, sole traders that were left out, and a company that a second search of the same run returns again (its row is stored, the charge is made once per run).

What a run that stops early costs. A record is charged at the moment its row is saved, and only then. A run that fails, times out, is aborted or is moved to another server has charged exactly the company rows in its dataset. When it is restarted or resurrected it continues where it was: finished searches are not asked again, and at most one search is asked a second time without storing or charging its rows twice.

You can set a maximum charge per run. The Actor then starts no search that the limit has no room for, stops in the middle of a result list when the limit is reached, and says so in its status message.

Input example

Look up companies by their exact registered names:

{
"queries": ["Zalando SE", "BASF SE"],
"searchMode": "exactName",
"maxResultsPerQuery": 10
}

Keyword search in one city:

{
"queries": ["Brauerei"],
"searchMode": "allWords",
"city": "Bamberg",
"maxResultsPerQuery": 25
}

One register number:

{
"registerNumber": "158855",
"registerType": "HRB",
"registerCourt": "Berlin"
}
FieldWhat it does
queriesCompany names or keywords, one search each. Up to 1,000 per run, 200 characters each. Repeated lines (also in another spelling of upper and lower case) are searched once.
searchModeallWords (default): the name contains every word. anyWord: at least one. exactName: exactly this registered name.
maxResultsPerQuery1 to 100 companies per search, default 10. One search reads one result page of the portal (10, 25, 50 or 100 rows).
registerTypeall (default), HRA, HRB, GnR, PR, VR or GsR.
registerNumberDigits only. Works without a name; add the register type and court to get one entry.
registerCourtThe court as the portal names it (München, Köln, Berlin (Charlottenburg)); Berlin or Muenchen work too. An unknown or ambiguous court (Frankfurt) ends the run before any request, with the nearest names in the message.
cityOnly companies with their seat or a branch in this place.
includeDeletedAlso return entries whose register sheet is closed. Default off.
maxResultsThe run stops when this many company records are stored. Default 1,000.
maxRequestsPerHour10 to 60, default 55. Lower it when other runs of yours use the portal in the same hour.

The filters apply to every search of the run.

Output example

[
{
"query": "BASF SE",
"position": 1,
"found": true,
"name": "BASF SE",
"legalForm": "SE",
"registerCourt": "Ludwigshafen a.Rhein (Ludwigshafen)",
"registerType": "HRB",
"registerNumber": "6000",
"registerId": "Amtsgericht Ludwigshafen a.Rhein (Ludwigshafen) HRB 6000",
"federalState": "Rheinland-Pfalz",
"seat": "Ludwigshafen am Rhein",
"status": "active",
"formerNames": [],
"availableDocuments": ["AD", "CD", "DK", "UT", "VÖ", "SI"],
"sourceUrl": "https://www.handelsregister.de/rp_web/normalesuche/welcome.xhtml",
"scrapedAt": "2026-10-07T21:40:21.368Z"
},
{
"query": "Brauerei",
"position": 2,
"found": true,
"name": "Brauerei Fässla Verwaltungs GmbH",
"legalForm": "GmbH",
"registerCourt": "Bamberg",
"registerType": "HRB",
"registerNumber": "6858",
"registerId": "Amtsgericht Bamberg HRB 6858",
"federalState": "Bayern",
"seat": "Bamberg",
"status": "active",
"formerNames": [],
"availableDocuments": ["AD", "CD", "DK", "UT", "VÖ", "SI"],
"sourceUrl": "https://www.handelsregister.de/rp_web/normalesuche/welcome.xhtml",
"scrapedAt": "2026-10-07T21:39:37.670Z"
},
{
"query": "Qxzvwk Nichtvorhanden 918273",
"position": null,
"found": false,
"name": null,
"legalForm": null,
"registerCourt": null,
"registerType": null,
"registerNumber": null,
"registerId": null,
"federalState": null,
"seat": null,
"status": null,
"formerNames": [],
"availableDocuments": [],
"sourceUrl": "https://www.handelsregister.de/rp_web/normalesuche/welcome.xhtml",
"scrapedAt": "2026-10-07T21:40:24.602Z"
}
]

Every field is present in every row. null means the portal did not say; lists are empty, never missing.

FieldMeaning
query, positionThe search the row answers and the row's place in the portal's result list. Together they are unique within a run. Positions can have gaps where sole traders were left out.
foundtrue for a company (charged). false for the one row that says a search returned no company (not charged).
nameThe registered name as the register prints it.
legalFormDerived from the registered name, not read from the register: GmbH, gGmbH, UG (haftungsbeschränkt), AG, SE, KGaA, OHG, KG, eG, e.V., PartG, PartG mbB, eGbR, EWIV, VVaG, Ltd., or a combination such as GmbH & Co. KG. null when the name carries none of them.
registerCourt, registerType, registerNumberThe court that keeps the entry, the register (HRB, HRA, GnR, PR, VR, GsR) and the number, digits only.
registerIdThe full citation as the portal prints it. It identifies the register entry.
federalState, seatThe federal state of the court, in German, and the registered seat.
statusactive (the portal's "aktuell": the register sheet is current, which says nothing about insolvency or liquidation), closed (the sheet is closed: the company was deleted or moved to another court) or deleted. Any other wording of the portal is passed on unchanged.
formerNamesEarlier registered names from the portal's history list. Names of former sole traders are left out.
availableDocumentsWhich document types the portal offers for the entry at that moment (AD, CD, HD, DK, UT, VÖ, SI). The Actor lists them; it does not retrieve them.
sourceUrlThe portal's public search form. Result pages have addresses that stop working when the session ends, so they are not returned.
scrapedAtWhen the result was read, ISO 8601 in UTC.

The record RUN_SUMMARY in the run's key-value store has the totals for programs that cannot read a log: recordsStored, chargedRecords, notFoundRows, soleTradersSkipped, searchesNotRun and stoppedBecause, requestsMade, mostRequestsInAnyHour (never above maxRequestsPerHour), secondsWaited, the input entries that were skipped, and under searches the outcome of every search with the number of matches the portal reported.

Limits

What this Actor leaves out on purpose:

  • No people. Officers, managing directors, representatives and partners are not returned: no names, no birth dates, no home towns, and no count either, because the search result carries none. This is the rule of the Actor, not a missing feature.
  • No sole traders. Entries named with e.K., e.Kfm., e.Kfr., "eingetragener Kaufmann", "eingetragene Kauffrau", "Inh." or "Inhaber" are skipped and counted in soleTradersSkipped, because their registered name is a person's name. An HRA entry is kept only when its name says it is a partnership (KG, OHG, EWIV, or a company as general partner as in "GmbH & Co."); any other HRA entry is treated as a sole trader, so a few partnerships and public bodies with unusual names are left out with them.
  • No register content from the documents. Street address, share capital, business purpose, representation rules, the legal form as registered and the founding date are not returned. They sit in the register document of each company: one more retrieval per company against the hourly limit, and that document names people.
  • No document downloads. No structured XML and no PDF printouts (AD, CD, HD, DK, UT, VÖ, SI). Only the list of types on offer is returned.
  • No proxy setting. Plain requests from one address. Spreading requests over several addresses would defeat the portal's hourly rule.
  • No speed above the portal's limit. About 27 searches an hour, no parallel sessions; 1,000 exact lookups take about 37 hours.
  • No filters by federal state, legal form or postal code. They belong to the portal's advanced search; this Actor uses the normal search. federalState and legalForm are in every row, so you can filter afterwards.
  • No phonetic search, no Standby HTTP endpoint, no monitor mode that returns only new or changed companies, and no EUID.
  • No country field: every record is German.
  • No former seats, only former company names.

What the source limits:

  • At most 100 matches per search. The portal lists no more, whatever the real number (seen on 2026-10-07 for a one-word search). Such a search is flagged truncated in the run summary with a note to narrow it by city, court or register type. One search reads one result page.
  • The hourly limit is counted per run. Two runs of yours in the same hour each count for themselves: lower maxRequestsPerHour or run them one after another. Apify's servers are shared, so the portal can refuse a run for traffic that was not yours.
  • A refusal is final. When the portal answers 403, shows a challenge page or keeps answering 429, the run stops, keeps what it stored, ends as failed and says so. Nothing is done to get around it. A request that meets a server error, or a page that breaks off before its end, is tried up to four times with growing pauses, and one that gets no answer at all twice; after three searches in a row without an answer the run stops asking. Every one of these attempts counts against the hourly limit and is named in the log.
  • availableDocuments is empty while the register system of a federal state is offline. The other fields are not affected.
  • The register is the source, not this Actor. Rows are what the portal's search returned at scrapedAt. For a legally binding extract, use the portal itself.

FAQ

The German commercial register is public by law: section 9 (1) of the Commercial Code (HGB) lets anyone inspect it for information purposes, and the portal's search needs no login. The portal's terms of use (read on 2026-10-07) add two rules. No more than 60 searches or company retrievals an hour: the Actor keeps that inside each run. And no systematic retrieval to build, extend or update a parallel copy of the register or of a part of it: use the Actor to look up and check companies, not to copy the register. The terms also bind what you do with retrieved data to data-protection law; this Actor returns company-level data only. You are responsible for how you use the data and for keeping the hourly limit across your own runs. This is not legal advice.

Why does my run say it is waiting?

The hour is full. The status message gives the number of requests sent in the last hour and the time the next one goes out. Nothing is lost while it waits, and waiting costs you nothing.

Why is a company missing?

  • exactName needs the full registered name with its legal form: Zalando SE, not Zalando.
  • It may be a sole trader (see Limits); soleTradersSkipped in the run summary counts them.
  • Its register sheet may be closed: switch includeDeleted on.
  • The search may have more matches than were returned: check truncated and the notes under searches in the run summary, and raise maxResultsPerQuery or narrow the search.

Why do I get several rows for one name?

The same name can be registered at several courts, and with includeDeleted a company that moved appears with its closed sheet at the old court and its current one at the new court. registerId tells them apart.

Why did the run fail?

The status message says why in one sentence: an input that has nothing to search for, a court the portal does not list, a refusal by the portal, or a portal that did not answer. Rows stored before the failure stay in the dataset and are the only ones charged. RUN_SUMMARY lists each search with its outcome.

Can I get managing directors, shareholders or addresses?

No. See Limits: this Actor returns the identity of the company and nothing about people.

Can I call it from code or an AI agent?

Yes. Start it through the Apify API or the Apify MCP server; the input, the dataset and the run summary each have a schema that describes every field.

Where do I report a problem?

On the Issues tab of this Actor. Include the run ID and the search that went wrong.

More Actors from this developer

Company registers:

Contacts and lists:

Jobs: