Um ein Cloudflare Turnstile mit CaptchaAI zu lösen, brauchen Sie genau zwei Angaben: den Sitekey und die Page-URL. Die Page-URL steht in der Adressleiste – der Sitekey dagegen versteckt sich je nach Integration im HTML-Attribut, in einem JavaScript-Aufruf oder in der URL des Widget-Iframes. Dieser Leitfaden zeigt drei zuverlässige Wege, den Sitekey aus einer beliebigen Seite auszulesen, und übergibt ihn anschließend per API an CaptchaAI. Turnstile zählt zu den am schnellsten wachsenden CAPTCHA-Typen im Web – entsprechend oft stoßen Scraping- und Automatisierungs-Workflows darauf.
Wo der Turnstile-Sitekey steckt
Ein Turnstile-Sitekey taucht an drei Stellen auf:
- Im
data-sitekey-Attribut von.cf-turnstile-Elementen - Im JavaScript-Aufruf
turnstile.render() - In der
src-URL des Turnstile-Iframes
Für jede Seite greift mindestens einer dieser drei Wege. Beginnen Sie immer mit dem DOM-Attribut (Methode 1): Es ist am schnellsten und kommt ohne ausgeführtes JavaScript aus. Bindet die Seite das Widget programmgesteuert ein und das Attribut fehlt, wechseln Sie zum Renderaufruf (Methode 2). Als verlässlicher Rückfall bleibt die Iframe-URL (Methode 3) – sobald das Widget gerendert ist, steht der Sitekey stabil im src-Parameter.
Methode 1: DOM-Attribut
Der Standardfall: Das Widget ist als <div class="cf-turnstile" data-sitekey="…"> im Markup verankert. Ein Einzeiler in der Browser-Konsole listet alle Turnstile-Instanzen samt Attributen auf:
// Browser console
document.querySelectorAll('.cf-turnstile').forEach((el, i) => {
console.log(`Turnstile ${i}:`, {
sitekey: el.getAttribute('data-sitekey'),
action: el.getAttribute('data-action'),
cData: el.getAttribute('data-cdata'),
theme: el.getAttribute('data-theme'),
});
});
Die relevanten Attribute im Überblick:
data-sitekey– der Wert, den Sie an CaptchaAI übergebendata-action– optionales Aktions-Label, das die Zielseite bei der Prüfung erwartetdata-cdata– optionale Kundendaten, die manche Integrationen mitschickendata-theme– rein kosmetisch und für die Lösung irrelevant
Python (statisches HTML)
Steht der Sitekey bereits im ausgelieferten HTML, genügt ein einfacher Request plus regulärer Ausdruck – kein Browser nötig:
import re
import requests
html = requests.get("https://example.com/login").text
matches = re.findall(
r'class=["\'][^"\']*cf-turnstile[^"\']*["\'][^>]*data-sitekey=["\']([^"\']+)',
html
)
for sk in matches:
print(f"Sitekey: {sk}")
Python (Selenium)
Wird das Widget erst per JavaScript in die Seite geschrieben, sehen Sie es im rohen HTML nicht. Dann rendert Selenium die Seite vollständig und liest das Attribut aus dem fertigen DOM:
from selenium import webdriver
from selenium.webdriver.common.by import By
driver = webdriver.Chrome()
driver.get("https://example.com/login")
widgets = driver.find_elements(By.CSS_SELECTOR, ".cf-turnstile")
for w in widgets:
sitekey = w.get_attribute("data-sitekey")
action = w.get_attribute("data-action")
print(f"Sitekey: {sitekey}, Action: {action}")
Methode 2: JavaScript-Renderaufruf
Manche Seiten binden Turnstile ohne data-sitekey-Attribut ein und rendern das Widget stattdessen programmgesteuert:
turnstile.render('#captcha-container', {
sitekey: '0x4AAAAAAAB...',
callback: function(token) {
document.getElementById('cf-token').value = token;
},
});
Den Sitekey holen Sie dann direkt aus dem Seitenquelltext oder aus dem gebündelten Skript:
# Find turnstile.render calls
render_match = re.search(
r'turnstile\.render\s*\([^,]*,\s*\{([^}]+)\}',
html
)
if render_match:
config = render_match.group(1)
sk = re.search(r'sitekey\s*:\s*["\']([^"\']+)', config)
if sk:
print(f"Sitekey from render: {sk.group(1)}")
Abfangen mit Puppeteer
Liegt der Aufruf in einem minifizierten Bundle oder wird der Sitekey dynamisch berechnet, hilft ein regulärer Ausdruck nicht weiter. In diesem Fall setzen Sie den turnstile.render-Aufruf ab, bevor die Seite lädt, und protokollieren die übergebenen Parameter live:
// Intercept turnstile.render before page loads
await page.evaluateOnNewDocument(() => {
window.__turnstileParams = [];
const origRender = window.turnstile?.render;
Object.defineProperty(window, 'turnstile', {
set(val) {
this._turnstile = val;
const orig = val.render;
val.render = function(container, params) {
window.__turnstileParams.push(params);
console.log('Turnstile render:', JSON.stringify(params));
return orig.apply(this, arguments);
};
},
get() { return this._turnstile; }
});
});
await page.goto('https://example.com/login', { waitUntil: 'networkidle2' });
const params = await page.evaluate(() => window.__turnstileParams);
console.log('Captured Turnstile params:', params);
Methode 3: Iframe-src
Turnstile rendert ein Iframe von challenges.cloudflare.com. Sobald es geladen ist, steht der Sitekey verlässlich in dessen src-URL – das macht diese Methode zum robustesten Rückfall:
document.querySelectorAll('iframe').forEach(iframe => {
if (iframe.src.includes('challenges.cloudflare.com')) {
console.log('Turnstile iframe:', iframe.src);
const match = iframe.src.match(/sitekey=([A-Za-z0-9_-]+)/);
if (match) console.log('Sitekey:', match[1]);
}
});
Turnstile mit CaptchaAI lösen
Turnstile ist ein regulär unterstützter Typ – der Parameter lautet method=turnstile. Für den Aufruf brauchen Sie drei Angaben:
- den
sitekeyaus einer der drei Methoden oben - die
pageurlder Seite, auf der das Widget erscheint - Ihren
API_KEYaus dem CaptchaAI-Dashboard
Die Abrechnung erfolgt Thread-basiert: Sie zahlen pro gleichzeitigem Thread, nicht pro Lösung. Schon der Tarif BASIC (15 $/Monat, 5 Threads) deckt kleinere Scraper ab; für parallele Pipelines skalieren Sie über die höheren Tarife.
Python
Der Ablauf ist zweistufig: Aufgabe an in.php übermitteln, dann das Ergebnis an res.php abfragen (Polling), bis das Token vorliegt:
import requests
import time
API_KEY = "YOUR_API_KEY"
SITEKEY = "0x4AAAAAAAB..."
PAGE_URL = "https://example.com/login"
# Submit
resp = requests.post("https://ocr.captchaai.com/in.php", data={
"key": API_KEY,
"method": "turnstile",
"sitekey": SITEKEY,
"pageurl": PAGE_URL,
"json": "1",
}).json()
if resp["status"] != 1:
raise Exception(f"Submit error: {resp['request']}")
task_id = resp["request"]
# Poll
for _ in range(24):
time.sleep(5)
result = requests.get("https://ocr.captchaai.com/res.php", params={
"key": API_KEY, "action": "get", "id": task_id, "json": "1"
}).json()
if result["status"] == 1:
token = result["request"]
print(f"Turnstile token: {token[:50]}...")
break
if result["request"] != "CAPCHA_NOT_READY":
raise Exception(f"Error: {result['request']}")
JavaScript
Dieselbe Logik in Node.js mit axios – Übermittlung, dann Polling im Fünf-Sekunden-Takt:
const axios = require('axios');
const submit = await axios.post('https://ocr.captchaai.com/in.php', null, {
params: {
key: 'YOUR_API_KEY',
method: 'turnstile',
sitekey: '0x4AAAAAAAB...',
pageurl: 'https://example.com/login',
json: 1,
}
});
const taskId = submit.data.request;
// Poll for result
let token = null;
for (let i = 0; i < 24; i++) {
await new Promise(r => setTimeout(r, 5000));
const poll = await axios.get('https://ocr.captchaai.com/res.php', {
params: { key: 'YOUR_API_KEY', action: 'get', id: taskId, json: 1 }
});
if (poll.data.status === 1) {
token = poll.data.request;
break;
}
}
console.log(`Token: ${token.substring(0, 50)}...`);
Token in das Formularfeld eintragen
Turnstile legt seinen Token in einem versteckten Input-Feld namens cf-turnstile-response ab. Nach dem Lösen tragen Sie den Wert dort ein und rufen zusätzlich den Widget-Callback auf, damit die Seite das Token als gültig akzeptiert:
# Selenium
driver.execute_script("""
const input = document.querySelector('input[name="cf-turnstile-response"]');
if (input) input.value = arguments[0];
// Also set in the Turnstile widget's callback
const widget = document.querySelector('.cf-turnstile');
const callbackName = widget?.getAttribute('data-callback');
if (callbackName && typeof window[callbackName] === 'function') {
window[callbackName](arguments[0]);
}
""", token)
Typische Fehler und ihre Lösung
| Problem | Ursache | Lösung |
|---|---|---|
Kein .cf-turnstile-Element gefunden |
Dynamisch gerendert | Auf vollständigen Seitenaufbau warten oder einen MutationObserver einsetzen |
| Sitekey leer | Wird über die JavaScript-API gesetzt | In den Skripten nach turnstile.render suchen |
| Token abgelehnt | Falscher Sitekey oder falsche Page-URL | Beide Werte gegen die Zielseite abgleichen |
method-Parameter falsch |
userrecaptcha statt Turnstile verwendet |
method=turnstile setzen |
Hinweis für Scraping-Projekte im DACH-Raum
Wenn Sie Turnstile-geschützte Seiten im Rahmen eines Scraping- oder Monitoring-Projekts automatisiert abrufen, gehört die rechtliche Seite von Anfang an in die Planung:
- DSGVO: IP-Adressen gelten als personenbezogene Daten – klären Sie Ihre Rechtsgrundlage und dokumentieren Sie die Datenflüsse.
- Nutzungsbedingungen: Der Zugriff auf fremde Portale sollte durch die AGB der Zielseite gedeckt sein.
- Staging zuerst: Prüfen Sie Extraktions- und Lösungslogik gegen eine eigene Umgebung wie
https://staging.example-app.test/login, bevor Sie sie auf produktive Ziele richten.
Häufige Fragen
Woran erkenne ich, dass eine Seite Cloudflare Turnstile einsetzt?
Am .cf-turnstile-Container oder an einem Iframe von challenges.cloudflare.com. Öffnen Sie die Entwicklertools und suchen Sie im DOM nach beiden – ist eines davon vorhanden, läuft Turnstile.
Kann ich den Sitekey einmal extrahieren und wiederverwenden?
In der Regel ja. Der Sitekey ist Teil der festen Turnstile-Konfiguration einer Domain und ändert sich selten. Prüfen Sie ihn dennoch gelegentlich nach, da Betreiber das Widget neu einrichten können.
Wie lange bleibt ein gelöstes Turnstile-Token gültig?
Nur wenige Minuten. Reichen Sie das Token unmittelbar nach dem Lösen bei Ihrem Zielformular ein; ein abgelaufenes Token wird mit einem Fehler abgewiesen.
Funktioniert die Extraktion auch bei unsichtbaren Turnstile-Widgets?
Ja. In den Modi „verwaltet“ und „nicht interaktiv“ zeigt Turnstile kein sichtbares Widget, doch der Sitekey steckt weiterhin im data-sitekey-Attribut, im Renderaufruf oder in der Iframe-URL – alle drei Methoden greifen unverändert.
Turnstile per API lösen – jetzt starten
Holen Sie sich Ihren API-Schlüssel auf captchaai.com, übergeben Sie Sitekey und Page-URL mit method=turnstile und bauen Sie das gelöste Token in Ihren Automatisierungs-Flow ein.