API Tutorials

Como resolver o reCAPTCHA invisível usando API

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-sitekey no 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.php e res.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 consultar res.php. Como o payload passa por formulários de cadastro reais, trate os dados usados no teste como dado pessoal sob a LGPD: use staging.example.com com 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

Os comentários estão desativados para este artigo.