Algumas páginas renderizam dois ou mais CAPTCHAs - um formulário de login com reCAPTCHA e uma inscrição em boletim informativo com um segundo reCAPTCHA, ou um formulário de várias etapas onde cada etapa desencadeia seu próprio desafio. Cada CAPTCHA tem uma chave de site e um elemento de destino exclusivos, então você precisa detectar todos eles, resolvê-los em paralelo e injetar cada token no retorno de chamada correto.
Detectando vários CAPTCHAs
Python com Selênio
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']}")
Resultado esperado:
Found 2 CAPTCHAs on page
[0] sitekey: 6LcXyzABCDEF-login
[1] sitekey: 6LcAbcDEFGHI-signup
JavaScript com Puppeteer
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}`));
})();
Resolvendo todos os CAPTCHAs em paralelo
Envie todos os CAPTCHAs para CaptchaAI de uma vez e depois pesquise até que cada um seja resolvido.
Pitão
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)
Resultado esperado:
[captcha-0] Submitted → task 71823456
[captcha-1] Submitted → task 71823457
[captcha-1] Solved
[captcha-0] Solved
Injetando tokens no widget correto
Cada widget reCAPTCHA possui sua própria área de texto g-recaptcha-response. Quando existem vários widgets, cada textarea é aninhada dentro de seu contêiner de widget.
Python (Selênio)
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)
JavaScript (titereiro)
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);
Tipos mistos de CAPTCHA
Quando uma página tiver diferentes tipos de CAPTCHA (por exemplo, reCAPTCHA + Cloudflare Turnstile), detecte cada tipo separadamente:
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
Envie cada um com seu parâmetro method correspondente - userrecaptcha para reCAPTCHA, turnstile para Turnstile.
Solução de problemas
| Problema | Causa | Correção |
|---|---|---|
| Token injetado, mas formulário ainda bloqueado | Retorno de chamada não acionado | Verifique data-callback e chame-o com o token |
| Apenas o primeiro CAPTCHA detectado | O segundo CAPTCHA carrega lentamente | Aguarde até que todos os iframes/widgets apareçam antes de digitalizar |
| Token errado no widget errado | Incompatibilidade de índice | Mapeie tokens para chaves de site, não para índice posicional |
ERROR_WRONG_GOOGLEKEY |
Sitekey extraído incorretamente | Verifique a chave do site do atributo iframe src ou data-sitekey |
Perguntas frequentes
Uma página pode ter chaves de site diferentes para cada CAPTCHA?
Sim. Cada widget pode usar uma chave de site separada. Sempre extraia a chave do site por widget, em vez de presumir que eles compartilham uma.
Devo resolvê-los sequencialmente ou em paralelo?
Em paralelo. Cada resolução leva de 15 a 30 segundos. Resolver dois CAPTCHAs em paralelo leva o mesmo tempo que resolver um.
E se o segundo CAPTCHA só aparecer após o envio do primeiro formulário?
Verifique novamente a página após cada envio de formulário para detectar CAPTCHAs recém-renderizados. Use WebDriverWait (Selenium) ou page.waitForSelector (Puppeteer) para aguardar o novo widget.
Resolva qualquer número de CAPTCHAs por página com CaptchaAI
Obtenha sua chave API emcaptchaai.com.
Guias relacionados
- Extração de Iframe CAPTCHA: Resolvendo CAPTCHAs em quadros aninhados
- Extraindo parâmetros reCAPTCHA da origem da página
- Resolução paralela de CAPTCHA