Trocar de provedor sem quebrar produção é a maior preocupação em qualquer migração de captcha solver — e a boa notícia é que AZCaptcha e CaptchaAI compartilham o mesmo formato de API compatível com 2Captcha. Na prática você muda dois valores: a URL base e a chave de API. O restante do fluxo — parâmetros, resposta em JSON, lógica de polling — continua igual.
Para uma base de código única, o trabalho leva entre 15 e 30 minutos, incluindo um teste paralelo para confirmar que tudo se comporta como esperado antes de desligar a chave antiga. Este guia mostra o que muda, o roteiro de 4 etapas para migrar sem downtime e uma referência completa de endpoints e parâmetros para consultar durante o código.
O que muda e o que continua igual
- URL base — muda: de
azcaptcha.comparaocr.captchaai.com. - Chave de API — muda: gere uma nova em captchaai.com, não reaproveite a antiga.
- Parâmetros de requisição (
method,googlekey,pageurl,json,proxy) — não mudam. proxytype— não muda: continua aceitandoHTTPeSOCKS5.- Formato da resposta JSON (
status,request) — não muda. - Lógica de polling (consultar
res.phpatéstatus == 1) — não muda.
Migração em 4 etapas
Etapa 1: crie e financie sua conta CaptchaAI
- Inscreva-se em captchaai.com
- Adicione créditos à conta
- Copie sua chave de API no painel
Guarde a chave em uma variável de ambiente desde o início — é o que os exemplos abaixo já assumem, e evita ter que caçar chaves hardcoded no código depois.
Etapa 2: troque a URL base no código
A mudança real está só na URL e na origem da chave. No Python, compare o solve_recaptcha de antes — com a URL e a chave do AZCaptcha hardcoded — com a versão depois, já apontando para ocr.captchaai.com e lendo a chave do ambiente.
Python - Antes (AZCaptcha)
import requests
API_KEY = "your_azcaptcha_key"
def solve_recaptcha(sitekey, pageurl):
# Submit
resp = requests.post("https://azcaptcha.com/in.php", data={
"key": API_KEY,
"method": "userrecaptcha",
"googlekey": sitekey,
"pageurl": pageurl,
"json": 1
})
data = resp.json()
if data["status"] != 1:
return {"error": data["request"]}
captcha_id = data["request"]
# Poll
import time
for _ in range(60):
time.sleep(5)
result = requests.get("https://azcaptcha.com/res.php", params={
"key": API_KEY, "action": "get", "id": captcha_id, "json": 1
}).json()
if result["status"] == 1:
return {"solution": result["request"]}
if result["request"] != "CAPCHA_NOT_READY":
return {"error": result["request"]}
return {"error": "TIMEOUT"}
Python - Depois (CaptchaAI)
import os
import time
import requests
API_KEY = os.environ["CAPTCHAAI_API_KEY"] # Changed: use env var
def solve_recaptcha(sitekey, pageurl):
# Submit — only URL changed
resp = requests.post("https://ocr.captchaai.com/in.php", data={
"key": API_KEY,
"method": "userrecaptcha",
"googlekey": sitekey,
"pageurl": pageurl,
"json": 1
})
data = resp.json()
if data.get("status") != 1:
return {"error": data.get("request")}
captcha_id = data["request"]
# Poll — only URL changed
for _ in range(60):
time.sleep(5)
result = requests.get("https://ocr.captchaai.com/res.php", params={
"key": API_KEY, "action": "get", "id": captcha_id, "json": 1
}).json()
if result.get("status") == 1:
return {"solution": result["request"]}
if result.get("request") != "CAPCHA_NOT_READY":
return {"error": result.get("request")}
return {"error": "TIMEOUT"}
Se seu stack é Node.js em vez de Python, a mudança é a mesma coisa em outra sintaxe — só as URLs se movem:
JavaScript - Antes (AZCaptcha)
const axios = require("axios");
const API_KEY = "your_azcaptcha_key";
async function solveRecaptcha(sitekey, pageurl) {
const submit = await axios.post("https://azcaptcha.com/in.php", null, {
params: { key: API_KEY, method: "userrecaptcha", googlekey: sitekey, pageurl, json: 1 },
});
if (submit.data.status !== 1) return { error: submit.data.request };
const captchaId = submit.data.request;
for (let i = 0; i < 60; i++) {
await new Promise((r) => setTimeout(r, 5000));
const poll = await axios.get("https://azcaptcha.com/res.php", {
params: { key: API_KEY, action: "get", id: captchaId, json: 1 },
});
if (poll.data.status === 1) return { solution: poll.data.request };
if (poll.data.request !== "CAPCHA_NOT_READY") return { error: poll.data.request };
}
return { error: "TIMEOUT" };
}
JavaScript - Depois (CaptchaAI)
const axios = require("axios");
const API_KEY = process.env.CAPTCHAAI_API_KEY; // Changed: env var
async function solveRecaptcha(sitekey, pageurl) {
// Only URLs changed
const submit = await axios.post("https://ocr.captchaai.com/in.php", null, {
params: { key: API_KEY, method: "userrecaptcha", googlekey: sitekey, pageurl, json: 1 },
});
if (submit.data.status !== 1) return { error: submit.data.request };
const captchaId = submit.data.request;
for (let i = 0; i < 60; i++) {
await new Promise((r) => setTimeout(r, 5000));
const poll = await axios.get("https://ocr.captchaai.com/res.php", {
params: { key: API_KEY, action: "get", id: captchaId, json: 1 },
});
if (poll.data.status === 1) return { solution: poll.data.request };
if (poll.data.request !== "CAPCHA_NOT_READY") return { error: poll.data.request };
}
return { error: "TIMEOUT" };
}
Etapa 3: encapsule o provedor em uma classe reutilizável
Se você atende mais de um projeto, ou pode precisar trocar de provedor de novo no futuro, não hardcode a URL em cada chamada. Encapsule tudo numa classe: trocar de provedor vira uma linha, não um find-and-replace pelo repositório inteiro.
import os
import time
import requests
class CaptchaProvider:
def __init__(self, base_url, api_key):
self.submit_url = f"{base_url}/in.php"
self.result_url = f"{base_url}/res.php"
self.api_key = api_key
self.session = requests.Session()
def solve(self, sitekey, pageurl, method="userrecaptcha"):
resp = self.session.post(self.submit_url, data={
"key": self.api_key,
"method": method,
"googlekey": sitekey,
"pageurl": pageurl,
"json": 1
})
data = resp.json()
if data.get("status") != 1:
return {"error": data.get("request")}
captcha_id = data["request"]
for _ in range(60):
time.sleep(5)
result = self.session.get(self.result_url, params={
"key": self.api_key, "action": "get",
"id": captcha_id, "json": 1
}).json()
if result.get("status") == 1:
return {"solution": result["request"]}
if result.get("request") != "CAPCHA_NOT_READY":
return {"error": result.get("request")}
return {"error": "TIMEOUT"}
# Switch by changing one line:
# provider = CaptchaProvider("https://azcaptcha.com", "old_key")
provider = CaptchaProvider(
"https://ocr.captchaai.com",
os.environ["CAPTCHAAI_API_KEY"]
)
Etapa 4: rode um teste paralelo antes de virar de vez
Nunca migre tráfego de produção só porque o código compilou. Rode os dois provedores lado a lado num mesmo lote de tarefas e compare taxa de sucesso e tempo de resolução antes de desativar o AZCaptcha.
def parallel_test(sitekey, pageurl, runs=10):
azcaptcha = CaptchaProvider("https://azcaptcha.com", "old_key")
captchaai = CaptchaProvider(
"https://ocr.captchaai.com",
os.environ["CAPTCHAAI_API_KEY"]
)
results = {"azcaptcha": [], "captchaai": []}
for i in range(runs):
start = time.time()
az_result = azcaptcha.solve(sitekey, pageurl)
results["azcaptcha"].append({
"success": "solution" in az_result,
"time": time.time() - start
})
start = time.time()
cai_result = captchaai.solve(sitekey, pageurl)
results["captchaai"].append({
"success": "solution" in cai_result,
"time": time.time() - start
})
for provider, data in results.items():
successes = sum(1 for r in data if r["success"])
avg_time = sum(r["time"] for r in data) / len(data)
print(f"{provider}: {successes}/{runs} success, {avg_time:.1f}s avg")
Se os seus workers rodam no Brasil — por exemplo em sa-east-1 (São Paulo) na AWS —, meça também o RTT até cada endpoint: parte da diferença em time.time() pode vir da distância até o datacenter, não da resolução em si. Rode ao menos 50 tarefas antes de concluir algo — com apenas 10, uma solução lenta já distorce a média.
Checklist de corte: o que não pode faltar antes da virada
- [ ] Crie a conta na CaptchaAI e adicione créditos
- [ ] Troque a URL base em todos os arquivos do projeto
- [ ] Atualize a chave de API (use variável de ambiente)
- [ ] Rode o teste paralelo (10+ resoluções)
- [ ] Compare as taxas de sucesso
- [ ] Compare os tempos de resolução
- [ ] Atualize monitoramento e alertas para os novos endpoints
- [ ] Migre o tráfego de produção
- [ ] Monitore por 24 horas
- [ ] Desative a chave do AZCaptcha
Erros comuns na migração e como resolver
ERROR_KEY_DOES_NOT_EXIST
Geralmente é chave de API incorreta. Confira a chave da CaptchaAI no painel e confirme que copiou sem espaços extras.
ERROR_ZERO_BALANCE
A conta nova ainda não tem créditos. Adicione créditos em captchaai.com antes de rodar o teste paralelo.
Códigos de erro diferentes dos que eu via no AZCaptcha
Pequenas diferenças de nomenclatura entre provedores são normais. Compare os códigos lado a lado — a maioria é idêntica entre AZCaptcha e CaptchaAI.
Taxa de resolução diferente da que eu via antes
Os dois provedores usam pools de solvers diferentes. Rode 50 ou mais resoluções de teste antes de comparar; com poucas amostras, o resultado não é estatisticamente válido.
Perguntas frequentes
Dá para migrar sem reescrever a lógica de polling?
Sim. O polling segue o mesmo contrato — res.php com action=get, checando status e request a cada 5 segundos — então basta trocar a URL base e a chave, como nos exemplos acima.
O que acontece com as tarefas que já estão em andamento no AZCaptcha durante a troca?
Elas continuam sendo processadas normalmente pelo AZCaptcha até você desativar a chave antiga. Por isso o checklist recomenda manter as duas chaves ativas durante o teste paralelo e só desativar o AZCaptcha depois de monitorar 24 horas de produção estável na CaptchaAI.
Minha configuração atual de proxy continua funcionando?
Sim. A CaptchaAI usa os mesmos parâmetros proxy e proxytype (HTTP/SOCKS5), então nenhuma mudança é necessária na resolução baseada em proxy.
A CaptchaAI resolve os mesmos tipos de CAPTCHA que eu já uso no AZCaptcha?
Para os tipos mais comuns, sim: reCAPTCHA v2/v3, Cloudflare Turnstile e Cloudflare Challenge, GeeTest v3, CAPTCHA de imagem/OCR, grid e BLS. hCaptcha e FunCaptcha não são suportados atualmente — confira o tipo usado no seu fluxo antes de migrar para evitar surpresas.
Quanto tempo leva a migração?
Para uma única base de código, 15 a 30 minutos. A maior parte disso é trocar a URL base com busca e substituição, mais o tempo do teste paralelo para validar.
Referência completa: endpoints e parâmetros
Consulte estas tabelas durante o find-and-replace do Passo 2.
Endpoints
| Operação | AZCaptcha | CaptchaAI |
|---|---|---|
| Enviar tarefa | https://azcaptcha.com/in.php |
https://ocr.captchaai.com/in.php |
| Consultar resultado | https://azcaptcha.com/res.php |
https://ocr.captchaai.com/res.php |
| Consultar saldo | res.php?action=getbalance |
res.php?action=getbalance |
| Reportar erro | res.php?action=reportbad |
res.php?action=reportbad |
Parâmetros
A maior parte dos parâmetros é idêntica. As diferenças reais:
| Parâmetro | AZCaptcha | CaptchaAI | Observação |
|---|---|---|---|
key |
chave de API | chave de API | Chave diferente — gere a sua em captchaai.com |
method |
userrecaptcha |
userrecaptcha |
Igual |
googlekey |
sitekey | sitekey | Igual |
pageurl |
URL da página | URL da página | Igual |
json |
1 |
1 |
Igual |
proxy |
user:pass@host:port |
user:pass@host:port |
Mesmo formato |
proxytype |
HTTP/SOCKS5 |
HTTP/SOCKS5 |
Igual |
Próximos passos
Pronto para migrar? Obtenha sua chave de API da CaptchaAI e comece pelo teste paralelo antes de virar o tráfego de produção.
Guias relacionados:
- Mapeamento de endpoints da API
- Como rodar o teste paralelo até a virada
- Por que times trocam de provedor de captcha