Referenz

Chrome DevTools Protocol + CaptchaAI: CAPTCHA-Diagnose in eigenen Testumgebungen

Anwendungsbereich: Dieser Leitfaden gilt ausschließlich für eigene oder ausdrücklich autorisierte QA- und Staging-Umgebungen. Er beschreibt Diagnose- und Verifikationsschritte für Ihre eigene CAPTCHA-Integration – nicht für fremde Websites oder unautorisierte Workflows.

Wenn eine CAPTCHA-Integration in Staging plötzlich rote Testläufe produziert, lautet die erste Frage selten „Löst der Solver korrekt?" – sondern „Kommt im Backend überhaupt an, was der Browser verschickt?". Genau hier setzt das Chrome DevTools Protocol (CDP) an: Es macht jeden Netzwerk-Request, jeden geladenen Sitekey und jede Serverantwort in Ihrem eigenen Testlauf sichtbar. Zusammen mit CaptchaAI wird daraus eine durchgehende Diagnosekette – vom geladenen Widget bis zur validierten Backend-Antwort. CDP liefert dabei keine „niedrigere Automatisierungsebene", sondern eine präzise Beobachtungsschicht für Ihre QA.


Wann CDP in der CAPTCHA-QA den Unterschied macht

CDP ist immer dann nützlich, wenn Ihre Testsuite eine konkrete Ja-oder-Nein-Frage beantworten soll, statt zu raten:

  • Lädt das CAPTCHA-Widget auf Ihrer Staging-Seite zum richtigen Zeitpunkt?
  • Verwendet die Seite pro Umgebung den erwarteten Sitekey?
  • Trifft die Verifikationsanfrage mit den erwarteten Parametern im Backend ein?
  • Stimmen Antwortcodes, Fehlertexte und Telemetrie mit Ihrer Testdokumentation überein?

Für keine dieser Aufgaben brauchen Sie Verdeckungs- oder Umgehungslogik. Entscheidend ist, dass Requests, Konsolenmeldungen und Serverantworten in Ihrer eigenen Umgebung reproduzierbar und nachvollziehbar bleiben. Genau das trennt eine belastbare QA-Diagnose von einem Fehlerbild, das sich beim nächsten Lauf scheinbar zufällig ändert.


Netzwerk-Requests und DOM-Zustand mit CDP beobachten

In einem einzigen Testlauf kann CDP mehrere Signale gleichzeitig sichtbar machen. Die folgende Tabelle zeigt, worauf sich das Mitschneiden in der Praxis lohnt:

Beobachtung Warum sie in QA zählt Was Sie prüfen sollten
Netzwerk-Request zum Widget Bestätigt das Laden des CAPTCHA-Skripts Host, Query-Parameter, Statuscode
DOM-Zustand des Widgets Zeigt, ob Sitekey und Callback korrekt gesetzt sind data-sitekey, Widget-Container, Fehlerzustand
Request zur Verifikation Bestätigt den Backend-Pfad Ziel-Endpunkt, Request-ID, Antwortzeit
Serverantwort Erklärt Testerfolg oder Testfehler success, Fehlercode, Staging-Metadaten

Eine schlanke CDP-Verbindung für solche Testdiagnosen kommt mit wenig Code aus. Sie öffnet einen WebSocket zur Debugging-Schnittstelle und aktiviert die Domains, die Sie zum Mitschneiden brauchen:

import http from "node:http";
import WebSocket from "ws";

async function connectToCdp(port = 9222) {
  const targets = await new Promise((resolve, reject) => {
    http.get(`http://127.0.0.1:${port}/json/list`, (res) => {
      let body = "";
      res.on("data", (chunk) => (body += chunk));
      res.on("end", () => resolve(JSON.parse(body)));
    }).on("error", reject);
  });

  const pageTarget = targets.find((target) => target.type === "page");
  const ws = new WebSocket(pageTarget.webSocketDebuggerUrl);

  await new Promise((resolve, reject) => {
    ws.once("open", resolve);
    ws.once("error", reject);
  });

  let id = 0;
  const send = (method, params = {}) => {
    const requestId = ++id;
    ws.send(JSON.stringify({ id: requestId, method, params }));
    return requestId;
  };

  send("Page.enable");
  send("Runtime.enable");
  send("Network.enable");

  return { ws, send };
}

Den Sitekey gegen die Staging-Seite abgleichen

In der QA sollten Sie den Sitekey nicht raten, sondern gegen die tatsächlich geladene Staging-Seite prüfen. So erkennen Sie Konfigurationsdrift – etwa einen Produktions-Sitekey, der versehentlich in die Testumgebung geraten ist – lange bevor er einen roten Lauf verursacht.

async function readSitekey(pageUrl) {
  const targetResponse = await fetch(
    "http://127.0.0.1:9222/json/new?" + encodeURIComponent(pageUrl)
  );
  const target = await targetResponse.json();
  const ws = new WebSocket(target.webSocketDebuggerUrl);

  await new Promise((resolve, reject) => {
    ws.once("open", resolve);
    ws.once("error", reject);
  });

  ws.send(JSON.stringify({ id: 1, method: "Runtime.evaluate", params: {
    expression: `(() => {
      const widget = document.querySelector('[data-sitekey]');
      if (!widget) return null;
      return {
        sitekey: widget.getAttribute('data-sitekey'),
        widgetType: widget.className,
        pageUrl: location.href,
      };
    })()`,
    returnByValue: true,
  }}));

  return await new Promise((resolve) => {
    ws.on("message", (payload) => {
      const message = JSON.parse(payload);
      if (message.id === 1) {
        resolve(message.result.result.value);
        ws.close();
      }
    });
  });
}

Wichtiger als die Browsersteuerung ist hier der Abgleich mit Ihrer Staging-Konfiguration. Drei Fragen gehören in jede Prüfroutine:

  • Stimmt der ausgelesene Sitekey mit der erwarteten Umgebung überein?
  • Wird das Widget nur auf den vorgesehenen Formularen geladen?
  • Ist der Callback- oder Action-Name in Ihren Testdaten dokumentiert?

Die CaptchaAI-Aufgabe aus demselben QA-Lauf starten

Sobald Page-URL und Sitekey aus Ihrer eigenen Testumgebung bestätigt sind, starten Sie eine CaptchaAI-Aufgabe aus demselben QA-Lauf und nehmen das Ergebnis in die Diagnosekette auf. Der Ablauf ist bewusst schlicht: Aufgabe übermitteln, den Status abfragen, Token entgegennehmen.

async function submitCaptchaTask({ apiKey, pageUrl, sitekey }) {
  const body = new URLSearchParams({
    key: apiKey,
    method: "userrecaptcha",
    googlekey: sitekey,
    pageurl: pageUrl,
    json: "1",
  });

  const submit = await fetch("https://ocr.captchaai.com/in.php", {
    method: "POST",
    body,
  });
  const submitJson = await submit.json();

  if (submitJson.status !== 1) {
    throw new Error(`CaptchaAI submit failed: ${submitJson.request}`);
  }

  for (let attempt = 0; attempt < 30; attempt += 1) {
    await new Promise((resolve) => setTimeout(resolve, 5000));
    const poll = await fetch(
      `https://ocr.captchaai.com/res.php?key=${apiKey}&action=get&id=${submitJson.request}&json=1`
    );
    const pollJson = await poll.json();
    if (pollJson.status === 1) {
      return pollJson.request;
    }
  }

  throw new Error("CaptchaAI result timeout in QA run");
}

Dieser Schritt bildet die Integrationskette ab: Widget erkannt, Aufgabe erzeugt, Token erhalten. Praktisch für die Testplanung: CaptchaAI rechnet pro gleichzeitigem Thread ab, nicht pro Lösung. Wer viele Staging-Läufe parallel fährt, wählt einfach einen Plan mit mehr Threads – etwa BASIC (15 $/Monat, 5 Threads) für einzelne Pipelines oder STANDARD (30 $/Monat, 15 Threads) für breitere Testmatrizen. Die eigentliche Validierung läuft anschließend gegen Ihre eigene Prüfroute.


Der eigentliche Prüfpunkt: die Backend-Validierung

Der wichtigste Diagnoseschritt ist meist nicht der Browser, sondern Ihr eigener Verifikationspfad. Lassen Sie Ihre QA-Suite deshalb die Backend-Antwort mitsamt Request-ID protokollieren – nur so werden Fehler reproduzierbar.

async function verifyInQaBackend({ token, testRunId }) {
  const response = await fetch("https://staging.example-app.test/qa/captcha/verify", {
    method: "POST",
    headers: { "content-type": "application/json" },
    body: JSON.stringify({
      token,
      testRunId,
      expectedAction: "signup",
      environment: "staging",
    }),
  });

  if (!response.ok) {
    throw new Error(`QA verify endpoint returned ${response.status}`);
  }

  return response.json();
}

Eine belastbare QA-Antwort enthält mehr als nur success: true:

  • Request-ID oder Trace-ID
  • erkannte Action oder Widget-ID
  • Antwortzeit des Verifikationspfads
  • Fehlercode bei Negativtests
  • Umgebung (staging, qa, preprod)

Damit lassen sich Diagnosefälle reproduzierbar nachstellen, ohne in produktive Integrationen eingreifen zu müssen.


Beispiel: CDP-Diagnose in einer GitLab-CI-Pipeline

Ein typisches DACH-Setup: Die CAPTCHA-QA läuft in einem GitLab-CI-Job auf einem eigenen Hetzner-Runner, headless Chrome wird mit --remote-debugging-port=9222 gestartet, und getestet wird gegen eine Staging-Instanz – zum Beispiel den Checkout eines Shopware-Shops. Der Job durchläuft dieselbe Kette wie oben: connectToCdp verbindet sich mit dem Debugging-Port, readSitekey bestätigt den Umgebungs-Sitekey, submitCaptchaTask holt ein Token, und verifyInQaBackend prüft die Antwort der eigenen Verifikationsroute. Schlägt der Job fehl, zeigt das CDP-Protokoll sofort, ob das Widget gar nicht geladen wurde oder ob erst das Backend die Antwort verweigert.

Ein Hinweis zum Datenschutz: Sobald Sie Netzwerk-Requests mitschneiden, können reale IP-Adressen oder personenbezogene Daten in Ihren QA-Logs landen – nach DSGVO sind IP-Adressen personenbezogen. Nutzen Sie in Staging deshalb feste Testkonten und synthetische Daten, und dokumentieren Sie Aufbewahrungsfristen für Ihre Logs. Das hält die Diagnose nachvollziehbar und rechtlich sauber.


Fehlerbehebung

Problem Wahrscheinliche Ursache Lösung
Widget lädt nicht Falsches Skript oder Feature-Flag Netzwerk-Requests und Staging-Konfiguration gemeinsam prüfen
Sitekey stimmt nicht Umgebungsdrift Konfigurationswert aus Deployment und DOM vergleichen
QA-Verify-Endpoint liefert 400 Erwartete Felder fehlen Request-Log im Backend mit dem Test-Schema abgleichen
Timeout beim Polling Queue oder Rate-Limit in der Testumgebung Timeout erhöhen und Testlast separat messen
Backend-Antwort ist inkonsistent Testdaten unterscheiden sich zwischen Läufen Feste Testkonten und reproduzierbare Testfixtures verwenden

Häufige Fragen

Welche CAPTCHA-Typen lassen sich so in der QA prüfen?

Alle Typen, die CaptchaAI generell unterstützt – in diesem Setup vor allem reCAPTCHA v2/v3, Cloudflare Turnstile und Cloudflare Challenge. Der CDP-Teil erkennt nur Widget und Sitekey; die Lösung übernimmt CaptchaAI über den passenden Method-Parameter (userrecaptcha). hCaptcha und FunCaptcha werden nicht unterstützt und gehören daher nicht in Ihre Testmatrix.

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

Meist rund 120 Sekunden. Lösen Sie das Token deshalb erst unmittelbar vor der Backend-Prüfung und legen Sie es nicht für spätere Läufe an – abgelaufene Token erzeugen sonst falsch-negative Testergebnisse.

Muss ich beim Protokollieren von Netzwerk-Requests die DSGVO beachten?

Ja, sobald reale IP-Adressen oder personenbezogene Daten in Ihren QA-Logs landen. Arbeiten Sie in Staging mit festen Testkonten und synthetischen Daten und legen Sie Aufbewahrungsfristen für Logs fest – so bleibt die Diagnose sauber und nachvollziehbar.

Warum antwortet mein QA-Verify-Endpoint mit 400?

In der Regel fehlen erwartete Felder im Request. Gleichen Sie das Backend-Request-Log mit Ihrem Test-Schema ab: Sind token, testRunId und der erwartete Action-Name gesetzt? Ein 400 ist fast immer ein Schema-Problem, kein CAPTCHA-Problem.


Verwandte Leitfäden

Machen Sie Ihre CAPTCHA-Integration mit nachvollziehbaren QA-Daten überprüfbar – CaptchaAI unterstützt reproduzierbare Testläufe in eigenen Umgebungen.

Kommentare sind für diesen Artikel deaktiviert.