ERROR_ZERO_BALANCE no meio de um lote de reCAPTCHA quase nunca significa conta sem crédito — na maioria das vezes é só um thread ocupado. Saber essa diferença é o que separa um chamado de suporte desnecessário de uma correção de 30 segundos.
Esta referência reúne todos os códigos de erro da API, organizados pelos dois endpoints onde eles aparecem:
in.php— erros de envio, disparados no momento em que você cria a tarefares.php— erros de consulta, disparados enquanto você aguarda o resultado
Para cada código: a causa real, a correção passo a passo e, quando existe, um payload de exemplo.
Como o CaptchaAI formata os erros
Inclua json=1 na requisição e os erros chegam estruturados:
{"status": 0, "request": "ERROR_CODE_HERE"}
Sem json=1, os erros retornam como texto simples: ERROR_CODE_HERE
As três regras que resolvem 90% dos erros
Antes de mergulhar na referência completa, memorize esta tabela — ela cobre a grande maioria dos casos reais:
| Padrão de erro | Ação |
|---|---|
CAPCHA_NOT_READY |
Normal — consulte novamente em 5 segundos |
Qualquer ERROR_ ligado a parâmetro ou formato |
Corrija a requisição — não reenvie a mesma requisição sem alterá-la |
Erros de servidor (ERROR_SERVER_ERROR, ERROR_INTERNAL_SERVER_ERROR) |
Tente novamente após 10 segundos, com backoff exponencial |
Erros ao enviar uma tarefa (in.php)
Estes códigos aparecem no momento em que você envia um novo CAPTCHA para a fila.
ERROR_WRONG_USER_KEY
Causa
o parâmetro key está em um formato incorreto. Toda chave de API da CaptchaAI tem 32 caracteres.
Correção
- Confirme que sua chave tem exatamente 32 caracteres.
- Verifique se não sobrou espaço em branco ou quebra de linha ao copiar.
- Copie a chave direto do painel em captchaai.com/api.php — nunca digite manualmente.
{
"key": "abc123... "
}
{
"key": "abc12345678901234567890123456789a"
}
ERROR_KEY_DOES_NOT_EXIST
Causa
a chave de API informada não corresponde a nenhuma conta ativa no sistema.
Correção
- Faça login em captchaai.com e copie a chave diretamente do painel.
- Confirme que é a chave da conta certa — é comum copiar por engano a chave de uma conta ou ambiente de teste.
- Se a conta acabou de ser criada, aguarde alguns minutos até a chave ser ativada.
ERROR_ZERO_BALANCE
Causa
não há threads disponíveis na sua conta para aceitar a tarefa agora.
Correção
- Aguarde as tarefas em execução terminarem — os threads são liberados assim que cada solução é entregue.
- Se isso acontece com frequência, faça upgrade de plano para mais threads simultâneos.
- Confira o saldo da conta em captchaai.com/api.php.
Nem sempre é falta de crédito. Se todos os threads do seu plano estiverem ocupados com outras tarefas no mesmo instante, novos envios recebem
ERROR_ZERO_BALANCEaté que um thread termine e seja liberado — mesmo com saldo positivo na conta.
ERROR_PAGEURL
Causa
o parâmetro pageurl está vazio ou ausente. Ele é obrigatório em qualquer CAPTCHA baseado em token (reCAPTCHA, Cloudflare Turnstile, GeeTest etc.).
Correção
envie a URL completa da página onde o CAPTCHA é carregado, com o protocolo incluído:
{
"pageurl": ""
}
{
"pageurl": "https://staging.example.com/qa-login"
}
ERROR_WRONG_GOOGLEKEY / ERROR_GOOGLEKEY
Causa
o parâmetro googlekey (a sitekey) está em branco, malformado ou ausente.
Correção
- Extraia novamente a sitekey do atributo
data-sitekeyna página de destino, ou do parâmetrokna URL âncora do reCAPTCHA. - Confirme que o valor não está vazio nem truncado ao copiar.
{
"googlekey": ""
}
{
"googlekey": "6Le-wvkSAAAAAPBMRTvw0Q4Muexq9bi0DJwx_mJ-"
}
ERROR_BAD_TOKEN_OR_PAGEURL
Causa
a combinação entre googlekey (sitekey) e pageurl é inválida — a sitekey não está registrada para essa URL de página.
Causas mais comuns:
- O widget do reCAPTCHA carrega dentro de um iframe em outro subdomínio, e você está enviando a URL da página pai em vez da URL do iframe.
- A sitekey pertence a outra página ou domínio.
- A sitekey foi extraída de um ambiente de desenvolvimento ou staging, não de produção.
Correção
- Se o reCAPTCHA estiver dentro de um iframe, use a URL
srcdo iframe comopageurl. - Confira a sitekey diretamente na página de produção, ao vivo.
- Teste os dois valores carregando manualmente a URL âncora do reCAPTCHA:
https://www.google.com/recaptcha/api2/anchor?k=YOUR_SITEKEY
Erros de upload de imagem: tamanho, formato e tipo
Estes quatro códigos têm a mesma raiz — algo errado no arquivo de imagem enviado — e a correção é sempre revisar o upload antes de reenviar:
| Código | Causa | Correção |
|---|---|---|
ERROR_TOO_BIG_CAPTCHA_FILESIZE |
A imagem ultrapassa o tamanho máximo aceito. | Comprima ou redimensione antes de enviar — JPEG para fotos, PNG para capturas de tela. |
ERROR_ZERO_CAPTCHA_FILESIZE |
O arquivo tem menos de 100 bytes — upload vazio ou corrompido. | Confirme que está enviando dados de imagem reais, não um arquivo vazio ou base64 quebrado. |
ERROR_WRONG_FILE_EXTENSION |
Extensão não suportada. Aceitos: jpg, jpeg, png, gif. |
Converta para um formato suportado antes de enviar. |
ERROR_IMAGE_TYPE_NOT_SUPPORTED |
O servidor não identifica o tipo da imagem pelo conteúdo do arquivo. | Converta para PNG ou JPEG e confirme que o arquivo não está corrompido. |
ERROR_UPLOAD
Causa
o servidor não conseguiu ler o arquivo enviado ou o payload base64.
Correção
- Em uploads de arquivo: confira a codificação do formulário multipart.
- Em base64: confirme que a string está completa e corretamente codificada.
- Teste com uma imagem já validada, para descartar corrupção de arquivo.
ERROR_BAD_PROXY
Causa
o proxy informado está inacessível ou foi marcado como inválido pelo sistema.
Correção
- Teste o proxy separadamente — ele consegue se conectar ao site de destino sozinho?
- Tente um proxy diferente.
- Confira o formato esperado:
login:senha@IP:PORTAouIP:PORTApara proxies autenticados por IP.
O uso de proxy precisa estar habilitado na sua conta. Se ainda não estiver, fale com o suporte da CaptchaAI.
ERROR_BAD_PARAMETERS
Causa
faltam parâmetros obrigatórios, ou algum deles tem o tipo de dado errado.
Correção
confira a documentação da API para o tipo de CAPTCHA específico e valide se todos os parâmetros exigidos estão presentes:
| Tipo CAPTCHA | Parâmetros obrigatórios |
|---|---|
| reCAPTCHA v2/v3 | key, method=userrecaptcha, googlekey, pageurl |
| Cloudflare Turnstile | key, method=turnstile, sitekey, pageurl |
| Cloudflare Turnstile em staging | key, method=turnstile_staging, pageurl, proxy, proxytype |
| GeeTest v3 | key, method=geetest, gt, challenge, pageurl |
| BLS | key, method=bls, body, textinstructions |
| Normal/image | key, method=post, file ou body |
IP_BANNED
Causa
seu IP foi banido temporariamente depois de repetidas tentativas de autenticação com falha.
Correção
aguarde cerca de 5 minutos e tente novamente com as credenciais corretas. Não insista enviando requisições com uma chave de API errada — isso só prolonga o bloqueio.
ERROR_SERVER_ERROR / ERROR_INTERNAL_SERVER_ERROR
Causa
falha temporária do lado do servidor.
Correção
aguarde 10 segundos e tente novamente. Use backoff exponencial para falhas repetidas:
import time
retry_delay = 10
for attempt in range(5):
response = submit_captcha()
if response.get("status") == 1:
break
time.sleep(retry_delay)
retry_delay *= 2 # 10s, 20s, 40s, 80s, 160s
Erros de consulta (res.php)
Estes códigos aparecem quando você verifica o status de uma tarefa já enviada.
CAPCHA_NOT_READY
Isto não é um erro. Significa que a solução ainda está sendo processada.
Ação
aguarde 5 segundos e consulte novamente.
if result.get("request") == "CAPCHA_NOT_READY":
time.sleep(5)
continue # poll again
Guia de tempo por tipo:
| Tipo CAPTCHA | Primeira consulta após | Intervalo entre consultas |
|---|---|---|
| reCAPTCHA v2/v3/Enterprise | 15 segundos | 5 segundos |
| Cloudflare Turnstile | 15 segundos | 5 segundos |
| Cloudflare Turnstile em staging | 20 segundos | 5 segundos |
| GeeTest v3 | 15 segundos | 5 segundos |
| Normal/image CAPTCHA | 5 segundos | 5 segundos |
ERROR_CAPTCHA_UNSOLVABLE
Causa
o CaptchaAI não conseguiu resolver o CAPTCHA depois de várias tentativas.
Motivos mais comuns:
- O tipo de CAPTCHA não é suportado, ou algum parâmetro está errado.
- O desafio expirou ou chegou corrompido.
- Em soluções com proxy: o proxy está lento demais ou inacessível.
- O site mudou a implementação do CAPTCHA.
Correção
- Confira se sitekey, pageurl e método estão corretos.
- Reenvie como uma tarefa nova.
- Se estiver usando proxy, teste outro.
- Se o erro persistir, é provável que o site tenha mudado — extraia sitekey e pageurl de novo.
Não tente reconsultar o mesmo ID de tarefa depois desse erro. Envie uma tarefa nova, com parâmetros atualizados.
Erros de ID da tarefa
| Código | Causa | Correção |
|---|---|---|
ERROR_WRONG_ID_FORMAT |
O ID do CAPTCHA precisa ser só numérico. | Envie exatamente o ID devolvido por in.php — apenas dígitos, sem caracteres extras. |
ERROR_WRONG_CAPTCHA_ID |
O ID da tarefa não existe ou já expirou. | Confirme que está consultando com o ID do envio original; se a tarefa for muito antiga, reenvie-a. |
ERROR_EMPTY_ACTION
Causa
o parâmetro action está ausente ou vazio na requisição de consulta.
Correção
inclua action=get na sua requisição a res.php:
params = {
"key": api_key,
"action": "get", # Required
"id": captcha_id,
"json": 1,
}
ERROR_PROXY_CONNECTION_FAILED
Causa
o solucionador não conseguiu se conectar ao site de destino usando seu proxy.
Correção
- O proxy pode estar temporariamente fora do ar — tente outro.
- O site de destino pode estar bloqueando o IP do proxy.
- Confirme que o proxy realmente alcança o site de destino.
ERROR_WRONG_USER_KEY / ERROR_KEY_DOES_NOT_EXIST
Esses dois também podem aparecer em res.php — mesma causa e mesma correção descritas nos erros de envio, acima.
Modelo pronto para tratamento de erros
Use este padrão como ponto de partida para um tratamento de erros robusto, em qualquer linguagem:
Python
import time
import requests
API_KEY = "YOUR_API_KEY"
SUBMIT_URL = "https://ocr.captchaai.com/in.php"
RESULT_URL = "https://ocr.captchaai.com/res.php"
# Errors that should not be retried (fix the request first)
NO_RETRY_ERRORS = {
"ERROR_WRONG_USER_KEY",
"ERROR_KEY_DOES_NOT_EXIST",
"ERROR_PAGEURL",
"ERROR_WRONG_GOOGLEKEY",
"ERROR_GOOGLEKEY",
"ERROR_BAD_TOKEN_OR_PAGEURL",
"ERROR_BAD_PARAMETERS",
"ERROR_WRONG_FILE_EXTENSION",
"ERROR_IMAGE_TYPE_NOT_SUPPORTED",
"IP_BANNED",
}
# Errors that can be retried
RETRY_ERRORS = {
"ERROR_ZERO_BALANCE",
"ERROR_SERVER_ERROR",
"ERROR_INTERNAL_SERVER_ERROR",
"ERROR_UPLOAD",
}
def solve_captcha(submit_data, max_retries=3, max_polls=60):
"""Submit and solve a CAPTCHA with full error handling."""
# Submit with retry logic
for attempt in range(max_retries):
resp = requests.post(SUBMIT_URL, data={**submit_data, "json": 1}, timeout=30)
resp.raise_for_status()
data = resp.json()
if data.get("status") == 1:
captcha_id = data["request"]
break
error = data.get("request", "UNKNOWN")
if error in NO_RETRY_ERRORS:
raise ValueError(f"Fatal error (fix request): {error}")
if error in RETRY_ERRORS and attempt < max_retries - 1:
time.sleep(10 * (2 ** attempt))
continue
raise RuntimeError(f"Submit failed: {error}")
else:
raise RuntimeError("Submit failed after max retries")
# Poll for result
time.sleep(15)
for _ in range(max_polls):
resp = requests.get(
RESULT_URL,
params={"key": API_KEY, "action": "get", "id": captcha_id, "json": 1},
timeout=30,
)
data = resp.json()
if data.get("request") == "CAPCHA_NOT_READY":
time.sleep(5)
continue
if data.get("status") == 1:
return data["request"]
error = data.get("request", "UNKNOWN")
if error == "ERROR_CAPTCHA_UNSOLVABLE":
raise RuntimeError("CAPTCHA unsolvable — resubmit with fresh parameters")
raise RuntimeError(f"Poll error: {error}")
raise TimeoutError("Solve timed out")
Node.js
const NO_RETRY_ERRORS = new Set([
"ERROR_WRONG_USER_KEY",
"ERROR_KEY_DOES_NOT_EXIST",
"ERROR_PAGEURL",
"ERROR_WRONG_GOOGLEKEY",
"ERROR_BAD_TOKEN_OR_PAGEURL",
"ERROR_BAD_PARAMETERS",
"IP_BANNED",
]);
async function solveCaptcha(submitData, maxRetries = 3, maxPolls = 60) {
const sleep = (ms) => new Promise((r) => setTimeout(r, ms));
// Submit with retry
let captchaId;
for (let attempt = 0; attempt < maxRetries; attempt++) {
const resp = await fetch("https://ocr.captchaai.com/in.php", {
method: "POST",
headers: { "Content-Type": "application/x-www-form-urlencoded" },
body: new URLSearchParams({ ...submitData, json: "1" }),
});
const data = await resp.json();
if (data.status === 1) {
captchaId = data.request;
break;
}
if (NO_RETRY_ERRORS.has(data.request)) {
throw new Error(`Fatal error: ${data.request}`);
}
if (attempt < maxRetries - 1) {
await sleep(10_000 * 2 ** attempt);
continue;
}
throw new Error(`Submit failed: ${data.request}`);
}
// Poll for result
await sleep(15_000);
for (let i = 0; i < maxPolls; i++) {
const resp = await fetch(
`https://ocr.captchaai.com/res.php?${new URLSearchParams({
key: submitData.key,
action: "get",
id: captchaId,
json: "1",
})}`
);
const data = await resp.json();
if (data.request === "CAPCHA_NOT_READY") {
await sleep(5_000);
continue;
}
if (data.status === 1) return data.request;
throw new Error(`Poll error: ${data.request}`);
}
throw new Error("Solve timed out");
}
Um cenário real: QA autorizado a partir do Brasil
Detalhe que pega equipes brasileiras de surpresa: se seus workers rodam em sa-east-1 (São Paulo) e o site de destino fica na Europa ou nos EUA, a latência de rede se soma ao tempo de resolução. Isso não gera um ERROR_ novo — mas pode fazer a primeira consulta chegar cedo demais e devolver CAPCHA_NOT_READY mais vezes que o esperado. Se isso for frequente, aumente o intervalo da primeira consulta antes de tratar como bug.
Outro ponto para QA autorizado: os payloads de erro trazem pageurl e, às vezes, dados do formulário de teste. Se seu pipeline salva esses payloads em log, trate-os como dado sensível e observe a LGPD ao armazenar e descartar os registros — mesmo com dados fictícios de staging, vale nascer já com a política de retenção correta.
Perguntas frequentes
Quanto tempo é normal esperar em CAPCHA_NOT_READY antes de considerar a tarefa travada?
Depende do tipo. Para reCAPTCHA, Turnstile e GeeTest v3, a primeira consulta útil chega em 15 segundos; para imagem/OCR, em 5 segundos. Se você passar de 60–90 segundos sem receber nada além de CAPCHA_NOT_READY, trate como travado: pare de consultar e reenvie a tarefa em vez de manter o polling indefinidamente.
ERROR_ZERO_BALANCE sempre significa que o crédito acabou?
Não. Na maioria dos casos é sinal de threads ocupados, não de saldo zerado. Confira o saldo em captchaai.com/api.php antes de assumir que precisa fazer upgrade — se o saldo estiver positivo, o mais provável é que as tarefas em execução ainda não liberaram um thread.
Recebi ERROR_CAPTCHA_UNSOLVABLE só em um site específico — é bug no meu código?
Nem sempre. Primeiro confirme que sitekey e pageurl vêm da página de produção, não de um iframe ou de staging. Se os parâmetros estiverem certos e o erro continuar isolado nesse site, é provável que ele tenha mudado a implementação do CAPTCHA recentemente — reextraia os parâmetros antes de abrir um chamado.
Como decido entre tentar novamente e parar para revisar a requisição?
Erros de parâmetro ou formato (ERROR_WRONG_USER_KEY, ERROR_PAGEURL, ERROR_BAD_TOKEN_OR_PAGEURL, entre outros) não devem ser repetidos — corrija a requisição primeiro. Erros de servidor (ERROR_SERVER_ERROR, ERROR_INTERNAL_SERVER_ERROR) são seguros para retentativa com backoff exponencial. ERROR_ZERO_BALANCE pode ser tentado de novo depois que um thread for liberado.
Preciso logar o payload inteiro do erro para abrir um chamado de suporte?
Não é obrigatório, mas ajuda muito: envie o código de erro exato, o pageurl usado e o horário aproximado. Evite incluir tokens de sessão ou dados pessoais do formulário de teste no chamado — mantenha o exemplo com dados fictícios de staging sempre que possível.
Guias relacionados
- Início rápido da CaptchaAI — para colocar sua primeira solução no ar
- Como resolver reCAPTCHA v2 pela API — tutorial completo do reCAPTCHA v2
- Como resolver Cloudflare Turnstile em staging pela API — o fluxo com proxy que essa variante exige
- Erros comuns ao resolver reCAPTCHA v2 — troubleshooting específico desse tipo