Registerabfragen scheitern selten an der Suchmaske, sondern am verzerrten Bild-CAPTCHA davor. Der Ablauf dahinter ist kurz: das CAPTCHA-Bild in derselben Sitzung laden, als Base64 an in.php übermitteln, das Ergebnis abfragen und den erkannten Text zusammen mit den Formulardaten absenden. Alles Weitere ist Session-Hygiene – Cookies behalten, versteckte Formularfelder mitschicken, Weiterleitungen zulassen.
Dieser Leitfaden ordnet die gängigen CAPTCHA-Typen den Portalkategorien zu, zeigt den Ablauf in Python und JavaScript und nennt die Parameter, mit denen die Texterkennung auch bei schlechten Vorlagen stabil bleibt.
Welche CAPTCHA-Typen in Registerportalen auftauchen
Behördliche Auskunftssysteme sind selten auf dem neuesten Stand: Statt reCAPTCHA oder Cloudflare Turnstile läuft dort oft ein selbst gebautes Bild-CAPTCHA, das seit der Inbetriebnahme unverändert ist.
| Portalkategorie | Typisches CAPTCHA | Beispiel für die Abfrage |
|---|---|---|
| Gerichtsaktensuche | eigenes Text-CAPTCHA | verzerrte alphanumerische Folge, 5–6 Zeichen |
| Grundbuch- und Katasterauskunft | Mathe-CAPTCHA | „Was ist 4 + 7?“ |
| Handels- und Unternehmensregister | Bild-Text-CAPTCHA | verzogene Buchstaben mit Linienrauschen |
| Personenstandsregister | reCAPTCHA v2 | Auswahl im Bildraster |
| Baugenehmigungen | einfaches Text-CAPTCHA | vierstelliger Zahlencode |
| UCC-Einträge (US) | eigenes OCR-CAPTCHA | Groß- und Kleinschreibung mit Hintergrundrauschen |
In der DACH-Region ist die Portallandschaft ähnlich fragmentiert: Handelsregister, Vereinsregister, Grundbuchauskunft der Länder und kommunale Ratsinformationssysteme laufen auf sehr unterschiedlichen Plattformen – entsprechend unterschiedlich fällt der Schutz der Suchmaske aus. Prüfen Sie jedes Portal einzeln.
Vor dem ersten Skript: den Rahmen klären
Registerdaten sind öffentlich zugänglich, aber nicht beliebig verwertbar. Vier Punkte, die in Rechercheprojekten regelmäßig zu Nacharbeit führen:
- Nutzungsbedingungen. Viele Auskunftsportale erlauben die Einzelabfrage, untersagen aber den systematischen Abruf oder die Weiterverwertung ganzer Bestände. Das steht in den AGB oder in den Hinweisen zur Nutzung.
- DSGVO. Namen, Anschriften und Geburtsdaten aus Registern sind personenbezogene Daten – ebenso die IP-Adressen in Ihren eigenen Logs. Rechtsgrundlage, Speicherdauer und Löschkonzept gehören geklärt, bevor der erste Datensatz abgelegt wird.
- Gebührenpflichtige Abrufe. Einzelne Auskünfte kosten Geld. Ein Skript, das unbesehen auf „Dokument abrufen“ klickt, erzeugt reale Kosten – trennen Sie Suche und Abruf sauber voneinander.
- Abfragetempo. Viele Portale laufen auf kleiner Infrastruktur; eine Pause von einigen Sekunden je Suche entscheidet oft darüber, ob ein Lauf bis zum Ende durchkommt.
Bild-CAPTCHAs im Suchformular lösen
Der Ablauf ist bei fast allen Portalen identisch:
- Suchseite laden und die Sitzung samt Cookies behalten.
- Die Bild-URL aus dem HTML lesen – meist
id="captchaImage", eine Klassecaptchaoder schlicht einsrc, in dem „captcha“ vorkommt. - Das Bild mit derselben Sitzung herunterladen und als Base64 an CaptchaAI übermitteln.
- Den erkannten Text zusammen mit Suchbegriff und versteckten Formularfeldern absenden.
Die folgende Klasse kapselt genau diese vier Schritte für eine Gerichtsaktensuche:
import requests
import base64
import time
from urllib.parse import urljoin
class PublicRecordsSearcher:
def __init__(self, api_key):
self.api_key = api_key
self.session = requests.Session()
self.session.headers.update({
"User-Agent": "Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36"
})
def search_court_records(self, portal_url, case_number):
"""Search court records, solving image CAPTCHAs as needed."""
# Load the search page
page = self.session.get(f"{portal_url}/search")
# Extract CAPTCHA image
captcha_img_url = self._extract_captcha_url(page.text, portal_url)
if not captcha_img_url:
# No CAPTCHA on this page
return self._submit_search(portal_url, case_number)
# Download and solve CAPTCHA
img_response = self.session.get(captcha_img_url)
captcha_text = self._solve_image_captcha(img_response.content)
# Submit search with solved CAPTCHA
return self._submit_search(portal_url, case_number, captcha_text)
def _extract_captcha_url(self, html, base_url):
from bs4 import BeautifulSoup
soup = BeautifulSoup(html, "html.parser")
# Look for common CAPTCHA image patterns
captcha_img = (
soup.find("img", {"id": "captchaImage"}) or
soup.find("img", {"class": "captcha"}) or
soup.find("img", attrs={"src": lambda s: s and "captcha" in s.lower()})
)
if captcha_img and captcha_img.get("src"):
return urljoin(base_url, captcha_img["src"])
return None
def _solve_image_captcha(self, image_bytes):
img_base64 = base64.b64encode(image_bytes).decode("utf-8")
resp = requests.post("https://ocr.captchaai.com/in.php", data={
"key": self.api_key,
"method": "base64",
"body": img_base64,
"json": 1
})
task_id = resp.json()["request"]
for _ in range(30):
time.sleep(3)
result = requests.get("https://ocr.captchaai.com/res.php", params={
"key": self.api_key,
"action": "get",
"id": task_id,
"json": 1
})
data = result.json()
if data["status"] == 1:
return data["request"]
raise TimeoutError("CAPTCHA solve timed out")
def _submit_search(self, portal_url, case_number, captcha_text=None):
form_data = {"caseNumber": case_number}
if captcha_text:
form_data["captcha"] = captcha_text
response = self.session.post(
f"{portal_url}/search/results",
data=form_data
)
return response.text
# Usage
searcher = PublicRecordsSearcher("YOUR_API_KEY")
results = searcher.search_court_records(
"https://courts.example.gov",
"2024-CV-12345"
)
Entscheidend ist die gemeinsame requests.Session: Ein Bild, das ohne Cookie oder mit einem zweiten Client geladen wird, gehört zu einer anderen Sitzung als das Formular – die Antwort ist dann auch bei einwandfreier Erkennung falsch.
Mathe-CAPTCHAs: rechnen statt erkennen
Manche Portale zeigen keine Zeichenfolge, sondern eine kleine Rechenaufgabe als Bild. Für die API bleibt das Texterkennung; nur die Anweisung ändert sich. Mit textinstructions fordern Sie das Ergebnis der Rechnung an und nicht die abgebildeten Zeichen.
def solve_math_captcha(self, image_bytes):
"""Solve math CAPTCHAs like '4 + 7 = ?'"""
img_base64 = base64.b64encode(image_bytes).decode("utf-8")
resp = requests.post("https://ocr.captchaai.com/in.php", data={
"key": self.api_key,
"method": "base64",
"body": img_base64,
"textinstructions": "solve the math equation and return only the number",
"json": 1
})
task_id = resp.json()["request"]
# Poll for result
for _ in range(30):
time.sleep(3)
result = requests.get("https://ocr.captchaai.com/res.php", params={
"key": self.api_key,
"action": "get",
"id": task_id,
"json": 1
})
data = result.json()
if data["status"] == 1:
return data["request"]
raise TimeoutError("Math CAPTCHA solve timed out")
Steht die Aufgabe als reiner HTML-Text im Seitenquelltext statt als Bild, brauchen Sie gar keinen Solver: Dann genügen ein regulärer Ausdruck und eine Addition im eigenen Code.
Mehrere Portale in einem Durchlauf abfragen
Recherchen enden selten bei einer Quelle. Wer denselben Namen im Unternehmensregister, in der Gerichtsaktensuche und im Grundbuchportal sucht, braucht eine Schleife, die Fehler pro Portal protokolliert, statt den ganzen Lauf abzubrechen.
class RecordsAggregator {
constructor(apiKey) {
this.apiKey = apiKey;
}
async searchAcrossPortals(query, portals) {
const results = [];
for (const portal of portals) {
try {
const data = await this.searchPortal(portal, query);
results.push({ portal: portal.name, records: data });
} catch (error) {
results.push({ portal: portal.name, error: error.message });
}
}
return results;
}
async searchPortal(portal, query) {
const pageResponse = await fetch(portal.searchUrl);
const html = await pageResponse.text();
// Check for image CAPTCHA
const captchaMatch = html.match(/captcha[^"]*\.(?:png|jpg|gif)/i);
let captchaAnswer = null;
if (captchaMatch) {
const imgUrl = new URL(captchaMatch[0], portal.searchUrl).href;
const imgData = await fetch(imgUrl);
const buffer = await imgData.arrayBuffer();
const base64 = Buffer.from(buffer).toString('base64');
captchaAnswer = await this.solveImageCaptcha(base64);
}
// Submit search
const formData = new URLSearchParams({ q: query });
if (captchaAnswer) formData.append('captcha', captchaAnswer);
const response = await fetch(portal.searchUrl, {
method: 'POST',
body: formData
});
return response.text();
}
async solveImageCaptcha(base64Image) {
const submitResp = await fetch('https://ocr.captchaai.com/in.php', {
method: 'POST',
body: new URLSearchParams({
key: this.apiKey,
method: 'base64',
body: base64Image,
json: '1'
})
});
const { request: taskId } = await submitResp.json();
for (let i = 0; i < 30; i++) {
await new Promise(r => setTimeout(r, 3000));
const result = await fetch(
`https://ocr.captchaai.com/res.php?key=${this.apiKey}&action=get&id=${taskId}&json=1`
);
const data = await result.json();
if (data.status === 1) return data.request;
}
throw new Error('CAPTCHA solve timed out');
}
}
// Usage
const aggregator = new RecordsAggregator('YOUR_API_KEY');
const results = await aggregator.searchAcrossPortals('Smith LLC', [
{ name: 'State Business Registry', searchUrl: 'https://sos.example.gov/search' },
{ name: 'County Court Records', searchUrl: 'https://courts.example.gov/search' }
]);
Das Muster ist bewusst sequenziell: Paralleles Abfragen derselben Quelle provoziert Rate-Limiting; parallelisieren lohnt sich erst über verschiedene Portale hinweg.
Erkennungsparameter richtig setzen
Je genauer Sie das erwartete Format beschreiben, desto stabiler fällt die Erkennung aus.
| Parameter | Wert | Wann sinnvoll |
|---|---|---|
method |
base64 |
Bild wurde als Bytes heruntergeladen |
method |
post |
Bilddatei wird direkt übermittelt |
language |
0 |
Text-CAPTCHAs mit lateinischen Zeichen |
numeric |
1 |
CAPTCHAs, die nur aus Ziffern bestehen |
min_len / max_len |
portalabhängig | wenn die Zeichenzahl vorhersehbar ist |
textinstructions |
eigene Anweisung | Rechenaufgaben oder feste Formate |
Bei sehr schlechten Vorlagen hilft zusätzlich eine Vorverarbeitung des Bildes: Graustufen, mehr Kontrast, Rauschen entfernen. Die Anleitung zur Bildvorverarbeitung beschreibt die einzelnen Schritte.
Wenn die Suche fehlschlägt
| Symptom | Ursache | Abhilfe |
|---|---|---|
| CAPTCHA-Bild liefert 403 | Sitzungscookie fehlt | erst die Suchseite laden, dann das Bild abrufen |
| Antwort wird abgelehnt | schlechte Bildqualität | Bild vorverarbeiten oder min_len / max_len setzen |
| Beim Absenden erscheint ein neues CAPTCHA | Formular-Token abgelaufen | versteckte Formularfelder im selben Request wie das Bild auslesen |
| Trefferliste bleibt leer | POST-Weiterleitung verliert Cookies | allow_redirects=True nutzen und die Sitzung beibehalten |
Durchsatz und Kosten einplanen
CaptchaAI rechnet Thread-basiert ab, nicht pro Lösung: Ein Thread ist eine gleichzeitig laufende CAPTCHA-Anfrage; die Zahl der Lösungen ist innerhalb des Tarifs nicht gedeckelt. Für Registerrecherchen zählt also die Parallelität, nicht die Gesamtzahl der geprüften Fälle.
- BASIC (15 $ pro Monat, 5 Threads) – sequenzielle Recherchen mit ein bis zwei parallelen Quellen.
- ADVANCE (90 $ pro Monat, 50 Threads) – nächtliche Sammelläufe über viele Portale.
- ENTERPRISE (300 $ pro Monat, 200 Threads) – Dauerbetrieb mit mehreren Rechercheteams.
Preise in US-Dollar. Bild-CAPTCHAs löst der Dienst laut den veröffentlichten Solver-Angaben in unter 0,5 Sekunden – der Engpass liegt in der Praxis beim Portal selbst.
Häufige Fragen
Welche CAPTCHA-Typen deckt CaptchaAI auf Registerportalen ab?
Bild- und OCR-CAPTCHAs (über 27.500 Varianten), Rasterbild-CAPTCHAs, reCAPTCHA v2 und v3 inklusive Enterprise, Cloudflare Turnstile, Cloudflare Challenge und GeeTest v3. hCaptcha und FunCaptcha werden nicht unterstützt, GeeTest v4 ist bislang nur als „bald verfügbar“ angekündigt. CaptchaFox, Friendly Captcha und Lemin laufen als Beta.
Wie oft darf ein Registerportal abgefragt werden?
So selten wie möglich und nur im Rahmen der Nutzungsbedingungen. Bewährt hat sich ein sequenzieller Lauf mit mehreren Sekunden Abstand statt paralleler Anfragen an dieselbe Quelle; große Sammelläufe legen Sie besser in die Nachtstunden.
Nach dem Absenden erscheint erneut ein CAPTCHA – woran liegt das?
Meist ist das Formular-Token abgelaufen oder die Sitzung ist zwischen Bildabruf und POST verloren gegangen. Lesen Sie alle versteckten Felder im selben Request aus, mit dem Sie das CAPTCHA-Bild holen, und senden Sie sie unverändert mit.
Brauche ich einen Browser oder reichen HTTP-Anfragen?
Für klassische Bild-CAPTCHAs reichen HTTP-Anfragen mit persistenter Sitzung – das ist schneller und weniger fehleranfällig als jede Browsersteuerung. Erst wenn ein Portal reCAPTCHA v2 oder Turnstile einsetzt und das Token per JavaScript in die Seite schreibt, lohnen sich Selenium oder Playwright.
Wie gehe ich mit den erhobenen Personendaten um?
Wie jede andere personenbezogene Verarbeitung: dokumentierte Rechtsgrundlage, minimaler Umfang, feste Löschfristen. Dass die Daten aus einem öffentlichen Register stammen, macht ihre Speicherung im eigenen System nicht automatisch zulässig.
Nächste Schritte
Holen Sie sich Ihren CaptchaAI-API-Schlüssel und lösen Sie das erste Register-CAPTCHA direkt aus Ihrem Recherche-Skript – ohne die Suchmaske manuell zu bedienen.