Seu script envia o formulário de staging, recebe HTTP 200 e o cadastro não aparece do outro lado. Nenhum erro, nenhum log, nenhuma caixa de seleção na tela. O culpado costuma ser um reCAPTCHA v2 invisível: dispara sozinho no clique do botão e só exibe desafio quando a análise de risco do Google desconfia da sessão.
Sem widget para procurar, o diagnóstico começa pelo DOM. Veja as quatro assinaturas que revelam a variante, como achar o elemento que a dispara e como resolvê-la com a API da CaptchaAI usando invisible=1.
Quatro formas de detectar o reCAPTCHA invisível
Rode as verificações no console, nesta ordem. A primeira que retornar algo fecha o diagnóstico; as demais só valem sem a div.
- Atributo
data-sizeda div.g-recaptcha - Presença do selo
grecaptcha-badge - Chamadas a
grecaptcha.executeno JavaScript inline - Parâmetro
renderna tag de script do reCAPTCHA
1. Leia o atributo data-size
Quando a div existe, o próprio tamanho declara a variante.
// Browser console
const widgets = document.querySelectorAll('.g-recaptcha');
widgets.forEach((el, i) => {
const size = el.getAttribute('data-size');
const sitekey = el.getAttribute('data-sitekey');
console.log(`Widget ${i}: size=${size}, sitekey=${sitekey}`);
if (size === 'invisible') {
console.log(' → This is Invisible reCAPTCHA');
}
});
2. Procure o selo no canto da tela
O selo aparece quando não há widget visível — a alternativa permitida é um aviso em texto no formulário.
const badge = document.querySelector('.grecaptcha-badge');
if (badge) {
console.log('reCAPTCHA badge found — likely Invisible reCAPTCHA');
console.log('Badge visibility:', getComputedStyle(badge).visibility);
}
3. Cace chamadas a grecaptcha.execute
Sem div alguma, a integração é programática e a pista está no JavaScript inline.
// Look for grecaptcha.execute in page scripts
document.querySelectorAll('script:not([src])').forEach(s => {
if (s.textContent.includes('grecaptcha.execute')) {
console.log('Found grecaptcha.execute — Invisible reCAPTCHA');
const match = s.textContent.match(/grecaptcha\.execute\s*\(\s*['"]?([^'",\s)]+)/);
if (match) console.log('Sitekey:', match[1]);
}
});
4. Inspecione o parâmetro render da tag de script
Se a URL do script traz render= com uma sitekey em vez de render=explicit, a ativação é automática.
document.querySelectorAll('script[src*="recaptcha"]').forEach(s => {
if (s.src.includes('render=') && !s.src.includes('render=explicit')) {
console.log('Invisible/v3 reCAPTCHA detected in script:', s.src);
}
});
- Guarde a sitekey: é o único parâmetro que muda entre páginas.
- Transforme as checagens em teste de QA: você descobre no deploy quando o frontend troca a configuração.
O que muda em relação ao v2 padrão
A diferença não está no algoritmo, e sim em quem inicia o desafio: no v2 padrão o usuário clica; no invisível, o site chama grecaptcha.execute() no envio.
| Característica | reCAPTCHA v2 padrão | reCAPTCHA v2 invisível |
|---|---|---|
| Widget visível | Sim (caixa de seleção) | Não (apenas o selo no canto) |
| Interação do usuário | Clique na caixa | Automático no envio do formulário |
data-size |
normal ou compact |
invisible |
| Pop-up de desafio | Sempre possível | Só para sessões suspeitas |
| Elemento no DOM | Div .g-recaptcha |
Div .g-recaptcha ou chamada programática |
- Seu bot não acha ponto de entrada: não há elemento com que interagir.
- Em staging com pouco tráfego a análise libera a sessão sem exibir imagem, e o time conclui que "não tem CAPTCHA aqui" — até rodar em volume.
Resolvendo com a API da CaptchaAI
A única diferença é o parâmetro invisible=1 no envio; sem esse sinal, o token tende a ser recusado pelo servidor de verificação.
googlekey: a sitekey (chave pública do widget) extraída no passo anteriorpageurl: a URL exata da página do formulárioinvisible:1, obrigatório nesta variante
import requests
import time
API_KEY = "YOUR_API_KEY"
# Submit with invisible flag
resp = requests.post("https://ocr.captchaai.com/in.php", data={
"key": API_KEY,
"method": "userrecaptcha",
"googlekey": "6Le-SITEKEY",
"pageurl": "https://staging.example.com/qa-login",
"invisible": "1", # critical for Invisible reCAPTCHA
"json": "1",
}).json()
if resp["status"] != 1:
raise Exception(f"Submit error: {resp['request']}")
task_id = resp["request"]
print(f"Submitted: {task_id}")
# Poll for result
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:
print(f"Token: {result['request'][:50]}...")
break
if result["request"] != "CAPCHA_NOT_READY":
raise Exception(f"Error: {result['request']}")
Em Node.js o envio é idêntico — muda o cliente HTTP.
const axios = require('axios');
const resp = await axios.post('https://ocr.captchaai.com/in.php', null, {
params: {
key: 'YOUR_API_KEY',
method: 'userrecaptcha',
googlekey: '6Le-SITEKEY',
pageurl: 'https://staging.example.com/qa-login',
invisible: 1,
json: 1,
}
});
const taskId = resp.data.request;
console.log(`Submitted: ${taskId}`);
- O consumo segue o modelo de threads: paga-se por concorrência, não por resolução.
- O BASIC (US$ 15/mês, 5 threads) atende uma suíte com poucos formulários por deploy; para monitoramento autorizado contínuo, o ADVANCE (US$ 90/mês, 50 threads) encaixa melhor.
- Escopo: reCAPTCHA v2 e v3, Cloudflare Turnstile e Challenge, GeeTest v3 e CAPTCHAs de imagem e grade. hCaptcha e FunCaptcha não são suportados.
Envio controlado ao endpoint de QA
Com o token em mãos, preencha g-recaptcha-response e acione a função declarada em data-callback. Só então envie o formulário.
from selenium import webdriver
from selenium.webdriver.common.by import By
driver = webdriver.Chrome()
driver.get("https://staging.example.com/qa-login")
# After solving, inject and trigger
driver.execute_script("""
// Set the token
document.querySelector('textarea[name="g-recaptcha-response"]').value = arguments[0];
// Find and trigger the callback
var widget = document.querySelector('.g-recaptcha');
var callbackName = widget ? widget.getAttribute('data-callback') : null;
if (callbackName && typeof window[callbackName] === 'function') {
window[callbackName](arguments[0]);
}
""", token)
# Submit the form
driver.find_element(By.CSS_SELECTOR, "form#login").submit()
- Pular o callback reproduz o sintoma da abertura: o formulário parte, o servidor responde sem erro e nada acontece.
- O token tem validade curta: resolva e injete na mesma execução, sem reaproveitar entre rodadas.
Localize o elemento que dispara o desafio
Falta saber quem chama o desafio. O caso simples é o botão que carrega a classe do widget.
<button class="g-recaptcha"
data-sitekey="6Le-SITEKEY"
data-callback="onSubmit"
data-size="invisible">
Submit
</button>
O caso chato é a ativação por código, escondida em um listener de clique.
// Site's code
document.getElementById('submit-btn').addEventListener('click', function() {
grecaptcha.execute();
});
- Verifique os dois padrões antes de descartar a variante invisível.
- Guarde o
data-callback: é a função que você chama depois de receber o token.
// Find elements with g-recaptcha class that are buttons
document.querySelectorAll('button.g-recaptcha, input.g-recaptcha').forEach(el => {
console.log('Trigger element:', el.tagName, el.textContent.trim());
console.log(' data-sitekey:', el.getAttribute('data-sitekey'));
console.log(' data-callback:', el.getAttribute('data-callback'));
});
Se a varredura não retornar nada, volte ao método 3: a chamada está no script inline.
Solução de problemas
Estes quatro sintomas cobrem quase todo chamado sobre a variante.
| Sintoma | Causa provável | Como corrigir |
|---|---|---|
| Token recusado pelo site | Falta invisible=1 no envio |
Inclua invisible: "1" na requisição à CaptchaAI |
| Não encontro a sitekey | A página não tem div .g-recaptcha |
Procure chamadas a grecaptcha.render() ou grecaptcha.execute() no JavaScript inline |
| O formulário envia, mas nada acontece | O callback não foi acionado | Leia data-callback no botão e chame essa função com o token |
| Nenhum CAPTCHA aparece nos testes | Só é exibido para sessões suspeitas | Verifique o elemento grecaptcha-badge ou as tags de script do reCAPTCHA |
Cenário prático: homologação que falha sem erro
Uma equipe em São Paulo roda testes de regressão em staging.example.com a cada deploy. O cadastro passou a falhar em 3 de 10 execuções, sempre sem mensagem de erro.
O console não mostrou div .g-recaptcha, mas o método 3 achou uma chamada a grecaptcha.execute() no script inline: o frontend migrara para o invisível na sprint anterior. Com a sitekey do próprio trecho, bastou incluir invisible=1 e chamar o callback do botão.
- Automatize apenas ambientes que você controla ou tem autorização para testar.
- Use dados fictícios: a LGPD e o RGPD tratam dados pessoais de teste com o mesmo rigor dos de produção.
Perguntas frequentes
Como sei se é v2 invisível ou v3?
Olhe a chamada de execução. O v2 invisível usa grecaptcha.execute() sem action; o v3 usa grecaptcha.execute(sitekey, {action: 'submit'}) e traz render=SITEKEY na URL do script.
Preciso de um navegador para resolver?
Para obter o token, não: a API exige apenas a sitekey e a URL da página. O navegador entra só na etapa final, para injetar o token e disparar o callback.
Quanto tempo leva a resolução?
Depende da fila e do tipo de desafio. Siga o exemplo em Python: aguarde alguns segundos antes da primeira consulta e refaça o polling em intervalos regulares, tratando CAPCHA_NOT_READY como resposta normal, não como erro.
O selo do reCAPTCHA some se eu resolver pela API?
Não. O selo é renderizado pelo site e continua onde estava; muda apenas o valor de g-recaptcha-response que você envia.
Posso resolver vários formulários em paralelo?
Sim, e as threads do plano definem o teto. Cada desafio em andamento ocupa uma thread; ao terminar, ela fica livre. Não há cobrança por resolução.
Comece a resolver o reCAPTCHA invisível hoje
Pegue sua chave de API em captchaai.com e rode o exemplo em Python no seu formulário de staging.