Para resolver um CAPTCHA de imagem de grade automaticamente, você não precisa do fluxo de token do reCAPTCHA: basta enviar a imagem completa da grade (3×3, 4×4 ou um layout fora do padrão) para o endpoint method=post da API da CaptchaAI e aplicar a resposta — índices de célula ou coordenadas de clique — de volta na página. É o caminho certo sempre que o site usa uma grade de imagens própria, fora do ecossistema do Google.
O reCAPTCHA também usa esse formato de grade, normalmente pedindo para marcar as células que contêm um determinado objeto — mas muitos sites implementam desafios de grade personalizados, sem relação nenhuma com o reCAPTCHA. Esses casos não respondem ao método de token (method=userrecaptcha), porque não existe um token do Google para gerar: o que existe é uma imagem estática, que precisa ser interpretada como um todo.
Este guia cobre o fluxo completo: capturar a imagem da grade, enviá-la para o endpoint method=post, consultar o resultado por polling e aplicar a resposta de volta no formulário, em Python e Node.js.
Requisitos para resolver CAPTCHA de grade via API
Antes de começar, você precisa de três coisas:
| Item | Detalhe |
|---|---|
| Chave de API da CaptchaAI | Gerada no painel em captchaai.com |
| Imagem da grade completa | Screenshot ou base64 da grade inteira — não recorte células individuais |
| Ambiente | Python 3.7+ ou Node.js 14+ |
Passo 1: capture a imagem completa da grade
A CaptchaAI analisa a grade inteira como uma única imagem — seja 3×3, 4×4 ou um layout fora do padrão — então não recorte célula por célula antes de enviar. Duas abordagens cobrem a maioria dos casos reais.
Opção A: screenshot do elemento do CAPTCHA
Se o desafio estiver renderizado como um elemento visível na página, capture apenas o contêiner com Selenium:
from selenium import webdriver
from selenium.webdriver.common.by import By
driver = webdriver.Chrome()
driver.get("https://example.com/protected-form")
# Screenshot just the captcha container
captcha_element = driver.find_element(By.CSS_SELECTOR, "#captcha-container")
captcha_element.screenshot("captcha_grid.png")
Opção B: extraia a imagem do atributo src
Quando a grade é uma única imagem (<img>) em vez de um elemento composto, pegue o src diretamente — ele já pode vir em base64 ou como uma URL para baixar:
import base64
import requests
captcha_img = driver.find_element(By.CSS_SELECTOR, ".grid-captcha img")
src = captcha_img.get_attribute("src")
if src.startswith("data:image"):
image_b64 = src.split(",")[1]
else:
image_data = requests.get(src).content
image_b64 = base64.b64encode(image_data).decode()
Dica de conformidade: se você guardar essas capturas de tela para depuração, trate-as como dado técnico transitório e evite reter, junto com elas, outros dados pessoais do formulário protegido — um cuidado que vale a pena alinhar com a LGPD sempre que o formulário coleta informações de usuários reais.
Passo 2: envie a imagem para o endpoint method=post da CaptchaAI
Com a imagem em mãos, envie para in.php usando method=post junto com recaptcha=1 — esse parâmetro sinaliza que a resposta deve voltar no formato de grade (índices ou coordenadas), e não como texto solto.
Upload de arquivo (Python)
import requests
import time
API_KEY = "YOUR_API_KEY"
with open("captcha_grid.png", "rb") as f:
response = requests.post("https://ocr.captchaai.com/in.php",
data={
"key": API_KEY,
"method": "post",
"recaptcha": 1,
"json": 1
},
files={"file": f}
)
data = response.json()
task_id = data["request"]
print(f"Task: {task_id}")
Envio em base64 (Python)
Se a imagem já estiver em memória, como no caso da Opção B do Passo 1, pule o upload de arquivo e envie o base64 direto no corpo da requisição:
response = requests.post("https://ocr.captchaai.com/in.php", data={
"key": API_KEY,
"method": "post",
"body": image_b64,
"recaptcha": 1,
"json": 1
})
task_id = response.json()["request"]
Envio em Node.js
A mesma chamada, agora com axios — a lógica de parâmetros é idêntica à versão em Python:
const axios = require('axios');
const fs = require('fs');
async function submitGridCaptcha(imagePath) {
const imageB64 = fs.readFileSync(imagePath).toString('base64');
const { data } = await axios.post('https://ocr.captchaai.com/in.php', null, {
params: {
key: 'YOUR_API_KEY',
method: 'post',
body: imageB64,
recaptcha: 1,
json: 1
}
});
return data.request;
}
Passo 3: consulte o resultado (polling)
A resposta não vem no mesmo request do envio — a CaptchaAI processa a imagem de forma assíncrona. Consulte res.php a cada poucos segundos até receber status: 1:
def get_grid_solution(task_id):
for _ in range(30):
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 Exception(f"Error: {result['request']}")
raise Exception("Timeout")
solution = get_grid_solution(task_id)
print(f"Solution: {solution}")
# Returns click coordinates or cell indices
Segundo a métrica pública da CaptchaAI, uma imagem de grade resolve em menos de 1 segundo em condições normais, com alta taxa de sucesso — o laço de 30 tentativas de 5 segundos acima é apenas margem de segurança para picos de fila, não uma estimativa do tempo real de solve. Se os seus workers rodam em uma região como sa-east-1 (São Paulo) na AWS, o RTT até a CaptchaAI tende a ficar baixo; ajuste o intervalo de polling conforme a latência medida no seu próprio ambiente.
Passo 4: aplique a resposta na página
O formato da resposta depende de como o site implementa a grade: alguns esperam cliques por índice de célula, outros por coordenadas x/y. Trate os dois formatos no seu código.
Clique por índice de célula
# If solution returns cell indices (e.g., "2,5,6")
selected = [int(i) for i in solution.split(",")]
cells = driver.find_elements(By.CSS_SELECTOR, ".grid-cell")
for idx in selected:
cells[idx - 1].click()
time.sleep(0.2)
driver.find_element(By.CSS_SELECTOR, ".verify-button").click()
Clique por coordenadas
from selenium.webdriver.common.action_chains import ActionChains
# If solution returns coordinates (e.g., "x=120,y=80;x=250,y=200")
captcha_element = driver.find_element(By.CSS_SELECTOR, "#captcha-container")
actions = ActionChains(driver)
for coord in solution.split(";"):
parts = dict(p.split("=") for p in coord.split(","))
x, y = int(parts["x"]), int(parts["y"])
actions.move_to_element_with_offset(captcha_element, x, y).click()
actions.perform()
Erros comuns ao resolver CAPTCHA de grade e como corrigir
| Erro | Causa | Correção |
|---|---|---|
ERROR_WRONG_FILE_EXTENSION |
Formato de imagem inválido | Use PNG ou JPEG e confira se o base64 está bem formado |
ERROR_CAPTCHA_UNSOLVABLE |
Imagem pequena demais ou borrada | Capture em resolução máxima, sem downscale |
| Células erradas selecionadas | A resposta chegou em um formato diferente do esperado | Confirme se a resposta veio como índices ou como coordenadas antes de mapear os cliques |
ERROR_TOO_BIG_CAPTCHA_FILESIZE |
A imagem passa do limite de tamanho | Redimensione para menos de 600 KB antes de enviar |
Exemplo completo pronto para rodar
Quer um projeto funcional completo, com setup de ambiente, polling, novas tentativas e tratamento de erro já implementados, em nove linguagens diferentes?
Veja o exemplo completo no GitHub →
Perguntas frequentes sobre resolução de CAPTCHA de grade
Quando usar resolução por grade em vez do método de token?
Use o método de token (method=userrecaptcha) para desafios reCAPTCHA padrão — é mais simples e mais confiável nesse caso específico. Use a resolução por grade (method=post com recaptcha=1) quando o desafio é uma grade de imagens própria do site, sem relação com o reCAPTCHA.
Quanto custa resolver CAPTCHA de grade com a CaptchaAI?
O preço não muda por tipo de CAPTCHA. Você paga por thread simultânea, com solves ilimitados por thread: o plano BASIC (US$ 15/mês, 5 threads) já cobre a maioria dos testes e integrações pequenas; para volume maior, os planos sobem até o ENTERPRISE (US$ 300/mês, 200 threads). A tabela completa de preços fica no site da CaptchaAI.
Preciso de um navegador headless para usar esse endpoint?
Não necessariamente. O endpoint method=post só precisa da imagem — como base64 ou arquivo. Um navegador (Selenium, Playwright ou Puppeteer) entra em cena apenas se você também precisar capturar a imagem na página e, depois, aplicar o clique da resposta; se a grade já chega isolada, por exemplo de um scraper de API, dá para pular o navegador inteiramente.
Dá para resolver grades dinâmicas, onde as células mudam a cada clique?
Para grades dinâmicas do reCAPTCHA, onde os blocos clicados são substituídos por novos, use o método de token (method=userrecaptcha). O método de grade resolve uma imagem estática única — não acompanha atualizações em tempo real dentro da mesma sessão de desafio.
Esse fluxo funciona em outras linguagens além de Python?
Sim. A lógica é a mesma em qualquer linguagem que consiga fazer uma requisição HTTP: os exemplos deste guia cobrem Python e Node.js, e o projeto completo no GitHub traz variações também em PHP, Go, Java, C#, Ruby, Rust e Kotlin.