Mehrere CAPTCHAs auf einer einzigen Seite verarbeiten Sie zuverlässig, sobald Sie drei Schritte sauber voneinander trennen:
- Erkennen – jedes Widget einzeln über seinen Sitekey erfassen, ohne anzunehmen, dass alle denselben teilen.
- Parallel lösen – alle Abfragen gleichzeitig an CaptchaAI übermitteln, statt nacheinander.
- Zuordnen – jedes zurückgelieferte Token exakt dem Widget zuweisen, aus dem es stammt.
Der häufigste Fehler ist dabei nicht das Lösen selbst, sondern die Zuordnung: Ein Token landet im falschen Formularfeld und die Seite bleibt blockiert. Solche Seiten sind in der Praxis keine Ausnahme – ein Login-Formular mit reCAPTCHA v2, direkt darunter eine Newsletter-Anmeldung mit einem zweiten Widget, oder ein mehrstufiges Buchungsformular, bei dem jeder Schritt seine eigene Abfrage nachlädt. Dieser Leitfaden zeigt den vollständigen Ablauf mit Selenium und Puppeteer – von der Erkennung über das parallele Lösen bis zur richtigen Token-Zuordnung.
Mehrere CAPTCHAs auf der Seite erkennen
Bevor Sie etwas lösen, brauchen Sie eine vollständige Liste aller Widgets samt Sitekey. Gehen Sie nie davon aus, dass sich alle CAPTCHAs denselben Sitekey teilen – jedes Widget kann einen eigenen führen. Für einen sauberen Durchlauf erfassen Sie pro Widget drei Angaben:
- den Sitekey aus
data-sitekeyoder demk-Parameter der iframe-src, - den CAPTCHA-Typ (reCAPTCHA v2, v3 oder Turnstile),
- den optionalen
data-callback, den die Seite nach dem Lösen erwartet.
Python mit Selenium
Jedes reCAPTCHA rendert ein eigenes anchor-iframe. Filtern Sie danach und lesen Sie den Sitekey aus dem k-Parameter der src-URL aus:
from selenium import webdriver
from selenium.webdriver.common.by import By
driver = webdriver.Chrome()
driver.get("https://example.com/multi-captcha-page")
# Find all reCAPTCHA iframes
captcha_iframes = driver.find_elements(
By.CSS_SELECTOR, 'iframe[src*="recaptcha/api2/anchor"]'
)
# Extract sitekeys from each iframe's src
import re
captchas = []
for i, iframe in enumerate(captcha_iframes):
src = iframe.get_attribute("src")
match = re.search(r"k=([A-Za-z0-9_-]+)", src)
if match:
captchas.append({
"index": i,
"sitekey": match.group(1),
"iframe": iframe
})
print(f"Found {len(captchas)} CAPTCHAs on page")
for c in captchas:
print(f" [{c['index']}] sitekey: {c['sitekey']}")
Erwartete Ausgabe:
Found 2 CAPTCHAs on page
[0] sitekey: 6LcXyzABCDEF-login
[1] sitekey: 6LcAbcDEFGHI-signup
JavaScript mit Puppeteer
Über die gerenderten .g-recaptcha-Container erhalten Sie zusätzlich das Attribut data-callback – die Funktion, die Google nach dem Lösen aufrufen würde. Diese Information brauchen Sie später beim Einfügen des Tokens:
const puppeteer = require('puppeteer');
(async () => {
const browser = await puppeteer.launch({ headless: false });
const page = await browser.newPage();
await page.goto('https://example.com/multi-captcha-page', {
waitUntil: 'networkidle2'
});
// Extract all reCAPTCHA widgets from the page
const captchas = await page.evaluate(() => {
const widgets = document.querySelectorAll('.g-recaptcha');
return Array.from(widgets).map((el, i) => ({
index: i,
sitekey: el.getAttribute('data-sitekey'),
elementId: el.id || `captcha-${i}`,
callbackName: el.getAttribute('data-callback') || null
}));
});
console.log(`Found ${captchas.length} CAPTCHAs`);
captchas.forEach(c => console.log(` [${c.index}] ${c.sitekey}`));
})();
Alle CAPTCHAs gleichzeitig lösen
Lösen Sie niemals nacheinander. Ein reCAPTCHA v2 löst CaptchaAI typischerweise in unter 60 Sekunden, Cloudflare Turnstile in unter 10 Sekunden – sequenziell summieren sich diese Zeiten, parallel laufen sie gleichzeitig ab. Schicken Sie also alle Sitekeys auf einmal an CaptchaAI und fragen Sie anschließend jeden Task ab, bis sein Token vorliegt.
Der Ablauf besteht aus zwei Phasen:
- Übermitteln – alle Sitekeys parallel an
in.phpsenden und die Task-IDs einsammeln. - Abfragen – jede Task-ID über
res.phppollen, bis das Token zurückkommt.
Hinweis: Jede gleichzeitige Abfrage belegt einen Thread Ihres Tarifs. Schon der BASIC-Tarif (15 $/Monat, 5 Threads) deckt fünf parallele CAPTCHAs ab – abgerechnet wird pro Thread, nicht pro Lösung, mit unbegrenzten Lösungen pro Thread im Abrechnungsmonat.
Python
import requests
import time
from concurrent.futures import ThreadPoolExecutor, as_completed
API_KEY = "YOUR_API_KEY"
PAGE_URL = "https://example.com/multi-captcha-page"
def submit_captcha(sitekey):
resp = requests.post("https://ocr.captchaai.com/in.php", data={
"key": API_KEY,
"method": "userrecaptcha",
"googlekey": sitekey,
"pageurl": PAGE_URL,
"json": "1"
})
result = resp.json()
if result["status"] != 1:
raise Exception(f"Submit error: {result['request']}")
return result["request"]
def poll_result(task_id, timeout=120):
deadline = time.time() + timeout
while time.time() < deadline:
time.sleep(5)
resp = requests.get("https://ocr.captchaai.com/res.php", params={
"key": API_KEY,
"action": "get",
"id": task_id,
"json": "1"
})
result = resp.json()
if result["status"] == 1:
return result["request"]
if result["request"] != "CAPCHA_NOT_READY":
raise Exception(f"Poll error: {result['request']}")
raise TimeoutError(f"Task {task_id} timed out")
def solve_all(captchas):
# Submit all in parallel
task_ids = {}
with ThreadPoolExecutor(max_workers=len(captchas)) as pool:
futures = {
pool.submit(submit_captcha, c["sitekey"]): c["index"]
for c in captchas
}
for future in as_completed(futures):
idx = futures[future]
task_ids[idx] = future.result()
print(f"[captcha-{idx}] Submitted → task {task_ids[idx]}")
# Poll all in parallel
tokens = {}
with ThreadPoolExecutor(max_workers=len(task_ids)) as pool:
futures = {
pool.submit(poll_result, tid): idx
for idx, tid in task_ids.items()
}
for future in as_completed(futures):
idx = futures[future]
tokens[idx] = future.result()
print(f"[captcha-{idx}] Solved")
return tokens
# Example usage
captchas = [
{"index": 0, "sitekey": "6LcXyzABCDEF-login"},
{"index": 1, "sitekey": "6LcAbcDEFGHI-signup"}
]
tokens = solve_all(captchas)
Erwartete Ausgabe:
[captcha-0] Submitted → task 71823456
[captcha-1] Submitted → task 71823457
[captcha-1] Solved
[captcha-0] Solved
Jedes Token dem richtigen Widget zuordnen
Jedes reCAPTCHA-Widget besitzt eine eigene g-recaptcha-response-Textarea. Sind mehrere Widgets vorhanden, liegt jede Textarea verschachtelt in ihrem eigenen Widget-Container. Ordnen Sie das Token daher immer über den Widget-Index oder – noch sicherer – über den Sitekey zu, damit es zuverlässig im passenden Formularfeld landet. Pro Widget sind zwei Schritte nötig:
- die richtige
textareaim zugehörigen Container finden und ihrenvalueauf das Token setzen, - den
data-callbackmit dem Token aufrufen, sofern er definiert ist.
Python (Selenium)
def inject_tokens(driver, captchas, tokens):
for c in captchas:
idx = c["index"]
token = tokens[idx]
# Find the textarea within the widget's container
container = driver.find_elements(By.CSS_SELECTOR, ".g-recaptcha")[idx]
textarea = container.find_element(
By.CSS_SELECTOR, 'textarea[name="g-recaptcha-response"]'
)
driver.execute_script(
"arguments[0].value = arguments[1];", textarea, token
)
# Trigger the callback if defined
callback = c.get("callback")
if callback:
driver.execute_script(f"{callback}('{token}');")
print(f"[captcha-{idx}] Token injected")
inject_tokens(driver, captchas, tokens)
Das Einfügen in die Textarea allein reicht oft nicht: Viele Formulare geben den Submit-Button erst frei, wenn der zugehörige data-callback mit dem Token aufgerufen wurde. Lösen Sie den Callback deshalb explizit aus, sobald er definiert ist.
JavaScript (Puppeteer)
async function injectTokens(page, captchas, tokens) {
for (const captcha of captchas) {
const token = tokens[captcha.index];
await page.evaluate((idx, tkn, callbackName) => {
const widgets = document.querySelectorAll('.g-recaptcha');
const textarea = widgets[idx].querySelector(
'textarea[name="g-recaptcha-response"]'
);
textarea.value = tkn;
if (callbackName && typeof window[callbackName] === 'function') {
window[callbackName](tkn);
}
}, captcha.index, token, captcha.callbackName);
console.log(`[captcha-${captcha.index}] Token injected`);
}
}
await injectTokens(page, captchas, tokens);
Gemischte CAPTCHA-Typen auf einer Seite
Kombiniert eine Seite unterschiedliche Typen – etwa reCAPTCHA v2 im Login und Cloudflare Turnstile in einem darunterliegenden Formular –, erkennen Sie jeden Typ über seinen eigenen Selektor und markieren ihn mit einem Label:
def detect_all_captchas(driver):
detected = []
# reCAPTCHA
recaptchas = driver.find_elements(By.CSS_SELECTOR, ".g-recaptcha")
for i, el in enumerate(recaptchas):
detected.append({
"type": "userrecaptcha",
"sitekey": el.get_attribute("data-sitekey"),
"label": f"recaptcha-{i}"
})
# Turnstile
turnstiles = driver.find_elements(By.CSS_SELECTOR, ".cf-turnstile")
for i, el in enumerate(turnstiles):
detected.append({
"type": "turnstile",
"sitekey": el.get_attribute("data-sitekey"),
"label": f"turnstile-{i}"
})
return detected
Übermitteln Sie jeden Eintrag mit dem passenden method-Parameter. Merken Sie sich pro Typ die richtige Kombination aus Methode und Zielfeld – hier trennen sich die beiden am deutlichsten:
| CAPTCHA-Typ | method-Parameter |
Zielfeld für das Token |
|---|---|---|
| reCAPTCHA v2/v3 | userrecaptcha |
g-recaptcha-response |
| Cloudflare Turnstile | turnstile |
cf-turnstile-response |
Beide Typen unterstützt CaptchaAI direkt. Weil das Turnstile-Token eben nicht in g-recaptcha-response gehört, lohnt sich die getrennte Behandlung pro Typ – ein vertauschtes Zielfeld ist auf gemischten Seiten die zweithäufigste Fehlerquelle nach der Index-Verwechslung.
FAQ
Wie viele Threads brauche ich, um mehrere CAPTCHAs parallel zu lösen?
So viele, wie Sie gleichzeitig lösen wollen: Jede parallele Abfrage belegt einen Thread. Für zwei bis fünf Widgets pro Seite genügt der BASIC-Tarif (15 $/Monat, 5 Threads); für höhere Nebenläufigkeit skalieren Sie über STANDARD (30 $/Monat, 15 Threads) aufwärts. Abgerechnet wird pro Thread mit unbegrenzten Lösungen.
Was passiert, wenn ich ein Token in das falsche Widget einfüge?
Die Validierung schlägt fehl und das Formular bleibt gesperrt, obwohl das Token gültig ist. Ordnen Sie Tokens deshalb über den Sitekey zu, nicht über die reine Reihenfolge im DOM – bei mehreren Widgets ist die Positionsannahme die häufigste Fehlerquelle.
Funktioniert der Ansatz auch mit unsichtbarem reCAPTCHA v2 und reCAPTCHA v3?
Ja. Unsichtbares reCAPTCHA v2 und reCAPTCHA v3 laufen über denselben userrecaptcha-Ablauf; bei v3 übergeben Sie zusätzlich Action und Mindest-Score. Erkennung, paralleles Lösen und Token-Zuordnung bleiben identisch.
Wie gehe ich mit einem CAPTCHA um, das erst nach dem ersten Formular erscheint?
Scannen Sie die Seite nach jeder Übermittlung erneut. Neu gerenderte Widgets erkennt Ihr Detektor erst nach dem Nachladen – mit WebDriverWait (Selenium) oder page.waitForSelector (Puppeteer) warten Sie gezielt auf das neue Element, bevor Sie den Sitekey auslesen.
Kann ich hCaptcha auf derselben Seite mitlösen?
Nein. hCaptcha wird von CaptchaAI derzeit nicht unterstützt. Auf gemischten Seiten lösen Sie die unterstützten Typen – reCAPTCHA v2/v3, Cloudflare Turnstile, Bild- und Grid-CAPTCHAs – und behandeln nicht unterstützte Widgets über einen separaten Weg.
Typische Fehler und schnelle Lösungen
Tipp: Bleibt ein Formular trotz gültigem Token gesperrt, prüfen Sie zuerst den Callback. In der Praxis ist ein nicht ausgelöster
data-callbackdie häufigste Ursache – nicht ein fehlerhaftes Token.
| Problem | Ursache | Lösung |
|---|---|---|
| Token eingefügt, Formular bleibt blockiert | Callback nicht ausgelöst | data-callback prüfen und mit dem Token aufrufen |
| Nur das erste CAPTCHA wird erkannt | Das zweite Widget lädt verzögert nach | Vor dem Scannen warten, bis alle iframes/Widgets sichtbar sind |
| Falsches Token im falschen Widget | Index-Verwechslung | Tokens den Sitekeys zuordnen, nicht dem Positionsindex |
ERROR_WRONG_GOOGLEKEY |
Sitekey falsch ausgelesen | Sitekey über das Iframe-Attribut src oder data-sitekey gegenprüfen |
Verwandte Leitfäden
- CAPTCHAs in verschachtelten iframes extrahieren
- reCAPTCHA-Parameter aus dem Seitenquelltext auslesen
- Parallel oder sequenziell lösen: Performance im Vergleich
Beliebig viele CAPTCHAs pro Seite mit CaptchaAI lösen
Holen Sie sich Ihren API-Schlüssel unter captchaai.com und übertragen Sie den gezeigten Ablauf direkt auf Ihre eigenen Formulare.