Uma tarefa de CAPTCHA que costuma levar 15 segundos hoje está levando 55 — e sem instrumentação, descobrir se o culpado é o worker de scraping travado ou o checkout de um cliente parado vira uma sessão inteira de grep em log. Ligue a CaptchaAI ao New Relic APM e cada chamada a in.php/res.php passa a ser uma transação rastreável: latência de envio, tempo de polling, taxa de sucesso e saldo da conta aparecem no mesmo painel onde você já acompanha o resto da aplicação.
Neste guia você encontra:
- O que instrumentar em cada fase do pipeline (envio, espera, aplicação do token)
- Instrumentação completa em Python e em JavaScript/Node.js
- Consultas NRQL prontas para montar o painel
- Alertas de taxa de resolução, latência e saldo
- Erros comuns de configuração e como corrigi-los
Quais métricas do pipeline CaptchaAI acompanhar no New Relic
O pipeline de resolução tem três fases bem distintas, e cada uma pede um tipo de métrica diferente:
- Envio — latência da chamada a
in.phpe erros de submissão (chave inválida, sitekey errada) - Espera — duração do polling em
res.phpe taxa de timeout - Aplicação do token — se o token chegou a ser usado no formulário e taxa de sucesso final
[Submit Task] → [Wait for Solution] → [Apply Token]
↓ ↓ ↓
Submit latency Poll duration Token usage
API errors Timeout rate Success rate
As seções a seguir mostram como capturar essas métricas com atributos e eventos personalizados — primeiro em Python, depois em Node.js.
Um detalhe que muda o resultado na prática: se os workers rodam fora da região do seu tráfego, o RTT extra de cada chamada de polling se soma no painel de latência. Para tráfego majoritariamente brasileiro, medir a partir de uma região como sa-east-1 (São Paulo) dá um baseline mais realista do que medir a partir dos EUA ou da Europa. E se algum atributo personalizado guardar dado que identifique uma pessoa — IP ou e-mail capturado durante um scraping, por exemplo — trate essa telemetria com o mesmo cuidado que a LGPD exige de qualquer outro dado pessoal: não logue esses campos como atributo do New Relic.
Instrumentação em Python: eventos personalizados do CaptchaAI no New Relic
O decorador @newrelic.agent.background_task transforma cada chamada a solve_captcha em uma transação em segundo plano rastreada pelo agente. Dentro dela, os eventos CaptchaSolveSuccess e CaptchaSolveError guardam o que o APM sozinho não sabe: o tipo de CAPTCHA, o tempo de resolução e a causa exata da falha.
import os
import time
import requests
import newrelic.agent
API_KEY = os.environ["CAPTCHAAI_API_KEY"]
session = requests.Session()
@newrelic.agent.background_task(name="captcha_solve", group="CaptchaAI")
def solve_captcha(sitekey, pageurl, captcha_type="recaptcha_v2"):
"""Solve a CAPTCHA with full New Relic instrumentation."""
# Add custom attributes for filtering
newrelic.agent.add_custom_attributes([
("captcha_type", captcha_type),
("target_url", pageurl),
])
# Submit phase
submit_result = _submit_task(sitekey, pageurl, captcha_type)
if "error" in submit_result:
newrelic.agent.record_custom_event("CaptchaSolveError", {
"error": submit_result["error"],
"phase": "submit",
"captcha_type": captcha_type,
})
return submit_result
# Poll phase
captcha_id = submit_result["captcha_id"]
poll_result = _poll_result(captcha_id, captcha_type)
# Record solve event
event_data = {
"captcha_type": captcha_type,
"captcha_id": captcha_id,
"success": "solution" in poll_result,
}
if "solution" in poll_result:
event_data["solve_time"] = poll_result.get("elapsed", 0)
newrelic.agent.record_custom_event("CaptchaSolveSuccess", event_data)
else:
event_data["error"] = poll_result.get("error", "unknown")
newrelic.agent.record_custom_event("CaptchaSolveError", event_data)
return poll_result
@newrelic.agent.function_trace(name="captcha_submit")
def _submit_task(sitekey, pageurl, captcha_type):
payload = {
"key": API_KEY,
"method": "userrecaptcha",
"googlekey": sitekey,
"pageurl": pageurl,
"json": 1
}
resp = session.post("https://ocr.captchaai.com/in.php", data=payload)
data = resp.json()
newrelic.agent.add_custom_attributes([
("submit_status", data.get("status")),
])
if data.get("status") != 1:
return {"error": data.get("request")}
return {"captcha_id": data["request"]}
@newrelic.agent.function_trace(name="captcha_poll")
def _poll_result(captcha_id, captcha_type):
start = time.time()
poll_count = 0
for _ in range(60):
time.sleep(5)
poll_count += 1
result = session.get("https://ocr.captchaai.com/res.php", params={
"key": API_KEY, "action": "get", "id": captcha_id, "json": 1
}).json()
if result.get("status") == 1:
elapsed = time.time() - start
newrelic.agent.add_custom_attributes([
("poll_count", poll_count),
("solve_time_seconds", round(elapsed, 2)),
])
return {"solution": result["request"], "elapsed": elapsed}
if result.get("request") != "CAPCHA_NOT_READY":
return {"error": result.get("request")}
return {"error": "TIMEOUT"}
def report_balance():
"""Record balance as a custom event."""
resp = session.get("https://ocr.captchaai.com/res.php", params={
"key": API_KEY, "action": "getbalance", "json": 1
})
data = resp.json()
if data.get("status") == 1:
balance = float(data["request"])
newrelic.agent.record_custom_event("CaptchaBalance", {
"balance": balance,
"low": balance < 10,
})
return balance
return None
newrelic.ini: dois ajustes para não perder dados em produção
Dois pontos custam caro se ficarem no padrão de fábrica:
custom_insights_events.enabledprecisa estartruepara os eventos acima aparecerem no NRQL, e otransaction_thresholdde 5 segundos costuma ser alto demais — a fase de polling sozinha já ultrapassa isso na maioria dos tipos de CAPTCHA.
# newrelic.ini
[newrelic]
app_name = CaptchaAI Pipeline
license_key = YOUR_NEW_RELIC_LICENSE_KEY
monitor_mode = true
log_level = info
transaction_tracer.enabled = true
transaction_tracer.transaction_threshold = 5.0
custom_insights_events.enabled = true
custom_insights_events.max_samples_stored = 5000
JavaScript: enviando eventos do CaptchaAI para o New Relic
A versão em Node.js segue a mesma lógica — envio, polling, evento de sucesso ou erro — só que dentro de uma startBackgroundTransaction e usando axios no lugar do requests do Python.
const newrelic = require("newrelic");
const axios = require("axios");
const API_KEY = process.env.CAPTCHAAI_API_KEY;
async function solveCaptchaWithNewRelic(sitekey, pageurl, captchaType = "recaptcha_v2") {
return newrelic.startBackgroundTransaction(
"CaptchaSolve",
"CaptchaAI",
async () => {
const transaction = newrelic.getTransaction();
newrelic.addCustomAttributes({
captchaType,
targetUrl: pageurl,
});
const startTime = Date.now();
try {
// Submit
const submitResp = await axios.post(
"https://ocr.captchaai.com/in.php",
null,
{
params: {
key: API_KEY,
method: "userrecaptcha",
googlekey: sitekey,
pageurl: pageurl,
json: 1,
},
}
);
if (submitResp.data.status !== 1) {
newrelic.recordCustomEvent("CaptchaSolveError", {
error: submitResp.data.request,
phase: "submit",
captchaType,
});
transaction.end();
return { error: submitResp.data.request };
}
const captchaId = submitResp.data.request;
newrelic.addCustomAttributes({ captchaId });
// Poll
let pollCount = 0;
for (let i = 0; i < 60; i++) {
await new Promise((r) => setTimeout(r, 5000));
pollCount++;
const pollResp = await axios.get(
"https://ocr.captchaai.com/res.php",
{
params: {
key: API_KEY, action: "get", id: captchaId, json: 1,
},
}
);
if (pollResp.data.status === 1) {
const elapsed = (Date.now() - startTime) / 1000;
newrelic.recordCustomEvent("CaptchaSolveSuccess", {
captchaType,
solveTime: elapsed,
pollCount,
});
newrelic.addCustomAttributes({
solveTime: elapsed,
pollCount,
});
transaction.end();
return { solution: pollResp.data.request, elapsed };
}
if (pollResp.data.request !== "CAPCHA_NOT_READY") {
newrelic.recordCustomEvent("CaptchaSolveError", {
error: pollResp.data.request,
phase: "poll",
captchaType,
});
transaction.end();
return { error: pollResp.data.request };
}
}
newrelic.recordCustomEvent("CaptchaSolveError", {
error: "TIMEOUT",
phase: "poll",
captchaType,
pollCount,
});
transaction.end();
return { error: "TIMEOUT" };
} catch (err) {
newrelic.noticeError(err);
transaction.end();
throw err;
}
}
);
}
// Balance monitoring
async function monitorBalance() {
try {
const resp = await axios.get("https://ocr.captchaai.com/res.php", {
params: { key: API_KEY, action: "getbalance", json: 1 },
});
if (resp.data.status === 1) {
const balance = parseFloat(resp.data.request);
newrelic.recordCustomEvent("CaptchaBalance", { balance });
}
} catch (err) {
newrelic.noticeError(err);
}
}
setInterval(monitorBalance, 60000);
module.exports = { solveCaptchaWithNewRelic };
Consultas NRQL para o painel de monitoramento da CaptchaAI
Com os eventos personalizados chegando, estas seis consultas cobrem o essencial:
- Taxa de sucesso na última hora
- Tempo médio de resolução por tipo de CAPTCHA
- Erros mais frequentes, agrupados por causa
- Latência P95 ao longo do tempo
- Saldo da conta nas últimas 24 horas
- Volume de tarefas por minuto
-- Solve success rate (last hour)
SELECT percentage(count(*), WHERE success = true)
FROM CaptchaSolveSuccess, CaptchaSolveError
SINCE 1 hour ago
-- Average solve time by CAPTCHA type
SELECT average(solveTime)
FROM CaptchaSolveSuccess
FACET captchaType
SINCE 1 hour ago TIMESERIES
-- Error breakdown
SELECT count(*)
FROM CaptchaSolveError
FACET error
SINCE 1 hour ago
-- P95 solve latency
SELECT percentile(solveTime, 95)
FROM CaptchaSolveSuccess
SINCE 1 hour ago TIMESERIES
-- Balance over time
SELECT latest(balance)
FROM CaptchaBalance
SINCE 24 hours ago TIMESERIES 5 minutes
-- Tasks per minute
SELECT rate(count(*), 1 minute)
FROM CaptchaSolveSuccess, CaptchaSolveError
SINCE 1 hour ago TIMESERIES
Alertas de taxa de resolução, latência e saldo
Estas quatro condições, montadas a partir das mesmas consultas NRQL, cobrem os sintomas que normalmente chegam primeiro como chamado de suporte:
- Queda na taxa de resolução
- Latência acima do aceitável no P95
- Saldo da conta perto de zerar
- Pico repentino de erros
| Alerta | Condição NRQL | Limite |
|---|---|---|
| Taxa de resolução baixa | SELECT percentage(count(*), WHERE success = true) |
<85% por 5 min |
| Latência alta | SELECT percentile(solveTime, 95) FROM CaptchaSolveSuccess |
> 120s por 10 min |
| Saldo baixo | SELECT latest(balance) FROM CaptchaBalance |
<US$ 10 |
| Pico de erros | SELECT count(*) FROM CaptchaSolveError |
> 50 em 5 minutos |
Erros comuns na integração CaptchaAI + New Relic
| Problema | Causa | Correção |
|---|---|---|
| Eventos personalizados não aparecem | custom_insights_events.enabled está como falso |
Habilite em newrelic.ini |
| Rastreamentos de transação ausentes | Limite (threshold) muito alto |
Reduza transaction_threshold para 1,0s |
| Atributos truncados | Valor muito longo | Mantenha os valores dos atributos com menos de 255 caracteres |
| Nenhum dado após o deploy | Chave de licença errada ou agente não inicia | Verifique com newrelic-admin validate-config newrelic.ini |
Perguntas frequentes
Esse monitoramento funciona para os tipos em beta (CaptchaFox, Friendly Captcha, Lemin)?
Sim — a instrumentação não depende do tipo de CAPTCHA, então basta registrar o captcha_type correto nos atributos e eventos personalizados. O que muda é o que dá para comparar:
- Tipos GA (reCAPTCHA v2/v3, Turnstile, GeeTest v3, imagem/OCR, grid, BLS) — taxa de sucesso e tempo de resolução já têm uma referência pública.
- Tipos em beta (CaptchaFox, Friendly Captcha, Lemin) — ainda sem taxa pública; use os próprios eventos do seu painel como linha de base.
- hCaptcha e FunCaptcha continuam fora do catálogo da CaptchaAI, então não há o que monitorar ali.
É seguro registrar esses eventos sem expor a chave de API nos logs do New Relic?
Sim, desde que você nunca inclua CAPTCHAAI_API_KEY como atributo personalizado — os exemplos deste guia só enviam captcha_type, captcha_id e tempos de resolução. Para uma camada extra, use attributes.exclude no newrelic.ini para bloquear qualquer atributo que comece com key ou token.
Qual a diferença entre o APM automático e os eventos personalizados que criamos aqui?
O APM instrumenta sozinho as chamadas HTTP, então já mostra latência e erros de rede sem nenhum código extra. Só que ele não sabe o que é um CAPTCHA — não distingue um erro de rede de um ERROR_WRONG_USER_KEY, por exemplo. É para isso que servem os eventos personalizados: eles carregam o contexto de negócio (tipo de CAPTCHA, tempo de resolução, causa da falha) que o APM sozinho não captura.
A instrumentação do New Relic deixa a resolução do CAPTCHA mais lenta?
Não de forma perceptível. O agente adiciona microssegundos de overhead por chamada instrumentada, e o tempo de resolução de um CAPTCHA (5 a 120 segundos, dependendo do tipo) torna essa diferença impossível de medir na prática.
Artigos relacionados
- Integração da CaptchaAI com Google Cloud Functions
- Scraping moderno com Crawlee e CaptchaAI
- Como montar um sistema de monitoramento de reviews com a CaptchaAI
Próximos passos
Tenha visibilidade completa do seu pipeline de CAPTCHA — comece com uma chave de API da CaptchaAI e conecte o New Relic em poucos minutos.
Veja também: