O reCAPTCHA invisível remove a caixa de seleção, mas adiciona novos modos de falha para automação. Os maiores problemas são não detectar o widget invisível, perder a função de retorno de chamada, enviar tokens expirados e usar parâmetros padrão v2 quando parâmetros invisíveis são necessários.
Este guia cobre todos os padrões de erros comuns com a correção exata. Se você precisar de informações sobre como funciona o reCAPTCHA invisível, leiaComo funciona o reCAPTCHA Invisible e como resolvê-loprimeiro.
Referência rápida de erros
| Erro | Causa | Correção |
|---|---|---|
ERROR_WRONG_GOOGLEKEY |
Sitekey incorreto ou sitekey de um domínio diferente | Extraia a chave do site da div do widget invisível ou da chamada grecaptcha.render() |
ERROR_PAGEURL |
Incompatibilidade de URL – URL da página pai enviado em vez do URL do iframe | Use o URL exato onde o widget invisível é carregado |
ERROR_CAPTCHA_UNSOLVABLE |
O Google sinalizou a tarefa como impossível | Tente novamente com proxy e cookies novos; verifique se o site mudou para v3 |
ERROR_BAD_TOKEN_OR_PAGEURL |
Token rejeitado pelo site de destino | Verifique se o pageurl corresponde exatamente; injetar via retorno de chamada, não campo oculto |
CAPCHA_NOT_READY |
Tarefa ainda em processamento | Continue pesquisando a cada 5 segundos; soluções invisíveis levam de 10 a 30 segundos |
ERROR_KEY_DOES_NOT_EXIST |
Chave de API CaptchaAI inválida | Verifique a chave emcaptchaai.com/account |
| Token aceito, mas formulário falha | Retorno de chamada não executado após envio controlado ao endpoint QA | Encontre e chame a função data-callback com o token |
Erro 1: não detectando reCAPTCHA invisível na página
O reCAPTCHA invisível não tem nenhuma caixa de seleção visível. Se o seu raspador não detectá-lo, as solicitações protegidas por captcha falharão silenciosamente com erros ou redirecionamentos de envio de formulário.
Como detectar reCAPTCHA invisível
Procure estes padrões na página HTML:
<!-- Pattern 1: div with data-size="invisible" -->
<div class="g-recaptcha" data-sitekey="6LdKlZEU..."
data-size="invisible"
data-callback="onSubmit"></div>
<!-- Pattern 2: button with data-sitekey and invisible size -->
<button class="g-recaptcha"
data-sitekey="6LdKlZEU..."
data-callback="onSubmit"
data-action="submit">Submit</button>
<!-- Pattern 3: programmatic render with size: invisible -->
<script>
grecaptcha.render('submit-btn', {
sitekey: '6LdKlZEU...',
callback: onSubmit,
size: 'invisible'
});
</script>
Script de detecção (Python):
import requests
from bs4 import BeautifulSoup
import re
def detect_invisible_recaptcha(url):
resp = requests.get(url)
soup = BeautifulSoup(resp.text, "html.parser")
# Check for data-size="invisible"
widget = soup.find("div", {"data-size": "invisible", "class": "g-recaptcha"})
if widget:
return {
"type": "invisible",
"sitekey": widget.get("data-sitekey"),
"callback": widget.get("data-callback")
}
# Check for programmatic render with invisible
scripts = soup.find_all("script")
for script in scripts:
if script.string and "size" in str(script.string) and "invisible" in str(script.string):
key_match = re.search(r"sitekey['\"]?\s*[:=]\s*['\"]([^'\"]+)", script.string)
if key_match:
return {
"type": "invisible-programmatic",
"sitekey": key_match.group(1),
"callback": "check grecaptcha.render() call"
}
return None
Script de detecção (Node.js):
const axios = require("axios");
const cheerio = require("cheerio");
async function detectInvisibleRecaptcha(url) {
const { data } = await axios.get(url);
const $ = cheerio.load(data);
// Check for data-size="invisible"
const widget = $(".g-recaptcha[data-size='invisible']");
if (widget.length) {
return {
type: "invisible",
sitekey: widget.attr("data-sitekey"),
callback: widget.attr("data-callback"),
};
}
// Check script tags for programmatic invisible render
const scriptContent = $("script")
.map((_, el) => $(el).html())
.get()
.join("\n");
if (scriptContent.includes("invisible")) {
const keyMatch = scriptContent.match(/sitekey['"]?\s*[:=]\s*['"]([^'"]+)/);
if (keyMatch) {
return {
type: "invisible-programmatic",
sitekey: keyMatch[1],
callback: "check grecaptcha.render() call",
};
}
}
return null;
}
Erro 2: chave de site errada – ERROR_WRONG_GOOGLEKEY
Isso acontece quando você envia uma chave de site que não corresponde ao widget reCAPTCHA invisível na página de destino. Causas comuns:
- Copiou a chave do site de uma caixa de seleção v2 em uma página diferente
- Usou uma chave de site do URL âncora de uma versão diferente do reCAPTCHA
- A página tem vários widgets reCAPTCHA e você pegou o errado
Correção: extraia a chave do site invisível correta
import requests
from bs4 import BeautifulSoup
def get_invisible_sitekey(url):
resp = requests.get(url)
soup = BeautifulSoup(resp.text, "html.parser")
# Priority 1: invisible widget
widget = soup.find(attrs={"data-size": "invisible", "class": "g-recaptcha"})
if widget:
return widget["data-sitekey"]
# Priority 2: any g-recaptcha div (may be invisible without data-size)
widget = soup.find(class_="g-recaptcha")
if widget and widget.get("data-sitekey"):
return widget["data-sitekey"]
return None
sitekey = get_invisible_sitekey("https://staging.example.com/qa-login")
print(f"Sitekey: {sitekey}")
Erro 3: Retorno de chamada não executado – o formulário é enviado, mas nada acontece
Esta é a falha invisível número um do reCAPTCHA que os desenvolvedores não percebem. Ao contrário da caixa de seleção v2, onde injetar o token em g-recaptcha-response é suficiente, o reCAPTCHA invisível quase sempre usa uma função de retorno de chamada JavaScript. Se você injetar o token, mas não chamar o retorno de chamada, o formulário nunca será processado.
Como funciona o fluxo de retorno de chamada
grecaptcha.execute()dispara o desafio invisível- Após resolver, o Google chama a função especificada em
data-callback - Essa função de retorno de chamada envia o formulário ou faz a chamada da API
Correção: encontre e execute o retorno de chamada
Etapa 1 — Identifique o nome do retorno de chamada:
# From HTML: data-callback="onSubmit"
# From JS: callback: onSubmit
# From grecaptcha.render: second argument with callback property
Etapa 2 — Injetar token E chamar o retorno de chamada (Selenium):
from selenium import webdriver
import requests
import time
driver = webdriver.Chrome()
driver.get("https://example.com/form")
# Get sitekey
sitekey = driver.find_element("css selector", ".g-recaptcha").get_attribute("data-sitekey")
callback_name = driver.find_element("css selector", ".g-recaptcha").get_attribute("data-callback")
# Solve with CaptchaAI
task_id = requests.get("https://ocr.captchaai.com/in.php", params={
"key": "YOUR_API_KEY",
"method": "userrecaptcha",
"googlekey": sitekey,
"pageurl": driver.current_url,
"invisible": 1
}).text.split("|")[1]
# Poll for result
token = None
for _ in range(60):
time.sleep(5)
resp = requests.get("https://ocr.captchaai.com/res.php", params={
"key": "YOUR_API_KEY",
"action": "get",
"id": task_id
}).text
if resp.startswith("OK|"):
token = resp.split("|")[1]
break
# Inject token into the response field
driver.execute_script(
f'document.getElementById("g-recaptcha-response").value = "{token}";'
)
# CRITICAL: Call the callback function
driver.execute_script(f'{callback_name}("{token}");')
Etapa 2 — Injetar token E chamar o retorno de chamada (Puppeteer):
const puppeteer = require("puppeteer");
const axios = require("axios");
(async () => {
const browser = await puppeteer.launch({ headless: "new" });
const page = await browser.newPage();
await page.goto("https://example.com/form");
// Get sitekey and callback
const { sitekey, callback } = await page.evaluate(() => {
const el = document.querySelector(".g-recaptcha[data-size='invisible']");
return {
sitekey: el?.getAttribute("data-sitekey"),
callback: el?.getAttribute("data-callback"),
};
});
// Submit to CaptchaAI
const submitResp = await axios.get("https://ocr.captchaai.com/in.php", {
params: {
key: "YOUR_API_KEY",
method: "userrecaptcha",
googlekey: sitekey,
pageurl: page.url(),
invisible: 1,
},
});
const taskId = submitResp.data.split("|")[1];
// Poll for result
let token;
for (let i = 0; i < 60; i++) {
await new Promise((r) => setTimeout(r, 5000));
const result = await axios.get("https://ocr.captchaai.com/res.php", {
params: { key: "YOUR_API_KEY", action: "get", id: taskId },
});
if (result.data.startsWith("OK|")) {
token = result.data.split("|")[1];
break;
}
}
// Inject token and fire callback
await page.evaluate(
(tok, cb) => {
document.getElementById("g-recaptcha-response").value = tok;
if (cb && typeof window[cb] === "function") {
window[cb](tok);
}
},
token,
callback,
);
await browser.close();
})();
Erro 4: Parâmetro invisible=1 ausente
Ao resolver o reCAPTCHA invisível por meio de CaptchaAI, você deve incluir invisible=1 em sua solicitação. Sem ele, o solucionador trata a tarefa como um desafio de caixa de seleção v2 padrão, que pode levar a ERROR_CAPTCHA_UNSOLVABLE ou tokens que o site de destino rejeita.
Solicitação errada versus correta
# WRONG — missing invisible=1
params = {
"key": "YOUR_API_KEY",
"method": "userrecaptcha",
"googlekey": sitekey,
"pageurl": page_url
}
# CORRECT — includes invisible=1
params = {
"key": "YOUR_API_KEY",
"method": "userrecaptcha",
"googlekey": sitekey,
"pageurl": page_url,
"invisible": 1 # Required for invisible reCAPTCHA
}
response = requests.get("https://ocr.captchaai.com/in.php", params=params)
Erro 5: o token expirou antes do envio
Os tokens reCAPTCHA invisíveis expiram em 120 segundos — o mesmo que o padrão v2. Mas os fluxos de trabalho invisíveis geralmente têm etapas de processamento adicionais entre a resolução e o envio, tornando a expiração mais provável.
Sintomas
- Formulário retorna erro genérico após envio controlado ao endpoint QA
siteverifydo lado do servidor retornatimeout-or-duplicate- O token era válido, mas demorou muito para chegar à etapa de envio
Correção: solução just-in-time
Solicite a resolução apenas quando estiver pronto para enviar imediatamente:
import requests
import time
def solve_invisible_recaptcha(api_key, sitekey, page_url):
# Submit task
resp = requests.get("https://ocr.captchaai.com/in.php", params={
"key": api_key,
"method": "userrecaptcha",
"googlekey": sitekey,
"pageurl": page_url,
"invisible": 1
})
if not resp.text.startswith("OK|"):
raise Exception(f"Submit failed: {resp.text}")
task_id = resp.text.split("|")[1]
# Poll for result
for _ in range(60):
time.sleep(5)
result = requests.get("https://ocr.captchaai.com/res.php", params={
"key": api_key,
"action": "get",
"id": task_id
})
if result.text.startswith("OK|"):
return result.text.split("|")[1]
if result.text != "CAPCHA_NOT_READY":
raise Exception(f"Solve failed: {result.text}")
raise Exception("Solve timed out after 5 minutes")
# Usage: solve JUST before you need to submit
# 1. Navigate to page and prepare form data first
# 2. THEN solve the captcha
# 3. Inject token and submit immediately
token = solve_invisible_recaptcha("YOUR_API_KEY", sitekey, page_url)
# Submit within 120 seconds of receiving the token
Erro 6: Token rejeitado — ERROR_BAD_TOKEN_OR_PAGEURL
O site de destino verificou o token com o Google e falhou. Causas comuns:
| Causa | Como identificar | Correção |
|---|---|---|
pageurl errado |
URL não corresponde ao domínio no registro do sitekey | Use o URL exato onde o widget é carregado |
| Token usado em domínio diferente | Reutilização de token entre domínios | Resolva com o pageurl do domínio correto |
| Token já usado | Enviando o mesmo token duas vezes | Solicite uma nova solução para cada envio |
| Incompatibilidade de IP | Seu IP difere do IP do solucionador | Adicione seu parâmetro proxy para corresponder ao IP da sessão |
| Bandeira invisível faltando | Resolvido como padrão v2, usado em página invisível | Adicione invisible=1 à solicitação de resolução |
Lista de verificação de depuração
def debug_invisible_solve(api_key, sitekey, page_url, proxy=None):
"""Run a diagnostic solve with detailed logging."""
print(f"Sitekey: {sitekey}")
print(f"Page URL: {page_url}")
print(f"Proxy: {proxy or 'none'}")
params = {
"key": api_key,
"method": "userrecaptcha",
"googlekey": sitekey,
"pageurl": page_url,
"invisible": 1
}
if proxy:
params["proxy"] = proxy
params["proxytype"] = "HTTP"
# Submit
resp = requests.get("https://ocr.captchaai.com/in.php", params=params)
print(f"Submit response: {resp.text}")
if not resp.text.startswith("OK|"):
return None
task_id = resp.text.split("|")[1]
print(f"Task ID: {task_id}")
# Poll with timing
start = time.time()
for _ in range(60):
time.sleep(5)
result = requests.get("https://ocr.captchaai.com/res.php", params={
"key": api_key, "action": "get", "id": task_id
})
elapsed = time.time() - start
print(f" [{elapsed:.0f}s] {result.text[:50]}")
if result.text.startswith("OK|"):
token = result.text.split("|")[1]
print(f"Token received after {elapsed:.0f}s")
print(f"Token length: {len(token)} characters")
print(f"Token starts with: {token[:30]}...")
return token
if result.text != "CAPCHA_NOT_READY":
print(f"FAILED: {result.text}")
return None
print("TIMEOUT after 5 minutes")
return None
Erro 7: vários widgets reCAPTCHA em uma página
Algumas páginas têm uma caixa de seleção v2 visível E um reCAPTCHA invisível. Se você resolver o problema errado, o token será válido, mas não corresponderá ao widget que protege a ação necessária.
Correção: direcione o widget correto
from bs4 import BeautifulSoup
def find_all_recaptcha_widgets(html):
soup = BeautifulSoup(html, "html.parser")
widgets = []
for el in soup.find_all(class_="g-recaptcha"):
widgets.append({
"sitekey": el.get("data-sitekey"),
"size": el.get("data-size", "normal"),
"callback": el.get("data-callback"),
"tag": el.name,
"id": el.get("id")
})
return widgets
# Example output:
# [
# {"sitekey": "6LdA...", "size": "normal", "callback": None, "tag": "div", "id": "recaptcha-login"},
# {"sitekey": "6LdB...", "size": "invisible", "callback": "onRegister", "tag": "div", "id": "recaptcha-register"}
# ]
# Use the widget with size="invisible" for the invisible solve
Solucionador reCAPTCHA invisível completo com tratamento de erros
Este wrapper pronto para produção lida com todos os erros acima:
import requests
import time
import logging
logger = logging.getLogger(__name__)
class InvisibleRecaptchaSolver:
def __init__(self, api_key, max_retries=3):
self.api_key = api_key
self.max_retries = max_retries
self.base_url = "https://ocr.captchaai.com"
def solve(self, sitekey, page_url, proxy=None):
"""Solve invisible reCAPTCHA with automatic retry on transient errors."""
for attempt in range(1, self.max_retries + 1):
try:
token = self._attempt_solve(sitekey, page_url, proxy)
if token:
return token
except Exception as e:
logger.warning(f"Attempt {attempt} failed: {e}")
if attempt < self.max_retries:
time.sleep(2 ** attempt)
raise Exception(f"Failed to solve after {self.max_retries} attempts")
def _attempt_solve(self, sitekey, page_url, proxy):
params = {
"key": self.api_key,
"method": "userrecaptcha",
"googlekey": sitekey,
"pageurl": page_url,
"invisible": 1
}
if proxy:
params["proxy"] = proxy
params["proxytype"] = "HTTP"
# Submit task
resp = requests.get(f"{self.base_url}/in.php", params=params)
if "ERROR" in resp.text:
error = resp.text.strip()
if error in ("ERROR_WRONG_GOOGLEKEY", "ERROR_KEY_DOES_NOT_EXIST"):
raise Exception(f"Configuration error (do not retry): {error}")
if error == "ERROR_ZERO_BALANCE":
raise Exception("Account balance is zero — add funds")
raise Exception(f"Submit error: {error}")
if not resp.text.startswith("OK|"):
raise Exception(f"Unexpected submit response: {resp.text}")
task_id = resp.text.split("|")[1]
# Poll for result
for _ in range(60):
time.sleep(5)
result = requests.get(f"{self.base_url}/res.php", params={
"key": self.api_key,
"action": "get",
"id": task_id
})
if result.text.startswith("OK|"):
return result.text.split("|")[1]
if result.text == "CAPCHA_NOT_READY":
continue
if result.text == "ERROR_CAPTCHA_UNSOLVABLE":
logger.warning("Captcha unsolvable — will retry with new task")
return None
raise Exception(f"Poll error: {result.text}")
raise Exception("Solve timed out after 5 minutes")
# Usage
solver = InvisibleRecaptchaSolver("YOUR_API_KEY")
token = solver.solve(
sitekey="6LdKlZEU...",
page_url="https://staging.example.com/qa-login"
)
print(f"Token: {token[:50]}...")
const axios = require("axios");
class InvisibleRecaptchaSolver {
constructor(apiKey, maxRetries = 3) {
this.apiKey = apiKey;
this.maxRetries = maxRetries;
this.baseUrl = "https://ocr.captchaai.com";
}
async solve(sitekey, pageUrl, proxy) {
for (let attempt = 1; attempt <= this.maxRetries; attempt++) {
try {
const token = await this._attemptSolve(sitekey, pageUrl, proxy);
if (token) return token;
} catch (err) {
console.warn(`Attempt ${attempt} failed: ${err.message}`);
if (attempt < this.maxRetries) {
await new Promise((r) => setTimeout(r, 2 ** attempt * 1000));
}
}
}
throw new Error(`Failed to solve after ${this.maxRetries} attempts`);
}
async _attemptSolve(sitekey, pageUrl, proxy) {
const params = {
key: this.apiKey,
method: "userrecaptcha",
googlekey: sitekey,
pageurl: pageUrl,
invisible: 1,
};
if (proxy) {
params.proxy = proxy;
params.proxytype = "HTTP";
}
// Submit task
const submitResp = await axios.get(`${this.baseUrl}/in.php`, { params });
if (submitResp.data.includes("ERROR")) {
const error = submitResp.data.trim();
if (["ERROR_WRONG_GOOGLEKEY", "ERROR_KEY_DOES_NOT_EXIST"].includes(error)) {
throw new Error(`Configuration error (do not retry): ${error}`);
}
throw new Error(`Submit error: ${error}`);
}
const taskId = submitResp.data.split("|")[1];
// Poll for result
for (let i = 0; i < 60; i++) {
await new Promise((r) => setTimeout(r, 5000));
const result = await axios.get(`${this.baseUrl}/res.php`, {
params: { key: this.apiKey, action: "get", id: taskId },
});
if (result.data.startsWith("OK|")) {
return result.data.split("|")[1];
}
if (result.data === "CAPCHA_NOT_READY") continue;
if (result.data === "ERROR_CAPTCHA_UNSOLVABLE") return null;
throw new Error(`Poll error: ${result.data}`);
}
throw new Error("Solve timed out after 5 minutes");
}
}
// Usage
const solver = new InvisibleRecaptchaSolver("YOUR_API_KEY");
solver.solve("6LdKlZEU...", "https://staging.example.com/qa-login").then((token) => {
console.log(`Token: ${token.substring(0, 50)}...`);
});
Lista de verificação de solução de problemas
Execute esta lista de verificação quando a solução do reCAPTCHA invisível falhar:
| Passo | Verifique | Comando/Action |
|---|---|---|
| 1 | Confirme que é invisível, não o padrão v2 | Procure data-size="invisible" ou size: 'invisible' na chamada de renderização |
| 2 | Verifique se a chave do site está correta | Compare com data-sitekey especificamente no widget invisível |
| 3 | Confirme invisible=1 na solicitação de API |
Verifique seus parâmetros in.php |
| 4 | Verifique se pageurl corresponde exatamente |
Use o URL do DevTools do navegador, não um URL de redirecionamento |
| 5 | Encontre o nome da função de retorno de chamada | Procure o atributo data-callback ou callback em grecaptcha.render() |
| 6 | Verifique a envio controlado ao endpoint QA + chamada de retorno | Ambas as etapas são necessárias – o token por si só não é suficiente |
| 7 | Verifique a atualização do token | O token deve ser usado dentro de 120 segundos |
| 8 | Teste com proxy se o IP for importante | Adicione os parâmetros proxy e proxytype |
Perguntas frequentes
Qual a diferença entre o reCAPTCHA invisível e o padrão v2 para resolução?
O método API é o mesmo (method=userrecaptcha), mas você deve adicionar invisible=1 à sua solicitação. A diferença crítica está no lado da injeção: o reCAPTCHA invisível quase sempre requer a chamada de uma função de retorno de chamada JavaScript após a injeção do token, enquanto o padrão v2 geralmente funciona apenas com o campo oculto.
Por que meu token funciona nos testes, mas falha na produção?
Provavelmente uma incompatibilidade de IP. Nos testes, o solucionador e seu navegador podem compartilhar IPs semelhantes. Na produção, o IP do solucionador e o IP do seu servidor são diferentes. Adicione um parâmetro de proxy que corresponda ao IP da sua sessão para corrigir isso.
Quanto tempo leva para resolver o reCAPTCHA invisível?
Os tempos de resolução típicos são de 10 a 30 segundos até CaptchaAI. Os desafios invisíveis são geralmente com menor latência do que os desafios de caixa de seleção v2 porque não exigem reconhecimento de imagem – eles dependem de análise de risco.
Posso resolver o reCAPTCHA invisível sem um navegador?
Sim. Como a solução acontece no lado do servidor por meio da API, você só precisa do sitekey e do pageurl. O navegador só será necessário se você precisar executar a função de retorno de chamada na página real. Para fluxos de trabalho de API puros, extraia a chave do site, resolva via CaptchaAI e envie o token com sua solicitação HTTP.
Próximas etapas
- Como funciona o reCAPTCHA Invisible e como resolvê-lo- antecedentes do mecanismo invisível
- Como resolver reCAPTCHA v2 usando API— solução padrão v2 para comparação
- reCAPTCHA v2 comum resolvendo erros e correções— padrões de erro padrão v2
- Códigos de erro CaptchaAI: referência completa— tabela completa de códigos de erro
Artigos relacionados
- Resolva Recaptcha Python invisível
- Erros e correções comuns de captcha de imagem de grade
- Recaptcha V2 vs Invisível