Anwendungsfälle

Playwright CAPTCHA-Handhabung mit CaptchaAI

Ein Playwright-Test läuft stabil durch – bis die Zielseite ein reCAPTCHA oder Cloudflare Turnstile einblendet und die Automatisierung hängen bleibt. Der pragmatische Ausweg: Playwright steuert den Browser, CaptchaAI löst das CAPTCHA serverseitig und liefert ein Token zurück, das Playwright in das Formular einträgt. Dieser Leitfaden zeigt die vollständige Integration in Python und Node.js – von der ersten Anfrage bis zum abgesendeten Formular.

Der Ablauf ist immer derselbe, egal welcher CAPTCHA-Typ erscheint: Sitekey aus dem DOM auslesen, an CaptchaAI übermitteln, Status abfragen, Token einfügen. Playwright kümmert sich um Navigation, Wartezeiten und Formulare; das Lösen selbst passiert außerhalb des Browsers.

Voraussetzungen

Anforderung Einzelheiten
Python pip install playwright requests, dann playwright install
Node.js npm install playwright axios
CaptchaAI API-Schlüssel Von captchaai.com

Wenn Sie CaptchaAI noch nicht eingerichtet haben, genügen ein Konto und der API-Schlüssel aus dem Dashboard, um in wenigen Minuten das erste CAPTCHA zu lösen.

Python: Playwright mit CaptchaAI verbinden

Der Solver-Client

Diese Funktion übermittelt den Sitekey an CaptchaAI, fragt den Status im Abstand von fünf Sekunden ab und gibt das fertige Token zurück. Das Muster gilt für reCAPTCHA genauso wie für Turnstile – nur der method-Parameter ändert sich.

from playwright.sync_api import sync_playwright
import requests
import time

API_KEY = "YOUR_API_KEY"

def solve_recaptcha(site_key, page_url):
    resp = requests.get("https://ocr.captchaai.com/in.php", params={
        "key": API_KEY,
        "method": "userrecaptcha",
        "googlekey": site_key,
        "pageurl": page_url
    })
    if not resp.text.startswith("OK|"):
        raise Exception(resp.text)
    task_id = resp.text.split("|")[1]

    for _ in range(60):
        time.sleep(5)
        result = requests.get("https://ocr.captchaai.com/res.php", params={
            "key": API_KEY, "action": "get", "id": task_id
        })
        if result.text == "CAPCHA_NOT_READY": continue
        if result.text.startswith("OK|"): return result.text.split("|")[1]
        raise Exception(result.text)
    raise TimeoutError()

Vollständiges Login-Beispiel

Ein typisches Szenario aus der Praxis: Ein Team in Berlin automatisiert die Ende-zu-Ende-Tests einer Login-Strecke, die in der Staging-Umgebung reCAPTCHA v2 ausliefert. Playwright füllt die Felder aus, erkennt das CAPTCHA am .g-recaptcha-Element, lässt es von CaptchaAI lösen und trägt das Token vor dem Absenden ein.

def login_with_captcha(url, username, password):
    with sync_playwright() as p:
        browser = p.chromium.launch(headless=True)
        context = browser.new_context(
            user_agent="Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36"
        )
        page = context.new_page()
        page.goto(url)

        # Fill login form
        page.fill("#username", username)
        page.fill("#password", password)

        # Check for reCAPTCHA
        recaptcha = page.query_selector(".g-recaptcha")
        if recaptcha:
            site_key = recaptcha.get_attribute("data-sitekey")
            print(f"Solving reCAPTCHA: {site_key}")

            token = solve_recaptcha(site_key, page.url)

            # Inject token
            page.evaluate(f"""
                document.getElementById('g-recaptcha-response').innerHTML = '{token}';
                document.getElementById('g-recaptcha-response').style.display = '';
            """)

        # Submit
        page.click('button[type="submit"]')
        page.wait_for_load_state("networkidle")

        print(f"Current URL: {page.url}")
        content = page.content()

        browser.close()
        return content

result = login_with_captcha(
    "https://example.com/login",
    "user@example.com",
    "password123"
)

Asynchrone Variante für hohen Durchsatz

Wer viele Seiten parallel testet – etwa in einer GitLab-CI-Pipeline auf einem Hetzner-Worker – fährt mit der asynchronen API besser. aiohttp fragt das Ergebnis ab, ohne den Event-Loop zu blockieren, sodass mehrere Seiten gleichzeitig laufen können. Die Zahl gleichzeitiger Lösungen ist dabei durch Ihre Thread-Zuteilung begrenzt (siehe unten).

from playwright.async_api import async_playwright
import aiohttp
import asyncio

async def solve_recaptcha_async(site_key, page_url):
    async with aiohttp.ClientSession() as session:
        params = {
            "key": API_KEY, "method": "userrecaptcha",
            "googlekey": site_key, "pageurl": page_url
        }
        async with session.get("https://ocr.captchaai.com/in.php", params=params) as resp:
            text = await resp.text()
            task_id = text.split("|")[1]

        for _ in range(60):
            await asyncio.sleep(5)
            params = {"key": API_KEY, "action": "get", "id": task_id}
            async with session.get("https://ocr.captchaai.com/res.php", params=params) as resp:
                text = await resp.text()
                if text == "CAPCHA_NOT_READY": continue
                if text.startswith("OK|"): return text.split("|")[1]
                raise Exception(text)
        raise TimeoutError()

async def main():
    async with async_playwright() as p:
        browser = await p.chromium.launch(headless=True)
        page = await browser.new_page()
        await page.goto("https://example.com/form")

        site_key = await page.get_attribute(".g-recaptcha", "data-sitekey")
        token = await solve_recaptcha_async(site_key, page.url)

        await page.evaluate(f"document.getElementById('g-recaptcha-response').innerHTML = '{token}'")
        await page.click('button[type="submit"]')
        await browser.close()

asyncio.run(main())

Das reCAPTCHA-v2-Token lässt sich auf dieselbe Weise auch außerhalb von Playwright per API anfordern – der method-Parameter userrecaptcha bleibt dabei identisch.

Node.js: Playwright mit CaptchaAI

Für reine JavaScript-Stacks funktioniert derselbe Ablauf mit axios. Der Solver-Client übermittelt den Sitekey und fragt das Ergebnis in einer Schleife ab, bis das Token bereitsteht.

const { chromium } = require("playwright");
const axios = require("axios");

const API_KEY = "YOUR_API_KEY";

async function solveRecaptcha(siteKey, pageUrl) {
  const submit = await axios.get("https://ocr.captchaai.com/in.php", {
    params: {
      key: API_KEY,
      method: "userrecaptcha",
      googlekey: siteKey,
      pageurl: pageUrl,
    },
  });
  const taskId = submit.data.split("|")[1];

  while (true) {
    await new Promise((r) => setTimeout(r, 5000));
    const result = await axios.get("https://ocr.captchaai.com/res.php", {
      params: { key: API_KEY, action: "get", id: taskId },
    });
    if (result.data === "CAPCHA_NOT_READY") continue;
    if (result.data.startsWith("OK|")) return result.data.split("|")[1];
    throw new Error(result.data);
  }
}

(async () => {
  const browser = await chromium.launch({ headless: true });
  const page = await browser.newPage();
  await page.goto("https://example.com/login");

  // Fill form
  await page.fill("#username", "user@example.com");
  await page.fill("#password", "password123");

  // Solve CAPTCHA
  const siteKey = await page.getAttribute(".g-recaptcha", "data-sitekey");
  if (siteKey) {
    const token = await solveRecaptcha(siteKey, page.url());
    await page.evaluate(
      (t) => (document.getElementById("g-recaptcha-response").innerHTML = t),
      token
    );
  }

  // Submit
  await page.click('button[type="submit"]');
  await page.waitForLoadState("networkidle");

  console.log("Logged in:", page.url());
  await browser.close();
})();

Cloudflare Turnstile in Playwright lösen

Turnstile folgt demselben Muster – nur der method-Parameter heißt turnstile, und der Sitekey steckt im .cf-turnstile-Element. Das zurückgegebene Token gehört in das Feld cf-turnstile-response.

# Detect Turnstile
turnstile = page.query_selector(".cf-turnstile")
if turnstile:
    site_key = turnstile.get_attribute("data-sitekey")

    resp = requests.get("https://ocr.captchaai.com/in.php", params={
        "key": API_KEY, "method": "turnstile",
        "sitekey": site_key, "pageurl": page.url
    })
    task_id = resp.text.split("|")[1]

    # Poll and inject...

Poll-Logik und Token-Einfügen sind mit dem reCAPTCHA-Beispiel oben identisch – nur method, das Selektor-Element und das Zielfeld unterscheiden sich.

Playwright, Selenium oder Puppeteer?

Playwright ist für neue Projekte oft die naheliegende Wahl, weil das automatische Warten Flakiness reduziert. Für die CaptchaAI-Anbindung spielt das Framework aber keine Rolle – die API-Aufrufe sind identisch.

Merkmal Playwright Selenium Puppeteer
Sprachen Python, Node.js, C#, Java Python, Java, C#, Ruby, JS Node.js
Browser Chromium, Firefox, WebKit Chrome, Firefox, Edge, Safari Chromium
Automatisches Warten integriert manuelle Waits teilweise
Netzwerk-Interception ja begrenzt ja
CaptchaAI-Integration gleiche API gleiche API gleiche API

CaptchaAI funktioniert mit allen drei Frameworks identisch: Sitekey auslesen, per API lösen, Token einfügen.

Thread-basierte Abrechnung und Parallelität

CaptchaAI rechnet pro gleichzeitigem Thread ab – nicht pro Lösung. Ein Thread entspricht einem CAPTCHA, das gerade in Bearbeitung ist; sobald es fertig ist, nimmt derselbe Thread das nächste auf. Für parallele Playwright-Läufe bestimmt Ihre Thread-Zahl also die Obergrenze gleichzeitiger Lösungen. Der BASIC-Tarif (15 $/Monat, 5 Threads) deckt fünf gleichzeitige Lösungen ab, STANDARD (30 $/Monat, 15 Threads) entsprechend mehr. Innerhalb eines Tarifs gibt es keine Tageslimits und keine Aufpreise pro CAPTCHA-Typ.

Häufige Fehler und Lösungen

Problem Lösung
page.query_selector liefert null CAPTCHA wird dynamisch geladen; page.wait_for_selector() verwenden
Token wird nicht übernommen Prüfen, ob das Antwort-Textfeld eine andere ID hat
Playwright stürzt in Docker ab Browser-Abhängigkeiten installieren: playwright install-deps
CAPTCHA erscheint nach dem Lösen erneut Die Seite erwartet evtl. einen Callback; über page.evaluate() auslösen

Häufige Fragen

Löst CaptchaAI das CAPTCHA oder übernimmt das Playwright?

CaptchaAI löst das CAPTCHA serverseitig und gibt ein Token zurück. Playwright liest nur den Sitekey aus dem DOM, trägt das fertige Token in das Antwortfeld ein und sendet das Formular ab. Das automatische Warten von Playwright hilft dabei, das CAPTCHA-Element zuverlässig zu finden, löst es aber nicht selbst.

Kann ich mehrere CAPTCHAs gleichzeitig verarbeiten?

Ja. Mit der asynchronen API und mehreren Playwright-Kontexten laufen Lösungen parallel. Die Obergrenze ergibt sich aus Ihrer Thread-Zuteilung im gewählten Tarif – jeder freie Thread nimmt sofort das nächste CAPTCHA auf.

Welche CAPTCHA-Typen unterstützt die Integration?

Der Workflow deckt reCAPTCHA v2 und v3, Cloudflare Turnstile und Challenge, GeeTest v3 sowie Bild-/OCR-, Raster- und BLS-CAPTCHAs ab. CaptchaFox, Friendly Captcha und Lemin sind als Beta verfügbar. hCaptcha und FunCaptcha werden derzeit nicht unterstützt, GeeTest v4 ist als „bald verfügbar" angekündigt.

Funktioniert der Workflow auch mit Firefox und WebKit?

Ja. Da CaptchaAI unabhängig vom Browser arbeitet, gilt derselbe Ablauf für Chromium, Firefox und WebKit. Sie tauschen lediglich p.chromium gegen p.firefox oder p.webkit – Sitekey-Auslesen, Lösen und Token-Einfügen bleiben unverändert.

Verwandte Leitfäden

Kommentare sind für diesen Artikel deaktiviert.