Se o formulário não mostra nenhuma caixinha "Não sou um robô" mas ainda assim busca um token antes de liberar o envio, você está diante do reCAPTCHA invisível — a variante que roda inteiramente em segundo plano e só libera a página depois que o token é validado. Pela API da CaptchaAI, o fluxo de resolução é quase idêntico ao do reCAPTCHA v2 padrão; a única mudança obrigatória é acrescentar invisible=1 na chamada de envio.
A parte que realmente muda de comportamento é como o token chega até o site. A maioria das implementações invisíveis não usa o campo oculto g-recaptcha-response — elas disparam uma função de callback em JavaScript assim que o token está pronto. Se você só preencher o campo oculto sem chamar essa função, a página trava exatamente no mesmo lugar de antes. Este guia mostra como detectar o reCAPTCHA invisível, resolver o token pela API e injetá-lo no callback certo, com código em Python e Node.js.
Não tem certeza se o desafio é invisível ou o reCAPTCHA v2 padrão? Leia reCAPTCHA v2 vs Invisível: como diferenciar para os sinais de detecção completos.
O que você precisa para resolver o reCAPTCHA invisível
Separe estes quatro itens antes de abrir o editor — nenhum dos exemplos abaixo funciona sem eles:
- Chave de API CaptchaAI — gerada em captchaai.com/api.php
- Sitekey — extraída do atributo
data-sitekeyno widget ou no botão - URL da página — endereço completo onde o CAPTCHA invisível é executado
- Ferramenta de navegador — Selenium ou Puppeteer, para executar o callback depois do token pronto
Passo a passo: do envio à injeção do token
O envio, a consulta e a injeção seguem sempre esta ordem — o que muda de um site para outro é como o token entra na página, e é isso que a Etapa 4 resolve.
Etapa 1: detectar reCAPTCHA invisível
Antes de enviar qualquer chamada à API, confirme que o desafio é mesmo invisível — o parâmetro extra só faz sentido nesse caso. Procure por um destes três padrões no código-fonte da página:
<!-- Option 1: div with data-size="invisible" -->
<div class="g-recaptcha" data-sitekey="6LdKlZEU..." data-size="invisible" data-callback="onSubmit"></div>
<!-- Option 2: button with data-sitekey (invisible by default) -->
<button data-sitekey="6LdKlZEU..." data-callback="onSubmit">Submit</button>
<!-- Option 3: programmatic execution -->
<script>
grecaptcha.execute('6LdKlZEU...', {action: 'submit'});
</script>
Se você vir data-size="invisible", um botão com data-sitekey sem nenhuma caixa de seleção ao lado, ou uma chamada solta a grecaptcha.execute() sem contêiner, é reCAPTCHA invisível — siga para o envio.
Etapa 2: enviar para CaptchaAI
O envio usa o mesmo method=userrecaptcha do reCAPTCHA v2 padrão. A única diferença é o parâmetro invisible, que avisa a CaptchaAI para tratar o desafio como invisível em vez de v2 clássico:
import requests
response = requests.get("https://ocr.captchaai.com/in.php", params={
"key": "YOUR_API_KEY",
"method": "userrecaptcha",
"googlekey": "6LdKlZEUAAAAAPoxm...",
"pageurl": "https://example.com/signup",
"invisible": 1,
"json": 1
})
task_id = response.json()["request"]
const params = new URLSearchParams({
key: "YOUR_API_KEY", method: "userrecaptcha",
googlekey: "6LdKlZEUAAAAAPoxm...",
pageurl: "https://example.com/signup",
invisible: 1, json: 1,
});
const res = await fetch(`https://ocr.captchaai.com/in.php?${params}`);
const { request: taskId } = await res.json();
Testando reCAPTCHA Invisible Enterprise? O envio muda pouco: mantenha invisible=1 e acrescente enterprise=1 na mesma chamada. O restante do fluxo — consulta e injeção do token — continua idêntico.
Etapa 3: consulte o resultado (polling)
A consulta a res.php segue o mesmo padrão de qualquer resolução de reCAPTCHA: pergunte a cada alguns segundos até status virar 1 ou a API devolver um erro diferente de CAPCHA_NOT_READY.
import time
for _ in range(40):
time.sleep(5)
result = requests.get("https://ocr.captchaai.com/res.php", params={
"key": "YOUR_API_KEY", "action": "get", "id": task_id, "json": 1
}).json()
if result.get("status") == 1:
token = result["request"]
break
if result.get("request") != "CAPCHA_NOT_READY":
raise RuntimeError(f"Error: {result['request']}")
Etapa 4: injetar o token via callback
Este é o passo que realmente separa o reCAPTCHA invisível do fluxo padrão. Em vez de só preencher um campo oculto, você precisa chamar a função de callback que o site espera — geralmente o mesmo nome declarado em data-callback ou passado para grecaptcha.render():
# Selenium example
from selenium import webdriver
driver = webdriver.Chrome()
driver.get("https://example.com/signup")
# Find the callback name
callback = driver.execute_script("""
var el = document.querySelector('[data-callback]');
if (el) return el.getAttribute('data-callback');
var btn = document.querySelector('[data-sitekey]');
if (btn) return btn.getAttribute('data-callback');
return null;
""")
# Execute the callback with the token
if callback:
driver.execute_script(f"window['{callback}']('{token}');")
else:
# Fallback: fill hidden field and submit
driver.execute_script(f"""
document.getElementById('g-recaptcha-response').innerHTML = '{token}';
document.querySelector('form').submit();
""")
// Puppeteer example
await page.evaluate((token) => {
const el = document.querySelector('[data-callback]') || document.querySelector('[data-sitekey]');
const callbackName = el?.getAttribute('data-callback');
if (callbackName && window[callbackName]) {
window[callbackName](token);
} else {
document.getElementById('g-recaptcha-response').innerHTML = token;
document.querySelector('form').submit();
}
}, token);
Se a página não expõe nenhum data-callback visível, o fallback do código acima entra em ação: preenche g-recaptcha-response manualmente e envia o formulário. Funciona em parte das implementações, mas não em todas. Quando falhar, abra o console do navegador e procure no JavaScript da página por funções que recebem o token do reCAPTCHA como argumento — é comum que estejam registradas dentro de ___grecaptcha_cfg ou amarradas a um evento de clique customizado no botão de envio.
Exemplo prático: QA de cadastro com reCAPTCHA invisível
Um cenário comum é testar em CI o botão "Criar conta" de um SaaS brasileiro que carrega reCAPTCHA invisível sem checkbox visível. Cada execução do pipeline mantém uma thread ocupada na CaptchaAI enquanto aguarda o token — a cobrança é por thread simultânea, não por solve:
- BASIC (US$ 15/mês, 5 threads) cobre a maioria das suítes de QA rodando em série.
- STANDARD (US$ 30/mês, 15 threads) absorve testes de regressão em paralelo sem mudar uma linha de código, porque a chamada para
in.phperes.phpé idêntica nos dois planos — só a concorrência muda. - Latência e dados de teste — se os workers rodam em nuvem, hospedá-los numa região próxima do público testado (por exemplo
sa-east-1, São Paulo, para sites com tráfego brasileiro) reduz o RTT entre abrir a página e consultarres.php. Como o payload passa por formulários de cadastro reais, trate os dados usados no teste como dado pessoal sob a LGPD: usestaging.example.comcom contas fictícias e nunca grave dados reais de usuários em log de depuração.
Função de trabalho completa
Reunindo as etapas 2 e 3 numa única função reutilizável:
import requests
import time
def solve_invisible_recaptcha(api_key, sitekey, page_url):
submit = requests.get("https://ocr.captchaai.com/in.php", params={
"key": api_key, "method": "userrecaptcha", "googlekey": sitekey,
"pageurl": page_url, "invisible": 1, "json": 1
}).json()
if submit.get("status") != 1:
raise RuntimeError(f"Submit error: {submit.get('request')}")
task_id = submit["request"]
for _ in range(40):
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.get("status") == 1:
return result["request"]
if result.get("request") != "CAPCHA_NOT_READY":
raise RuntimeError(f"Solve error: {result.get('request')}")
raise TimeoutError("Timed out")
token = solve_invisible_recaptcha("YOUR_API_KEY", "6LdKlZEU...", "https://example.com/signup")
Exemplo executável completo
Precisa de um projeto funcional completo, com setup de ambiente, polling, novas tentativas e tratamento de erro já resolvidos? Veja o exemplo executável completo no GitHub →
Perguntas frequentes
Como sei se o reCAPTCHA da página é invisível e não o v2 padrão?
Procure data-size="invisible" na div do widget, um botão com data-sitekey sem nenhuma caixa de seleção ao lado, ou uma chamada solta a grecaptcha.execute(). Qualquer um dos três confirma que é invisível.
Quanto tempo leva para receber o token pela API?
A CaptchaAI resolve o reCAPTCHA invisível em menos de 30 segundos, com alta taxa de sucesso nos tipos suportados.
O loop do exemplo cobre até 200 segundos (40 tentativas de 5 s) de margem, mas raramente chega perto disso.
O que acontece se eu esquecer o parâmetro invisible=1?
A CaptchaAI trata o envio como reCAPTCHA v2 padrão, e o site pode rejeitar o token porque a validação client-side espera o formato do desafio invisível.
Sempre inclua invisible: 1 na chamada de envio.
Selenium, Puppeteer e Playwright resolvem o callback do mesmo jeito?
A chamada para a API da CaptchaAI é idêntica nos três. Só muda a sintaxe para executar JavaScript na página — execute_script no Selenium, page.evaluate() no Puppeteer e no Playwright. A lógica de detectar o nome do callback e chamá-lo com o token é a mesma.
O reCAPTCHA invisível consome mais threads da CaptchaAI do que o v2 padrão?
Não. A cobrança é por thread simultânea ocupada enquanto a tarefa está em andamento, não por tipo de CAPTCHA — um reCAPTCHA invisível e um v2 padrão consomem o mesmo espaço de thread durante a resolução.
Comece a resolver o reCAPTCHA invisível agora
Pegue sua chave de API em captchaai.com/api.php, acrescente invisible=1 ao seu código de resolução do reCAPTCHA v2 e reaproveite o padrão de injeção de callback mostrado acima — a chamada de API muda em uma linha, o resto do pipeline continua igual.
Guias relacionados
- Como o reCAPTCHA Invisible funciona por trás dos panos
- Erros comuns ao resolver reCAPTCHA Invisible
- reCAPTCHA v2 padrão vs Invisível: como diferenciar
- Como resolver o callback do reCAPTCHA v2 com a API