Integrationen

ChromeDriver + CaptchaAI: Integration in automatisierte Test-Pipelines

Automatisierte Browser-Tests scheitern häufig an genau einer Stelle: der CAPTCHA-Abfrage vor dem Login- oder Checkout-Formular. undetected-chromedriver sorgt für ein realistisches Browser-Verhalten, sodass Ihre QA-Läufe die Seite so ansteuern wie ein echter Nutzer – und CaptchaAI löst die CAPTCHA-Abfrage, sobald sie auftritt, und liefert ein Token zurück, das Ihr Test in das Formular einfügt.

Diese Anleitung zeigt Schritt für Schritt, wie Sie beide Werkzeuge in einer Python-Test-Pipeline kombinieren: undetected-chromedriver steuert den Browser, CaptchaAI löst reCAPTCHA v2 und Cloudflare Turnstile. undetected-chromedriver baut auf dem Selenium-ChromeDriver auf, gleicht die Chrome-Version automatisch ab und setzt die Browser-Konfiguration auf praxisnahe Standardwerte – ideal für QA in eigenen Staging-Umgebungen, in denen belastbare Testergebnisse zählen.


Voraussetzungen und Installation

Sie brauchen Python 3.8 oder neuer, eine lokal installierte Chrome-Version und einen CaptchaAI-API-Schlüssel (erhältlich auf captchaai.com). Beide Python-Pakete installieren Sie in einem Schritt:

pip install undetected-chromedriver requests

undetected-chromedriver lädt den passenden ChromeDriver beim ersten Start selbst herunter – ein manueller Versionsabgleich entfällt.


Browser für den Testlauf starten

Die folgende Funktion erzeugt eine Chrome-Instanz mit praxisnahen Optionen. Für CI/CD-Läufe ohne Anzeige aktivieren Sie den Headless-Modus über die auskommentierte Zeile; --no-sandbox ist in Container-Umgebungen meist erforderlich.

import undetected_chromedriver as uc
import requests
import time

CAPTCHAAI_KEY = "YOUR_API_KEY"
CAPTCHAAI_URL = "https://ocr.captchaai.com"


def create_browser():
    # Einen Chrome-Browser fuer automatisierte Tests starten
    options = uc.ChromeOptions()
    # Fuer CI/CD-Umgebungen ohne Anzeige:
    # options.add_argument("--headless=new")
    options.add_argument("--no-sandbox")
    options.add_argument("--disable-gpu")
    return uc.Chrome(options=options)

reCAPTCHA v2 lösen und Token einfügen

Der Ablauf folgt immer demselben Muster: Sitekey und Seiten-URL an CaptchaAI übermitteln, den Status per Polling abfragen und das fertige Token in das g-recaptcha-response-Feld eintragen. Das Timeout ist mit 30 Versuchen à 5 Sekunden großzügig bemessen.

def solve_recaptcha_v2(sitekey, pageurl):
    resp = requests.post(
        f"{CAPTCHAAI_URL}/in.php",
        data={
            "key": CAPTCHAAI_KEY,
            "method": "userrecaptcha",
            "googlekey": sitekey,
            "pageurl": pageurl,
            "json": 1,
        },
        timeout=30,
    )
    resp.raise_for_status()
    task_id = resp.json()["request"]

    for _ in range(30):
        time.sleep(5)
        result = requests.get(
            f"{CAPTCHAAI_URL}/res.php",
            params={"key": CAPTCHAAI_KEY, "action": "get", "id": task_id, "json": 1},
            timeout=30,
        )
        result.raise_for_status()
        data = result.json()
        if data.get("status") == 1:
            return data["request"]

    raise TimeoutError("CAPTCHA-Lösungszeit abgelaufen")


def inject_recaptcha_token(driver, token):
    # Token in das g-recaptcha-response-Feld einfuegen
    driver.execute_script(
        'document.getElementById("g-recaptcha-response").value = arguments[0];',
        token,
    )

Kompletter Integrationstest

Jetzt fügen sich die Bausteine zu einem durchgehenden Test in einer eigenen Staging-Umgebung zusammen: Seite aufrufen, Sitekey aus dem DOM lesen, Token lösen, einfügen, Formular absenden und das Erfolgssignal prüfen. driver.quit() im finally-Block schließt den Browser auch bei einem Fehler zuverlässig.

from selenium.webdriver.common.by import By
from selenium.webdriver.support.ui import WebDriverWait
from selenium.webdriver.support import expected_conditions as EC


def run_integration_test():
    # Integrationstests mit CAPTCHA-Handling in eigener Staging-Umgebung
    driver = create_browser()
    wait = WebDriverWait(driver, 30)

    try:
        # Eigene Testseite aufrufen
        driver.get("https://staging.example-app.test/form")

        # Auf Seitenladung warten
        wait.until(EC.presence_of_element_located((By.ID, "submit-button")))

        # CAPTCHA-Element finden und Sitekey extrahieren
        captcha_el = driver.find_element(By.CLASS_NAME, "g-recaptcha")
        sitekey = captcha_el.get_attribute("data-sitekey")
        pageurl = driver.current_url

        # Token lösen und an das eigene Testformular übergeben
        token = solve_recaptcha_v2(sitekey, pageurl)
        inject_recaptcha_token(driver, token)

        # Formular in der Staging-Umgebung absenden
        driver.find_element(By.ID, "submit-button").click()

        # Erfolg pruefen
        success_el = wait.until(
            EC.presence_of_element_located((By.CLASS_NAME, "success-message"))
        )
        print(f"Test bestanden: {success_el.text}")

    finally:
        driver.quit()


if __name__ == "__main__":
    run_integration_test()

Cloudflare Turnstile im selben Setup lösen

Trifft Ihr Test statt reCAPTCHA auf ein Cloudflare Turnstile-Widget, ändert sich nur die method (turnstile) und das Zielfeld (cf-turnstile-response). Struktur und Polling bleiben identisch – der Rest Ihrer Pipeline muss nicht angepasst werden.

def solve_turnstile(sitekey, pageurl):
    resp = requests.post(
        f"{CAPTCHAAI_URL}/in.php",
        data={
            "key": CAPTCHAAI_KEY,
            "method": "turnstile",
            "sitekey": sitekey,
            "pageurl": pageurl,
            "json": 1,
        },
        timeout=30,
    )
    resp.raise_for_status()
    task_id = resp.json()["request"]

    for _ in range(24):
        time.sleep(5)
        result = requests.get(
            f"{CAPTCHAAI_URL}/res.php",
            params={"key": CAPTCHAAI_KEY, "action": "get", "id": task_id, "json": 1},
            timeout=30,
        )
        result.raise_for_status()
        data = result.json()
        if data.get("status") == 1:
            return data["request"]

    raise TimeoutError("Turnstile-Lösungszeit abgelaufen")


def inject_turnstile_token(driver, token):
    # Token in das cf-turnstile-response-Feld einfuegen
    driver.execute_script(
        "document.querySelector(\"[name='cf-turnstile-response']\").value = arguments[0];",
        token,
    )

Wiederholungslogik für stabile CI-Läufe

In einer CI-Pipeline sind kurzzeitige Netzwerkfehler oder eine überlastete Staging-Seite normal. Ein schlanker Wrapper mit erneutem Versuch und kurzer Wartezeit verhindert, dass ein einzelner Aussetzer den gesamten Testlauf rot färbt. Für längere Läufe können Sie die Wartezeit zwischen den Versuchen schrittweise erhöhen – ein exponentielles Backoff entlastet die API bei kurzen Störungen zusätzlich und vermeidet unnötige Wiederholungen im Sekundentakt.

import time


def with_retry(fn, retries=3, delay=5.0):
    # Funktion mit Wiederholungslogik bei Fehlern ausfuehren
    for attempt in range(1, retries + 1):
        try:
            return fn()
        except Exception as exc:
            if attempt == retries:
                raise
            print(
                f"Versuch {attempt}/{retries} fehlgeschlagen: {exc} "
                f"– neuer Versuch in {delay}s"
            )
            time.sleep(delay)

In eine GitLab-CI-Pipeline einbinden

In vielen DACH-Teams läuft die Test-Pipeline über GitLab CI, häufig auf eigenen Runnern bei Hetzner, IONOS oder netcup. Damit undetected-chromedriver dort funktioniert, brauchen Sie ein Image mit installiertem Chrome und starten den Browser mit --headless=new sowie --no-sandbox. Den API-Schlüssel hinterlegen Sie als geschützte CI-Variable und lesen ihn über os.environ ein – niemals fest im Code.

Ein praktischer Aufbau: Der run_integration_test-Schritt läuft gegen Ihre Staging-URL, das with_retry-Muster fängt Aussetzer ab, und ein fehlgeschlagener CAPTCHA-Schritt bricht den Job mit klarer Fehlermeldung ab. So bleibt der Grund für einen roten Lauf im Log sofort erkennbar.

Ein Hinweis zur DSGVO: Sobald Testläufe mit echten personenbezogenen Daten oder IP-gebundenen Proxys arbeiten, gelten IP-Adressen als personenbezogen. Prüfen Sie Ihre Datenflüsse und die Rechtsgrundlage – am besten testen Sie ausschließlich in eigenen oder freigegebenen Umgebungen.


Häufige Fehler beheben

Problem Ursache Maßnahme
ChromeDriver-Version passt nicht Chrome-Update uc.Chrome() lädt automatisch die passende Version
CAPTCHA erscheint nicht Sitekey-Konfiguration Sitekey in der Staging-Config prüfen
Token nach dem Einfügen abgelehnt Token abgelaufen (über 120 Sekunden) Token zeitnah nach der Lösung eintragen
NoSuchElementException DOM-Änderung Selektoren in der Staging-Umgebung prüfen
Sitzung abgelaufen Cookie-Verwaltung Cookies zwischen Tests beibehalten

Häufige Fragen

Welche CAPTCHA-Typen deckt dieses Setup ab?

Die Beispiele lösen reCAPTCHA v2 und Cloudflare Turnstile. CaptchaAI unterstützt darüber hinaus reCAPTCHA v3, Cloudflare Challenge, GeeTest v3 sowie Bild- und Rasterbild-CAPTCHAs – nach demselben Muster: übermitteln, Status abfragen, Token einfügen.

Was kostet das CAPTCHA-Lösen bei vielen Testläufen?

CaptchaAI rechnet pro gleichzeitigem Thread ab, nicht pro Lösung. Der Einstiegstarif BASIC (15 $/Monat, 5 Threads) deckt parallele Läufe ab; jeder Thread löst im Abrechnungsmonat unbegrenzt viele CAPTCHAs. Aktuelle Tarife finden Sie unter captchaai.com.

Wie lange ist ein gelöstes Token gültig?

reCAPTCHA- und Turnstile-Tokens laufen nach rund 120 Sekunden ab. Fügen Sie das Token direkt nach der Lösung in das Formular ein und senden Sie es sofort ab – deshalb steht der Lösungsschritt kurz vor dem Absenden.

Kann ich den Browser über mehrere Tests hinweg wiederverwenden?

Ja. Behalten Sie Cookies und Sitzung zwischen Tests bei, um wiederholte Anmeldungen zu vermeiden. Starten Sie den Browser nur dann neu, wenn sich die Konfiguration ändert oder ein Testfall eine saubere Sitzung verlangt.

Funktioniert das Setup im Headless-Modus auf einem CI-Runner?

Ja. Aktivieren Sie den Modus mit options.add_argument("--headless=new") und ergänzen Sie --no-sandbox für Container. Prüfen Sie Ihre CAPTCHA-Selektoren zuerst im sichtbaren Modus, da manche Seiten im Headless-Betrieb ein leicht abweichendes DOM ausliefern.


Weiterführende Leitfäden


Integrieren Sie CaptchaAI in Ihre Selenium-Test-Pipeline – Holen Sie sich Ihren CaptchaAI-Schlüssel.

Kommentare sind für diesen Artikel deaktiviert.