Das Ärgerlichste an Cloudflare Turnstile ist selten der Fehlercode, den Sie sofort sehen – es ist das gültige Token, das Ihre API zurückliefert und das die Zielseite trotzdem ablehnt. Genau hier verlieren die meisten Integrationen die meiste Zeit.
Fast jeder Turnstile-Fehler lässt sich einer von drei Phasen zuordnen: der Anfragephase (Ihre Übermittlung an die API wird abgelehnt), der Ergebnisphase (die Abfrage schlägt fehl oder läuft in ein Timeout) und der Validierungsphase auf der Zielseite (die API liefert ein gültiges Token, die Seite weist es aber zurück). Wer weiß, in welcher Phase der Fehler entsteht, hört auf, Lösungen zu raten.
Hinter der überwiegenden Mehrheit aller Turnstile-Probleme stecken drei Ursachen:
- Falsche exakte Seiten-URL – besonders auf Cloudflare-Challenge-Seiten, wo der Kontext strenger geprüft wird
- Falscher Sitekey – aus dem falschen Element oder einer anderen Widget-Instanz ausgelesen
- Token über den falschen Pfad angewendet – die Seite erwartet
cf-turnstile-response, einen Callback oder beides
CaptchaAI löst Turnstile mit einer durchweg hohen Erfolgsquote in unter 10 Sekunden. Scheitert Ihre Integration, liegt es fast immer an den Parametern, die Sie senden, oder daran, wie Sie das zurückgegebene Token anwenden.
Schnelldiagnose: Symptom, Phase und Lösung auf einen Blick
Wenn Sie es eilig haben, ordnen Sie Ihr Symptom zuerst hier zu. Die Tabelle nennt für jeden Fehler die Phase, in der er entsteht, die wahrscheinliche Ursache und den schnellsten Fix – die Detailabschnitte darunter erklären jeweils das Warum.
| Fehler / Symptom | Phase | Wahrscheinliche Ursache | Lösung |
|---|---|---|---|
ERROR_WRONG_USER_KEY |
Übermittlung | Ungültiger API-Schlüssel | 32-stelligen Schlüssel prüfen |
ERROR_KEY_DOES_NOT_EXIST |
Übermittlung | Ungültiger Schlüssel | Dashboard prüfen |
ERROR_ZERO_BALANCE |
Übermittlung | Kein freier Thread | Warten oder Plan wechseln |
ERROR_PAGEURL |
Übermittlung | pageurl fehlt |
Vollständige URL ergänzen |
ERROR_BAD_PARAMETERS |
Übermittlung | Sitekey, Methode oder pageurl fehlen | Alle Pflichtfelder prüfen |
CAPCHA_NOT_READY |
Abfrage | Lösung läuft noch | 5 Sekunden warten, erneut abfragen |
ERROR_WRONG_ID_FORMAT |
Abfrage | Nicht-numerische CAPTCHA-ID | Exakte ID aus in.php verwenden |
ERROR_WRONG_CAPTCHA_ID |
Abfrage | Ungültige CAPTCHA-ID | Übermittlungs-ID prüfen |
ERROR_EMPTY_ACTION |
Abfrage | action=get fehlt |
Action-Parameter ergänzen |
| Token von der Seite abgelehnt | Validierung | Falsches Feld, Callback nicht ausgelöst, falsche URL | Feldnamen prüfen, Callback aufrufen, exakte pageurl bestätigen |
| Zweite Lösung scheitert | Validierung | Token wiederverwendet | Pro Übermittlung frisches Token anfordern |
Turnstile oder Cloudflare Challenge – womit haben Sie es zu tun?
| Signal | Turnstile | Cloudflare Challenge |
|---|---|---|
| Was Sie sehen | Eingebettetes Widget auf der Seite (Kontrollkästchen oder unsichtbar) | Ganzseitiger Cloudflare-Verifizierungsbildschirm |
| Was CaptchaAI zurückgibt | Ein Token zum Einfügen ins Formular | Ein cf_clearance-Cookie |
| API-Methode | turnstile |
cloudflare_challenge |
| Proxy nötig? | Optional | Ja (erforderlich) |
Klären Sie das zuerst, denn beide Fälle brauchen unterschiedliche Fixes. Treffen Sie auf eine ganzseitige Cloudflare-Challenge (kein eingebettetes Widget), brauchen Sie stattdessen den Cloudflare-Challenge-Löser; er liefert ein cf_clearance-Cookie und benötigt einen Proxy. Der Rest dieses Leitfadens behandelt das eingebettete Turnstile-Widget.
Was Turnstile bei der Fehlersuche besonders macht
Bevor Sie sich in einzelne Fehlercodes vertiefen, sollten Sie drei Eigenheiten kennen, die Turnstile von anderen CAPTCHA-Typen unterscheiden.
Zwei Wege, das Token anzuwenden
Das zurückgegebene Token lässt sich auf zwei Arten einsetzen, und der falsche Weg scheitert stillschweigend:
| Methode | Wann geeignet |
|---|---|
Verstecktes Feld – Token in cf-turnstile-response (und mitunter g-recaptcha-response) eintragen |
Wenn die Seite ein Standardformular mit einem versteckten Eingabefeld verwendet |
Callback-Funktion – die in turnstile.render() oder data-callback definierte Funktion aufrufen |
Wenn die Seite programmatisch validiert statt über ein Formular |
Die exakte Seiten-URL wiegt schwerer
Turnstile-Token sind eng an den Seitenkontext gebunden. Auf Cloudflare-Challenge-Seiten (dem ganzseitigen Verifizierungsbildschirm) führt schon eine geringfügig abweichende URL – ein anderer Pfad, ein fehlender Query-Parameter – dazu, dass das Token abgelehnt wird.
Token gelten nur für eine einzige Übermittlung
Ein Turnstile-Token lässt sich genau einmal verifizieren. Sendet Ihre Automatisierung es versehentlich zweimal oder liegt eine Race Condition vor, scheitert der zweite Versuch.
Fehler in der Anfragephase (Übermittlung an in.php)
Diese Fehler entstehen beim Absenden der Aufgabe an https://ocr.captchaai.com/in.php. Die einfachen Fälle betreffen Schlüssel, Guthaben und Serverzustand:
| Fehler | Ursache | Lösung |
|---|---|---|
ERROR_WRONG_USER_KEY |
Das Format des API-Schlüssels stimmt nicht (er muss 32 Zeichen lang sein) | Schlüssel unter captchaai.com/api.php abgleichen |
ERROR_KEY_DOES_NOT_EXIST |
Der Schlüssel ist korrekt formatiert, aber keinem aktiven Konto zugeordnet | Dashboard prüfen: Konto aktiv, Schlüssel korrekt übernommen |
ERROR_ZERO_BALANCE |
In Ihrem Plan ist gerade kein freier Thread verfügbar | Warten, Parallelität senken oder in einen größeren Plan wechseln |
| HTML- oder 500/502-Antwort | Vorübergehender serverseitiger Fehler | 5–10 Sekunden warten und erneut versuchen |
ERROR_PAGEURL
Der Parameter pageurl fehlt. Übergeben Sie die vollständige URL – Protokoll, Domain und Pfad:
pageurl=https://example.com/login
ERROR_BAD_PARAMETERS
Pflichtparameter fehlen oder sind fehlerhaft. Für Turnstile sind erforderlich:
| Parameter | Typ | Erforderlich | Beschreibung |
|---|---|---|---|
key |
String | Ja | Ihr CaptchaAI-API-Schlüssel |
method |
String | Ja | Muss turnstile sein |
sitekey |
String | Ja | Sitekey des Turnstile-Widgets |
pageurl |
String | Ja | Vollständige Seiten-URL |
Optional, aber hilfreich:
| Parameter | Typ | Beschreibung |
|---|---|---|
action |
String | Wert von data-action oder des action-Parameters aus turnstile.render() |
proxy |
String | Format: login:password@IP:PORT |
proxytype |
String | HTTP, HTTPS, SOCKS4, SOCKS5 |
Prüfen Sie, ob alle Pflichtfelder vorhanden und korrekt typisiert sind, bevor Sie eine tiefere Ursache vermuten.
Den richtigen Turnstile-Sitekey finden
Der Sitekey ist der Parameter, der am häufigsten falsch ist. So finden Sie ihn zuverlässig.
Option 1 – das Attribut data-sitekey:
<div class="cf-turnstile" data-sitekey="0x4AAAAAAAB1example"></div>
Option 2 – ein Aufruf von turnstile.render():
turnstile.render('#captcha-container', {
sitekey: '0x4AAAAAAAB1example',
callback: function(token) {
document.getElementById('cf-turnstile-response').value = token;
}
});
Option 3 – den Render-Aufruf abfangen (fortgeschritten):
Wird der Sitekey dynamisch geladen, können Sie turnstile.render überschreiben, bevor das Widget initialisiert wird, und so die Parameter mitlesen:
// Inject this before the Turnstile script loads
const originalRender = window.turnstile.render;
window.turnstile.render = function(container, params) {
console.log('Sitekey:', params.sitekey);
console.log('Action:', params.action);
return originalRender.call(this, container, params);
};
Fehler in der Ergebnisphase (Abfrage von res.php)
Diese Fehler entstehen beim Abfragen von https://ocr.captchaai.com/res.php. Die meisten sind selbsterklärend und in einem Zug behoben:
| Antwort | Ursache | Lösung |
|---|---|---|
CAPCHA_NOT_READY |
Kein Fehler – die Lösung läuft noch (bei CaptchaAI meist unter 10 Sekunden) | 5 Sekunden warten und erneut abfragen |
ERROR_WRONG_ID_FORMAT |
Die CAPTCHA-ID enthält nicht-numerische Zeichen | Die exakte ID aus in.php unverändert verwenden |
ERROR_WRONG_CAPTCHA_ID |
Die ID passt zu keiner übermittelten Aufgabe | Die richtige ID aus der Übermittlungsantwort abfragen |
ERROR_CAPTCHA_UNSOLVABLE |
Die Lösung ist fehlgeschlagen – möglich sind ein falscher Sitekey oder eine nicht unterstützte Seitenkonfiguration | Sitekey prüfen, Anfrage neu aufsetzen, erneut versuchen |
ERROR_INTERNAL_SERVER_ERROR |
Serverseitiges Problem | 10 Sekunden warten und erneut versuchen |
ERROR_EMPTY_ACTION
Der Parameter action fehlt in Ihrer Polling-Anfrage. Senden Sie beim Abfragen stets action=get mit:
https://ocr.captchaai.com/res.php?key=YOUR_KEY&action=get&id=CAPTCHA_ID&json=1
Hinweis: Verwenden Sie beim Abfragen
json=1, um eine JSON-Antwort der Form{"status": 1, "request": "<token>"}zu erhalten; ohne den Parameter liefert der Endpunkt einfachen Text wieOK|<token>oderCAPCHA_NOT_READY. Beide Formen funktionieren – wählen Sie die, die Ihr Parser leichter verarbeitet.
Wenn die Zielseite ein gültiges Token ablehnt
Diese Fälle sind am schwersten zu debuggen: Die API liefert erfolgreich ein Token, doch die Zielseite weist es zurück. Zwei Ursachen betreffen das Formularfeld selbst.
Fall 1: Token im falschen Feld
Das Formular wird abgesendet, aber die Seite meldet einen Validierungsfehler oder lädt neu. Turnstile-Seiten können das Token in verschiedenen Feldern erwarten:
cf-turnstile-response– das primäre versteckte Turnstile-Feldg-recaptcha-response– manche Seiten nutzen dies als Fallback
Prüfen Sie das Formular der Seite auf beide Felder. In der Browser-Automatisierung:
# Selenium — inject into both fields for safety
driver.execute_script("""
var cfField = document.querySelector('[name="cf-turnstile-response"]');
var gField = document.querySelector('[name="g-recaptcha-response"]');
if (cfField) cfField.value = arguments[0];
if (gField) gField.value = arguments[0];
""", token)
Fall 2: Callback wird nicht ausgelöst
Das Token steht im Feld, aber das Formular blockiert die Übermittlung weiterhin. Die Seite nutzt dann eine Callback-Funktion statt (oder zusätzlich zu) dem versteckten Feld; der Callback übernimmt weitere Logik – etwa das Freischalten der Absenden-Schaltfläche oder das Auslösen einer AJAX-Anfrage. Ermitteln Sie den Callback und rufen Sie ihn auf:
// Check data-callback attribute
const callbackName = document.querySelector('.cf-turnstile').getAttribute('data-callback');
if (callbackName && window[callbackName]) {
window[callbackName](token);
}
// Or if it was passed in turnstile.render()
// You may need to intercept the render call to capture it
Die letzten beiden Fälle betreffen nicht das Feld, sondern den Kontext und die Gültigkeit des Tokens:
| Symptom | Ursache | Lösung |
|---|---|---|
| Token trotz korrektem Sitekey und frischer Lösung abgelehnt | Der pageurl passt nicht zum echten Seitenkontext – häufig auf Cloudflare-Challenge-Seiten und in Single-Page-Applications, wo die sichtbare Adresse von der Lade-URL abweicht |
Im „Netzwerk"-Tab der DevTools die exakte URL ermitteln, unter der das Widget lädt, und genau diese als pageurl übergeben |
| Erste Lösung funktioniert, die folgenden scheitern | Turnstile-Token gelten nur für eine Übermittlung; nach der Prüfung durch Cloudflare ist das Token ungültig | Für jede Formularübermittlung eine frische Lösung anfordern; Token weder zwischenspeichern noch wiederverwenden |
Aus der Praxis: Turnstile im DACH-Checkout-Test
Ein Muster, das in DACH-Teams immer wieder auftaucht: Ein Shop läuft auf Shopware oder JTL, der Checkout ist mit Turnstile abgesichert, und die QA testet den Kaufabschluss in einer eigenen Staging-Umgebung wie https://staging.shop.example.test/checkout. Der Worker liegt auf einem Hetzner-VPS, die API liefert zuverlässig Token – trotzdem bricht der Test beim Absenden ab.
In neun von zehn Fällen liegt es am pageurl. Der Test übergibt die Basis-URL des Shops, während das Widget tatsächlich unter der Checkout-URL mit angehängten Query-Parametern lädt. Sobald der Kontext exakt stimmt, wird das Token akzeptiert. Der zweite häufige Grund tritt in SPA-basierten Storefronts auf: Die sichtbare Adresse in der Adressleiste hat sich per Client-Routing geändert, das Widget wurde aber unter einer anderen URL initialisiert – hier hilft nur der Blick in den „Netzwerk"-Tab.
Zum Verifizieren des Fixes lohnt ein zweiter Testlauf mit protokolliertem pageurl und – falls das Widget einen action-Wert setzt – mitgesendetem action-Parameter; so schließen Sie aus, dass ein zweiter Fehler den ersten überdeckt. Zahlungsschritte im Checkout-Test bilden Sie über die Sandbox-Modi der Zahlungsanbieter mit Test-Token ab, nie mit echten Kartendaten.
Wer personenbezogene Daten testweise verarbeitet, sollte dabei die DSGVO im Blick behalten: IP-Adressen gelten als personenbezogen, und die Rechtsgrundlage für Testdaten sollte dokumentiert sein. Prüfen Sie stets nur eigene oder ausdrücklich autorisierte Umgebungen.
Vollständige Lösung in Python und Node.js
Die folgenden beiden Referenzimplementierungen übermitteln eine Turnstile-Aufgabe, fragen das Ergebnis ab und geben das gelöste Token zurück – das Grundgerüst, in das Sie Ihre Sitekey- und pageurl-Fixes einsetzen.
Python
import time
import requests
API_KEY = "YOUR_CAPTCHAAI_API_KEY"
SITEKEY = "0x4AAAAAAAB1example"
PAGE_URL = "https://example.com/login"
SUBMIT_URL = "https://ocr.captchaai.com/in.php"
RESULT_URL = "https://ocr.captchaai.com/res.php"
def solve_turnstile(api_key, sitekey, pageurl):
"""Submit a Turnstile challenge and return the solved token."""
# Submit
submit_resp = requests.post(
SUBMIT_URL,
data={
"key": api_key,
"method": "turnstile",
"sitekey": sitekey,
"pageurl": pageurl,
"json": 1,
},
timeout=30,
)
submit_resp.raise_for_status()
submit_data = submit_resp.json()
if submit_data.get("status") != 1:
raise RuntimeError(f"Submit failed: {submit_data}")
captcha_id = submit_data["request"]
print(f"Task created — captcha ID: {captcha_id}")
# Wait before first poll (Turnstile is fast — 10 seconds is usually enough)
time.sleep(10)
# Poll for result
for _ in range(60):
result_resp = requests.get(
RESULT_URL,
params={
"key": api_key,
"action": "get",
"id": captcha_id,
"json": 1,
},
timeout=30,
)
result_resp.raise_for_status()
result_data = result_resp.json()
if result_data.get("request") == "CAPCHA_NOT_READY":
time.sleep(5)
continue
if result_data.get("status") == 1:
return result_data["request"]
raise RuntimeError(f"Polling error: {result_data}")
raise TimeoutError("Turnstile solve timed out")
# Usage
token = solve_turnstile(API_KEY, SITEKEY, PAGE_URL)
print(f"Solved token: {token[:80]}...")
# Inject into cf-turnstile-response and/or g-recaptcha-response
# Then submit the form
Node.js
const API_KEY = "YOUR_CAPTCHAAI_API_KEY";
const SITEKEY = "0x4AAAAAAAB1example";
const PAGE_URL = "https://example.com/login";
const SUBMIT_URL = "https://ocr.captchaai.com/in.php";
const RESULT_URL = "https://ocr.captchaai.com/res.php";
function sleep(ms) {
return new Promise((resolve) => setTimeout(resolve, ms));
}
async function solveTurnstile(apiKey, sitekey, pageurl) {
// Submit
const submitResp = await fetch(SUBMIT_URL, {
method: "POST",
headers: { "Content-Type": "application/x-www-form-urlencoded" },
body: new URLSearchParams({
key: apiKey,
method: "turnstile",
sitekey: sitekey,
pageurl: pageurl,
json: "1",
}),
});
const submitData = await submitResp.json();
if (submitData.status !== 1) {
throw new Error(`Submit failed: ${JSON.stringify(submitData)}`);
}
const captchaId = submitData.request;
console.log(`Task created — captcha ID: ${captchaId}`);
// Turnstile is fast — wait 10 seconds before first poll
await sleep(10_000);
// Poll for result
for (let i = 0; i < 60; i++) {
const resultResp = await fetch(
`${RESULT_URL}?${new URLSearchParams({
key: apiKey,
action: "get",
id: captchaId,
json: "1",
})}`
);
const resultData = await resultResp.json();
if (resultData.request === "CAPCHA_NOT_READY") {
await sleep(5_000);
continue;
}
if (resultData.status === 1) {
return resultData.request;
}
throw new Error(`Polling error: ${JSON.stringify(resultData)}`);
}
throw new Error("Turnstile solve timed out");
}
// Usage
solveTurnstile(API_KEY, SITEKEY, PAGE_URL)
.then((token) => {
console.log(`Solved token: ${token.slice(0, 80)}...`);
// Inject into cf-turnstile-response and/or g-recaptcha-response
})
.catch(console.error);
FAQ
Kostet mich ein fehlgeschlagener Turnstile-Versuch Guthaben?
Nein – CaptchaAI rechnet Thread-basiert ab, nicht pro Lösung. Ein Thread ist eine gleichzeitig laufende Anfrage; sobald sie abgeschlossen ist, wird der Thread wieder frei. Jeder Plan enthält unbegrenzte Lösungen pro Thread, es gibt keine Gebühr pro CAPTCHA. Der Einstieg beginnt bei BASIC (15 $/Monat, 5 Threads).
Wie viele Turnstile-Token kann ich gleichzeitig lösen?
So viele, wie Ihr Plan Threads bereitstellt: BASIC (15 $/Monat) bietet 5 gleichzeitige Threads, STANDARD (30 $/Monat) 15 und ADVANCE (90 $/Monat) 50. Erscheint ERROR_ZERO_BALANCE, sind alle Threads belegt – senken Sie die Parallelität oder wechseln Sie in einen größeren Plan.
Warum wird mein Token nur beim ersten Mal akzeptiert?
Weil Turnstile-Token nur für eine einzige Übermittlung gelten. Nach der Prüfung durch den Cloudflare-Server ist das Token verbraucht. Fordern Sie für jede Formularübermittlung eine frische Lösung an und speichern Sie Token nicht zwischen – sie laufen ohnehin nach kurzer Zeit ab.
Turnstile oder Cloudflare Challenge – woran erkenne ich den Unterschied?
Turnstile ist ein eingebettetes Widget und liefert ein Token für ein Formularfeld. Die Cloudflare Challenge ist ein ganzseitiger Verifizierungsbildschirm und liefert ein cf_clearance-Cookie. Sehen Sie ein kompaktes Widget, ist es Turnstile (method=turnstile); füllt der Sperrbildschirm das ganze Fenster, brauchen Sie cloudflare_challenge plus Proxy.
Was bedeutet CAPCHA_NOT_READY?
Das ist kein Fehler, sondern der Hinweis, dass die Lösung noch läuft. Warten Sie 5 Sekunden und fragen Sie das Ergebnis erneut ab. Turnstile-Lösungen sind bei CaptchaAI meist in unter 10 Sekunden fertig.
Turnstile-Workflow korrigieren
Wenn Ihre Turnstile-Integration scheitert, arbeiten Sie diese fünf Punkte der Reihe nach ab:
- Sitekey prüfen – aus
data-sitekeyoderturnstile.render()auslesen - Seiten-URL prüfen – die exakte URL inklusive Protokoll und Pfad verwenden
- Token-Pfad prüfen – erwartet die Seite
cf-turnstile-response,g-recaptcha-responseoder einen Callback? json=1nutzen – beim Abfragen von Turnstile-Ergebnissen immer JSON-Antworten anfordern- Token nicht wiederverwenden – pro Übermittlung eine frische Lösung anfordern
Starten Sie mit dem CaptchaAI-Turnstile-Löser, gleichen Sie Ihre Parameter mit den API-Dokumenten ab und lesen Sie So funktioniert Cloudflare Turnstile, wenn Sie Hintergrund zur Widget-Mechanik brauchen.