Was dieser Artikel NICHT ist
Ein Tutorial über eine magische kostenlose Handelsregister-Bulk-API des Bundes. Die gibt es nämlich nicht. Wenn du das hier liest weil du dachtest "ach, das Handelsregister hat bestimmt eine offizielle REST-API wo ich massenhaft Firmendaten ziehen kann" — sorry, Fehlanzeige.
Was es wirklich gibt: kommerzielle APIs von Drittanbietern, manuelle Portal-Nutzung mit sorgfältiger Automatisierung, das EU-weite BRIS-System für grenzüberschreitende Suchen. Und genau die schauen wir uns jetzt an — mit Code, mit Kosten, mit rechtlichen Grenzen.
Hinweis: Dieser Artikel zeigt die technische Seite des Datenabrufs. Für die anschließende Verarbeitung dieser Daten im Rahmen einer Lead-Pipeline und die DSGVO-Compliance dabei siehe B2B Lead Automation DSGVO-konform. Für den größeren Kontext wie so eine Pipeline insgesamt aussieht: 500 B2B-Leads legal mit KI generieren.
Die Realität — drei Wege, keiner ist perfekt
Option 1: Kommerzielle APIs
Mehrere Anbieter haben das Handelsregister und andere öffentliche Quellen bereits aggregiert und bieten strukturierten API-Zugang:
- handelsregister.ai — REST-API mit Echtzeit-Daten, CRM-Integrationen
- OpenRegister — API plus Batch-Exports für große Datenmengen
- Northdata — umfassende Firmendaten inkl. Vernetzungen, Finanzdaten
- Companyinfo.de — Register + wirtschaftliche Eigentümer + PEP-Checks
- Viaductus — Handelsregister-API mit KI-Analyse
Kostenmodell: Pay-per-Request (meist 0,10–0,50 € pro Abfrage) oder Abo-Modelle ab ~100 €/Monat für höhere Volumina. Batch-Exporte (kompletter Datenbestand) kosten deutlich mehr — realistisch ab 1000 € aufwärts, je nach Umfang.
Vorteil: Saubere Daten, strukturiert, rechtlich unbedenklich (der Anbieter hat die Daten bereits verarbeitet und lizenziert sie weiter), aktuelle Updates.
Nachteil: Kostet Geld. Für einmalige Recherchen überdimensioniert.
Python-Beispiel mit handelsregister.ai (Stand 2026 — vor Nutzung aktuelle Doku prüfen):
import requests
# API-Key über handelsregister.ai registrieren
API_KEY = "dein_api_key_hier"
BASE_URL = "https://api.handelsregister.ai/v1"
def fetch_company_by_name(company_name: str):
"""
Sucht Firma nach Name im Handelsregister.
Gibt strukturiertes JSON zurück.
"""
headers = {"Authorization": f"Bearer {API_KEY}"}
params = {"name": company_name, "limit": 10}
response = requests.get(
f"{BASE_URL}/companies/search",
headers=headers,
params=params
)
if response.status_code == 200:
return response.json()
else:
raise Exception(f"API-Fehler: {response.status_code} - {response.text}")
# Beispiel-Aufruf
result = fetch_company_by_name("Mustermann GmbH")
for company in result.get("companies", []):
print(f"Firma: {company['name']}")
print(f"Sitz: {company['location']}")
print(f"HRB: {company['register_number']}")
print(f"Geschäftsführung: {', '.join(company.get('management', []))}")
print("---")
Rate-Limits: Meist 100–1000 Requests/Stunde je nach Plan. Bei Batch-Operationen über mehrere Tausend Firmen: Batch-Export-Option nutzen statt einzelner Calls.
Option 2: Manuelle Portal-Nutzung + sorgfältige Automatisierung
Das offizielle Portal www.handelsregister.de (bzw. www.unternehmensregister.de) bietet seit 2022 kostenlose Abrufe von Handelsregisterauszügen. Es gibt aber keine offizielle Bulk-API.
Was man machen kann: Einzelne Suchen über das Portal, mit Python und Playwright automatisiert, unter strikter Beachtung von Rate-Limits und robots.txt.
Rechtliche Einordnung: Das Portal ist öffentlich zugänglich, Daten sind öffentlich. Aber: Massenhaftes automatisiertes Abfragen kann gegen die Nutzungsbedingungen verstoßen und technisch zu IP-Sperren führen. Das ist keine offizielle API-Nutzung, sondern geduldetes Scraping mit engen Grenzen.
Faustregel: Maximal 1 Request alle 5–10 Sekunden. Mehr ist Missbrauch und wird geblockt.
Python-Beispiel mit Playwright (vereinfacht):
from playwright.async_api import async_playwright
import asyncio
import time
async def search_handelsregister_portal(company_name: str, city: str):
"""
Sucht im offiziellen Handelsregister-Portal.
WICHTIG: Nur für Einzelabfragen, nicht für Bulk.
Rate-Limit: max. 1 Abfrage alle 10 Sekunden.
"""
async with async_playwright() as p:
browser = await p.chromium.launch(headless=True)
page = await browser.new_page()
# Zur erweiterten Suche
await page.goto("https://www.handelsregister.de/rp_web/search.xhtml")
# Firma + Sitz eingeben
await page.fill('input[name="schlagwoerter"]', company_name)
await page.fill('input[name="schlagwortOptionen.ort"]', city)
# Suchen
await page.click('button[type="submit"]')
await page.wait_for_load_state("networkidle")
# Ergebnis-Tabelle parsen
rows = await page.query_selector_all('.result-table tr')
results = []
for row in rows[1:]: # erste Zeile = Header
cells = await row.query_selector_all('td')
if len(cells) >= 4:
results.append({
"name": await cells[0].inner_text(),
"sitz": await cells[1].inner_text(),
"registernummer": await cells[2].inner_text(),
"registerart": await cells[3].inner_text()
})
await browser.close()
return results
# Beispiel — MIT 10-Sekunden-Pause zwischen Aufrufen
async def batch_search_with_limits(companies: list):
all_results = []
for idx, (name, city) in enumerate(companies):
print(f"[{idx+1}/{len(companies)}] Suche: {name}, {city}")
try:
result = await search_handelsregister_portal(name, city)
all_results.extend(result)
except Exception as e:
print(f"Fehler bei {name}: {e}")
# KRITISCH: Rate-Limit respektieren
if idx < len(companies) - 1:
print("⏳ Warte 10 Sekunden...")
time.sleep(10)
return all_results
# Nutzung
companies_to_search = [
("Mustermann GmbH", "Berlin"),
("Beispiel AG", "München"),
# ... maximal 20-30 pro Session
]
# asyncio.run(batch_search_with_limits(companies_to_search))
Realistische Größenordnung: Bei 10-Sekunden-Pausen: 6 Firmen/Minute, 360 Firmen/Stunde. Für 500 Firmen brauchst du ~1,5 Stunden Laufzeit. Für 5000 Firmen: 14 Stunden.
Fazit: Machbar für kleine bis mittlere Listen (50–500 Firmen), wenn du Zeit hast. Für Zehntausende Firmen: viel zu langsam, nutze Kommerzielle APIs mit Batch-Export.
Option 3: EU-weites BRIS-System
Das Business Registers Interconnection System (BRIS) verbindet die Handelsregister aller EU-Mitgliedsstaaten über eine zentrale Plattform: e-Justice Portal.
Was es bietet: Grundlegende Firmenexistenz-Checks, grenzüberschreitende Suchen (z.B. deutsche Firma mit französischer Tochter), Informationen zu ausländischen Zweigniederlassungen.
Was es NICHT bietet: Vollständige Finanzdaten, Eigentümerstrukturen, Bulk-Export, eine öffentliche REST-API.
Nutzung: Manuell über das Portal oder über nationale Register-Portale die BRIS einbinden. Für programmatischen Zugriff: nicht direkt verfügbar.
Wann sinnvoll: Wenn du gezielt einzelne EU-Firmen prüfen willst, besonders bei grenzüberschreitenden Sachverhalten. Für Lead-Gen in Deutschland allein: weniger relevant.
Welche Datenfelder bekommst du überhaupt?
Egal welcher Weg — das sind die typischen Felder aus dem Handelsregister:
| Feld | Beschreibung | Immer vorhanden? | |---|---|---| | Firmenname | Offizieller Name laut Register | ✅ Ja | | Rechtsform | GmbH, AG, UG, GmbH & Co. KG, etc. | ✅ Ja | | Sitz | Stadt/Ort der Niederlassung | ✅ Ja | | Registernummer | HRA, HRB + Nummer | ✅ Ja | | Registergericht | Amtsgericht das zuständig ist | ✅ Ja | | Geschäftsführung | Namen der Geschäftsführer | ✅ Meistens | | Gesellschafter | Bei GmbH: Namen, Anteile | ⚠️ Oft, nicht immer vollständig | | Stammkapital | Eingetragenes Kapital | ✅ Ja | | Geschäftszweck | Was die Firma macht | ⚠️ Oft sehr generisch | | Gründungsdatum | Eintragungsdatum | ✅ Ja | | Status | Aktiv, in Liquidation, gelöscht | ✅ Ja |
Was NICHT drin ist:
- E-Mail-Adressen
- Telefonnummern
- Mitarbeiterzahlen
- Umsatzzahlen (außer bei publizierten Jahresabschlüssen, die separat abgerufen werden)
- Website-URLs
Für vollständige B2B-Leads brauchst du Anreicherung — siehe B2B-Leads legal mit KI generieren für die komplette Pipeline inkl. Impressum-Parsing.
Rate-Limits und "Zumutbarkeit"
Bei kommerziellen APIs: Klar dokumentiert, meist 100–10.000 Requests/Stunde je nach Plan. Überschreitung = HTTP 429 oder Throttling.
Beim offiziellen Portal (Scraping): Nicht offiziell dokumentiert, aber:
- 1 Request/10 Sekunden = sicher
- 1 Request/5 Sekunden = Grauzone
- 1 Request/Sekunde oder schneller = wird geblockt, IP-Sperre wahrscheinlich
Technisch: Das Portal hat CAPTCHA-Schutz. Wenn du zu schnell bist, kommt CAPTCHA → dein Script bricht ab. Nutze playwright mit stealth-Plugin um nicht sofort als Bot erkannt zu werden, aber respektiere trotzdem Rate-Limits.
Ethisch: Das offizielle Portal ist für Menschen gebaut, nicht für Bulk-Scraper. Wenn du ernsthaft hunderte oder tausende Firmen abfragen willst: bezahle für eine API statt die öffentliche Infrastruktur zu missbrauchen.
DSGVO-Kurzcheck für Handelsregister-Daten
Sind Handelsregister-Daten personenbezogen? Teilweise ja — die Namen der Geschäftsführer sind personenbezogene Daten.
Darf ich sie speichern/verarbeiten? Ja, unter berechtigtem Interesse (Art. 6 Abs. 1 lit. f DSGVO), weil:
- Die Daten sind öffentlich vom Staat veröffentlicht
- Die Geschäftsführer haben sich bewusst in eine öffentliche Rolle begeben
- Die Nutzung für B2B-Leadgenerierung ist ein legitimes wirtschaftliches Interesse
Was du NICHT darfst:
- Die Daten an Dritte verkaufen ohne rechtliche Grundlage
- Sie für Privatpersonen-Marketing nutzen (nur B2B!)
- Sensitive Daten daraus ableiten (z.B. Gesundheitsdaten, politische Meinungen)
Was du dokumentieren musst:
- Verarbeitungsverzeichnis (Art. 30 DSGVO): Welche Daten, woher, wofür, wie lange
- Datenschutzerklärung: Transparenz über die Verarbeitung
- Berechtigtes Interesse: Abwägung zwischen deinem Interesse und Rechten der Betroffenen
Für die komplette DSGVO-Audit-Dokumentation einer Lead-Pipeline siehe B2B Lead Automation DSGVO-konform.
Disclaimer: Das hier ist keine Rechtsberatung. Bei Unsicherheit konsultiere eine Fachanwältin oder einen Fachanwalt für Datenschutzrecht.
Realistische Kosten — drei Szenarien
Szenario 1: Kleine Liste (50–200 Firmen, einmalig)
- Option: Manuelles Scraping des Portals mit Playwright
- Zeitaufwand: 2–4 Stunden (inkl. Setup)
- Kosten: 0 € (nur deine Zeit)
- Rechtlich: Grauzone, aber bei so kleinen Mengen toleriert
Szenario 2: Mittlere Liste (500–2000 Firmen, quartalsweise Update)
- Option: Kommerzielle API (z.B. handelsregister.ai, OpenRegister) im Pay-per-Use-Modell
- Kosten: ~0,20 € pro Firma × 1000 Firmen = 200 € pro Batch
- Zeitaufwand: 1 Stunde Setup, dann 10 Minuten pro Batch (vollautomatisch)
- Rechtlich: Sauber, API-Nutzung ist lizenziert
Szenario 3: Große Liste (10.000+ Firmen, monatliche Updates)
- Option: Kommerzielle API mit Abo-Modell oder Batch-Export
- Kosten: Abo ab ~500 €/Monat für höhere Volumina, oder einmaliger Batch-Export ~2000–5000 €
- Zeitaufwand: 2–4 Stunden Setup, dann vollautomatisch
- Rechtlich: Sauber
Code-Vorlage: Komplette Pipeline mit handelsregister.ai
Hier eine realistische Implementierung für Batch-Abfragen mit einer kommerziellen API — adaptierbar für jeden der oben genannten Anbieter:
import requests
import csv
import time
from typing import List, Dict
class HandelsregisterAPI:
"""
Wrapper für handelsregister.ai API.
Beispiel-Struktur — vor Nutzung aktuelle Doku prüfen!
"""
def __init__(self, api_key: str):
self.api_key = api_key
self.base_url = "https://api.handelsregister.ai/v1"
self.headers = {"Authorization": f"Bearer {api_key}"}
def search_company(self, name: str, location: str = None) -> List[Dict]:
"""Sucht Firma nach Name (optional mit Ort)."""
params = {"name": name}
if location:
params["location"] = location
response = requests.get(
f"{self.base_url}/companies/search",
headers=self.headers,
params=params
)
if response.status_code == 200:
return response.json().get("companies", [])
elif response.status_code == 429:
raise Exception("Rate-Limit überschritten — warte 60 Sekunden")
else:
raise Exception(f"API-Fehler: {response.status_code}")
def get_company_details(self, company_id: str) -> Dict:
"""Holt vollständige Details zu einer Firma."""
response = requests.get(
f"{self.base_url}/companies/{company_id}",
headers=self.headers
)
if response.status_code == 200:
return response.json()
else:
raise Exception(f"Fehler beim Abruf von {company_id}")
def batch_fetch_companies(
api: HandelsregisterAPI,
company_list: List[tuple],
output_csv: str
):
"""
Batch-Verarbeitung: Liste von (Name, Ort) → CSV mit allen Details.
"""
results = []
for idx, (name, location) in enumerate(company_list):
print(f"[{idx+1}/{len(company_list)}] Suche: {name}, {location}")
try:
# Schritt 1: Suche
matches = api.search_company(name, location)
if not matches:
print(f" ❌ Keine Treffer für {name}")
continue
# Nehme erstes Match (bei Mehrdeutigkeit: manuell nachprüfen)
company_id = matches[0]["id"]
# Schritt 2: Details abrufen
details = api.get_company_details(company_id)
results.append({
"name": details.get("name"),
"legal_form": details.get("legal_form"),
"location": details.get("location"),
"register_number": details.get("register_number"),
"management": ", ".join(details.get("management", [])),
"founding_date": details.get("founding_date"),
"status": details.get("status"),
"business_purpose": details.get("business_purpose", "")
})
print(f" ✅ {details['name']} — {details['register_number']}")
except Exception as e:
print(f" ⚠️ Fehler: {e}")
# Bei Rate-Limit: pausieren
if "429" in str(e):
print(" ⏳ Rate-Limit — warte 60 Sekunden")
time.sleep(60)
# Rate-Limit respektieren (auch ohne 429)
time.sleep(0.5) # 2 Requests/Sekunde = konservativ
# Ergebnisse als CSV speichern
with open(output_csv, 'w', newline='', encoding='utf-8') as f:
if results:
writer = csv.DictWriter(f, fieldnames=results[0].keys())
writer.writeheader()
writer.writerows(results)
print(f"\n✅ {len(results)} Firmen gespeichert in {output_csv}")
# ========== NUTZUNG ==========
# 1. API-Key setzen (registriere bei handelsregister.ai)
api = HandelsregisterAPI(api_key="DEIN_API_KEY_HIER")
# 2. Firmenliste vorbereiten (aus CSV, DB, manuell...)
companies = [
("Mustermann Maschinenbau GmbH", "Stuttgart"),
("Beispiel Metallverarbeitung AG", "München"),
("Test Handel GmbH", "Berlin"),
# ... bis zu 10.000+
]
# 3. Batch-Abfrage starten
batch_fetch_companies(
api=api,
company_list=companies,
output_csv="handelsregister_results.csv"
)
Kosten für 500 Firmen: Bei 0,20 €/Firma = 100 €. Laufzeit: ~5 Minuten.
Was in der Praxis NICHT sauber klappt
- Firmen ohne Handelsregister-Eintrag: Einzelunternehmer, Freiberufler, viele Handwerksbetriebe — die stehen nicht im HR. Für die brauchst du die Handwerkskammer-Register oder Gewerbeanmeldungen (noch schwieriger zugänglich).
- Veraltete Daten: Handelsregister-Änderungen werden oft mit Verzögerung eingetragen. Ein Geschäftsführer der seit 6 Monaten weg ist, kann noch drin stehen.
- Unvollständige Gesellschafter-Infos: Bei verschachtelten Holding-Strukturen kriegst du oft nur die oberste Ebene.
- Bayerisches Sonderregister: Bayern hatte lange ein eigenes System, das ist inzwischen weitgehend harmonisiert, aber manche alte Einträge haben abweichende Strukturen.
Wer profitiert von welchem Weg?
| Profil | Empfehlung | |---|---| | Startup, einmalige Recherche 50–200 Firmen | Manuelles Scraping (kostenlos, aber langsam) | | Agentur, quartalsweise Lead-Gen 500–2000 Firmen | Kommerzielle API Pay-per-Use | | Großer B2B-Player, 10.000+ Firmen, monatliche Updates | API-Abo oder Batch-Export | | Compliance-kritische Branchen (Finance, Legal) | Nur kommerzielle APIs (rechtlich sauber) |
Weiterlesen
Für die komplette Lead-Pipeline (Handelsregister → Webseiten → E-Mails → Anreicherung): 500 B2B-Leads legal mit KI generieren.
Für die DSGVO-Compliance dieser Pipeline: B2B Lead Automation DSGVO-konform.
Für die rechtlichen Grenzen beim Scraping allgemein: DSGVO beim B2B-Scraping — was ist erlaubt?
Eigene Lead-Gen-Pipeline am Bauen? Zone "Sales & Outreach" im Discord — konkrete technische Fragen, kein Marketing-Gelaber.
