API-Tutorials

Lösungsstrategien für Bild-CAPTCHA mit mehreren Zeichen

Ein Bild-CAPTCHA mit mehreren Zeichen lösen Sie am zuverlässigsten, indem Sie das Rohbild als base64 an die OCR-API übergeben und der Erkennung vorab mitteilen, was sie erwartet: Zeichenzahl, Groß-/Kleinschreibung, Zeichensatz und eine kurze Textanweisung. Über Treffer oder Fehlversuch entscheiden bei verbundenen Buchstaben, quer liegenden Störlinien oder wechselnden Schriftarten fast immer diese Hinweisparameter – nicht die Auflösung des Bildes.

Dieser Leitfaden zeigt die Parameterprofile für die drei schwierigsten Bildklassen, wann eine Vorverarbeitung wirklich etwas bringt und wie eine sinnvolle Wiederholungslogik aussieht. Alle Beispiele sind in Python geschrieben und kommen ohne Browser aus.


Das Wesentliche in Kürze

  • Bild-CAPTCHAs löst CaptchaAI in unter 0,5 s mit hoher Erfolgsquote; der Engpass liegt meist in Ihrer eigenen Pipeline.
  • minLen und maxLen sind die wirksamsten Parameter bei verbundenen Zeichen, regsense=1 erhält die Schreibweise, language=2 beschränkt auf lateinische Zeichen.
  • Vorverarbeitung ist die Ausnahme: Zu aggressives Binarisieren radiert dünne Buchstabenteile mit weg.
  • Abgerechnet wird pro Thread, nicht pro Lösung – ein zweiter Versuch kostet nur Laufzeit.

Verzerrungstypen: womit Sie es zu tun haben

Bevor Sie Parameter setzen, lohnt sich ein genauer Blick auf das Bild. Die folgende Einordnung deckt ab, was in älteren Portalen, Foren-Registrierungen und Behörden-Frontends noch im Einsatz ist:

Typ Merkmal Schwierigkeit
Sauberer Text keine Verzerrung, einheitliche Schriftart einfach
Verzerrter Text Buchstaben einzeln gedreht oder skaliert mittel
Verbundene Buchstaben Zeichen berühren oder überlappen sich schwer
Mehrere Schriftarten pro Zeichen eine andere Schrift schwer
Rauschen und Störlinien Bildrauschen, Linien quer über dem Text mittel
Farbwechsel jedes Zeichen in einer anderen Farbe mittel
Rechenaufgabe Zahlen und Operatoren, erwartet wird das Ergebnis mittel

Die letzten beiden Zeilen werden gern übersehen: Farbwechsel bricht jede schwellenwertbasierte Binarisierung, und bei Rechenaufgaben zählt nicht die abgebildete Zeichenkette, sondern deren Ergebnis.


Grundgerüst: einreichen, abfragen, verwenden

Der Ablauf ist bei allen Varianten identisch: Bild als base64 an in.php übermitteln, Task-ID entgegennehmen, res.php abfragen, bis die Lösung vorliegt. Die Hinweisparameter reisen als zusätzliche Felder in derselben Payload mit – deshalb nimmt die folgende Funktion sie als optionales Dictionary entgegen.

import requests
import base64
import time
import os

API_KEY = os.environ["CAPTCHAAI_API_KEY"]


def solve_complex_image(image_b64, hints=None):
    """Solve a complex multi-character image CAPTCHA."""
    payload = {
        "key": API_KEY,
        "method": "base64",
        "body": image_b64,
        "json": 1,
    }

    if hints:
        payload.update(hints)

    resp = requests.post(
        "https://ocr.captchaai.com/in.php",
        data=payload,
        timeout=30,
    )
    result = resp.json()

    if result.get("status") != 1:
        raise RuntimeError(f"Submit failed: {result.get('request')}")

    task_id = result["request"]

    time.sleep(8)
    for _ in range(24):
        resp = requests.get("https://ocr.captchaai.com/res.php", params={
            "key": API_KEY,
            "action": "get",
            "id": task_id,
            "json": 1,
        }, timeout=15)
        data = resp.json()
        if data.get("status") == 1:
            return data["request"]
        if data["request"] != "CAPCHA_NOT_READY":
            raise RuntimeError(data["request"])
        time.sleep(5)

    raise TimeoutError("Solve timeout")

Zwei Details lohnen den zweiten Blick. Erstens die Wartezeiten: Das Beispiel pausiert acht Sekunden vor der ersten Abfrage und danach im Fünf-Sekunden-Takt – für nächtliche Batch-Läufe entspannt, für interaktive Abläufe zu träge. Zweitens die Schreibweise CAPCHA_NOT_READY: Der Tippfehler steckt im API-Protokoll selbst. Wer auf CAPTCHA_NOT_READY prüft, baut sich eine Endlosschleife bis zum Timeout.


Hinweisprofile für die drei schwierigsten Fälle

Verbundene und überlappende Buchstaben

Wenn Zeichen ineinanderlaufen, hilft vor allem eine enge Längenangabe: minLen und maxLen verhindern, dass ein zusammengewachsenes „rn“ als „m“ durchgeht. Die Textanweisung benennt zusätzlich die Bildeigenschaft.

def solve_connected_letters(image_path):
    """Solve CAPTCHA with connected/overlapping characters."""
    with open(image_path, "rb") as f:
        b64 = base64.b64encode(f.read()).decode("ascii")

    return solve_complex_image(b64, hints={
        "textinstructions": "Characters may be connected or overlapping",
        "minLen": 4,
        "maxLen": 8,
    })

Störlinien und gemischte Groß-/Kleinschreibung

regsense=1 ist der Schalter, ohne den die Schreibweise verloren geht – bei Formularen, die den Wert exakt vergleichen, ist das der häufigste stille Fehler. language=2 grenzt auf lateinische Zeichen ein und nimmt kyrillische oder griechische Fehldeutungen aus dem Rennen.

def solve_noisy_mixed(image_path):
    """Solve CAPTCHA with background noise and mixed case."""
    with open(image_path, "rb") as f:
        b64 = base64.b64encode(f.read()).decode("ascii")

    return solve_complex_image(b64, hints={
        "regsense": 1,         # Case-sensitive
        "language": 2,         # Latin characters
        "textinstructions": "Ignore background lines and noise",
    })

Wechselnde Schriftarten in einem Bild

Mehrere Schriftschnitte pro Bild sind für regelbasierte Erkennung der unangenehmste Fall, weil kein Zeichenmodell durchgängig passt. Setzen Sie hier ein enges Längenfenster und benennen Sie die Schriftvielfalt explizit in der Textanweisung.

def solve_multi_font(image_path):
    """Solve CAPTCHA using multiple fonts per character."""
    with open(image_path, "rb") as f:
        b64 = base64.b64encode(f.read()).decode("ascii")

    return solve_complex_image(b64, hints={
        "textinstructions": "Each character may use a different font or style",
        "minLen": 5,
        "maxLen": 7,
    })

Vorverarbeitung: die Ausnahme, nicht die Regel

Vorverarbeitung wirkt verlockend, verschlechtert das Ergebnis aber häufiger, als sie es verbessert: Ein zu hoher Schwellenwert entfernt dünne Buchstabenteile zusammen mit dem Rauschen. Sinnvoll ist sie bei kontrastarmen Scans, JPEG-Artefakten und großflächigem Bildrauschen – dann in dieser Reihenfolge: Graustufen, Kontrast, Schärfen, Schwellenwert.

# preprocess.py
from PIL import Image, ImageFilter, ImageEnhance
import io
import base64


def preprocess_for_ocr(image_path):
    """Preprocess image to improve OCR accuracy."""
    img = Image.open(image_path)

    # Convert to grayscale
    img = img.convert("L")

    # Increase contrast
    enhancer = ImageEnhance.Contrast(img)
    img = enhancer.enhance(2.0)

    # Sharpen
    img = img.filter(ImageFilter.SHARPEN)

    # Binarize (threshold)
    threshold = 128
    img = img.point(lambda p: 255 if p > threshold else 0)

    # Encode back to base64
    buffer = io.BytesIO()
    img.save(buffer, format="PNG")
    return base64.b64encode(buffer.getvalue()).decode("ascii")

Prüfen Sie den Schwellenwert an mindestens 20 gespeicherten Beispielbildern gegen die Rohübermittlung. Bringt die Vorverarbeitung keine messbare Verbesserung, lassen Sie sie weg – sonst wissen Sie bei Fehlern nicht mehr, ob das Modell oder Ihr Filter danebenlag.


Wiederholungslogik und Qualitätsmeldungen

Eine identische Wiederholung liefert selten ein anderes Ergebnis. Sinnvoll ist eine Kaskade, die pro Versuch die Randbedingungen lockert: erst das vollständige Hinweisprofil, dann ohne Textanweisung, zuletzt ohne Einschränkung bei Zeichensatz und Schreibweise.

# retry_strategy.py


def solve_with_retry(image_b64, hints, max_retries=3):
    """Retry solving with fallback strategies."""
    strategies = [
        hints,                                          # Original hints
        {**hints, "textinstructions": ""},              # Without instructions
        {**hints, "numeric": 0, "regsense": 0},        # Relaxed constraints
    ]

    for i, strategy in enumerate(strategies[:max_retries]):
        try:
            result = solve_complex_image(image_b64, strategy)
            return {"text": result, "strategy": i, "success": True}
        except RuntimeError:
            continue

    return {"text": None, "strategy": -1, "success": False}


def report_bad_answer(task_id):
    """Report incorrect answer for quality feedback."""
    requests.get("https://ocr.captchaai.com/res.php", params={
        "key": API_KEY,
        "action": "reportbad",
        "id": task_id,
    }, timeout=10)

reportbad gehört fest in die Fehlerbehandlung: Melden Sie jede Antwort, die das Zielformular zurückweist, direkt im except-Zweig.


Durchsatz planen: Abrechnung pro Thread

Ein Thread ist ein gleichzeitig laufendes CAPTCHA, keine einzelne Lösung. Bei Lösungszeiten unter 0,5 s ist ein einzelner Thread deshalb erstaunlich ergiebig – der begrenzende Faktor ist meist Ihr Scraper. BASIC (15 $/Monat, 5 Threads) trägt einen einzelnen Crawler mühelos, STANDARD (30 $/Monat, 15 Threads) deckt mehrere parallele Jobs ab, und erst bei dauerhaft zweistelliger Parallelität lohnt ADVANCE (90 $/Monat, 50 Threads). Die Preise gelten in US-Dollar; innerhalb eines Plans gibt es weder Tageslimits noch Aufschläge nach CAPTCHA-Typ.


Praxisbeispiel: Lieferantenportal eines Großhändlers

Ein typisches Szenario aus dem DACH-Raum: Ein Großhändler gleicht nachts Preise aus einem älteren Lieferantenportal in seine Shopware-Instanz ab. Beim Login erscheint ein fünfstelliges Bild-CAPTCHA mit Störlinien; Zugangsdaten und Abrufrhythmus sind vertraglich vereinbart.

Der Worker läuft als GitLab-CI-Job auf einem Hetzner-Server, konfiguriert mit dem Profil für Störlinien und gemischte Schreibweise: regsense=1, language=2, dazu minLen: 5 und maxLen: 5, weil die Zeichenzahl hier konstant ist. Fehlversuche laufen in die Wiederholungskaskade, abgelehnte Antworten werden per reportbad gemeldet.

Datenschutzhinweis: Sobald bei solchen Abgleichen personenbezogene Daten anfallen – Ansprechpartner, E-Mail-Adressen, IP-Adressen in Logs –, brauchen Sie eine Rechtsgrundlage nach DSGVO. Speichern Sie CAPTCHA-Bilder nur so lange, wie die Fehleranalyse es erfordert.


Fehlerbehebung

Symptom Ursache Abhilfe
Zeichen fehlen in der Antwort verbundene Buchstaben als ein Zeichen gelesen textinstructions ergänzen, minLen setzen
Zu viele Zeichen in der Antwort Störlinien werden als Text interpretiert vor der Übermittlung entrauschen
Groß-/Kleinschreibung stimmt nicht Schreibweise wird nicht erhalten regsense=1 setzen
Rechenaufgabe kommt als Zeichenkette zurück calc=1 fehlt Rechenmodus für mathematische CAPTCHAs aktivieren
Auf einem Portal dauerhaft falsch portalspezifische Schriftart Fehlantworten per reportbad melden

Häufige Fragen

Welche Parameter bringen bei schwierigen Bildern am meisten?

minLen und maxLen. Eine feste oder eng begrenzte Zeichenzahl schließt die häufigsten Fehldeutungen aus, weil zusammengewachsene Buchstabenpaare sonst als ein Zeichen durchgehen. Danach folgt regsense, erst zuletzt die freie textinstructions-Beschreibung.

Kostet jeder Wiederholungsversuch extra?

Nein. Abgerechnet wird pro gleichzeitigem Thread, nicht pro Lösung; die Zahl der Lösungen pro Thread ist innerhalb eines Plans unbegrenzt. Ein erneuter Versuch belegt lediglich für kurze Zeit wieder einen Thread.

Wie behandle ich CAPTCHAs mit Rechenaufgaben?

Mit aktiviertem Rechenmodus (calc=1). Ohne ihn erhalten Sie die abgebildete Zeichenkette – etwa „7 + 4“ – statt des Ergebnisses. Manche Formulare erwarten allerdings genau diesen Ausdruck; prüfen Sie im Zweifel beides.

Werden hCaptcha und FunCaptcha ebenfalls abgedeckt?

Nein, beide werden nicht unterstützt. Abgedeckt sind Bild-CAPTCHAs (OCR), Rasterbild- und BLS-CAPTCHAs, die reCAPTCHA-Familie, Cloudflare Turnstile und Challenge sowie GeeTest v3; CaptchaFox, Friendly Captcha und Lemin sind in der Beta. GeeTest v4 ist angekündigt, aber nicht verfügbar.

Was tun, wenn ein Portal dauerhaft falsche Ergebnisse liefert?

Fehlantworten konsequent per reportbad melden und eine portalspezifische textinstructions-Zeile hinterlegen, die Schriftbild und Störmuster beschreibt. Legen Sie pro Fehlertyp ein Beispielbild ab – das verkürzt die Analyse, wenn sich das Portal ändert.


Verwandte Leitfäden


Mehrstellige Bild-CAPTCHAs zuverlässig lösen – jetzt mit CaptchaAI starten.

Kommentare sind für diesen Artikel deaktiviert.