You can't fix what you can't see. Datadog gives you real-time visibility into your CAPTCHA solving pipeline — solve rates, latency percentiles, error breakdowns, and anomaly alerts that fire before your pipeline breaks.
Key Metrics to Track
| Metric | Type | Why It Matters |
|---|---|---|
captcha.solve.count |
Counter | Total tasks submitted |
captcha.solve.success |
Counter | Successful solves |
captcha.solve.error |
Counter | Failed solves (by error type) |
captcha.solve.latency |
Histogram | Time from submit to solution |
captcha.queue.depth |
Gauge | Pending tasks in queue |
captcha.balance |
Gauge | Remaining API balance |
captcha.worker.active |
Gauge | Active worker processes |
Python — DogStatsD Integration
import os
import time
import functools
import requests
from datadog import initialize, statsd
# Initialize Datadog
initialize(
statsd_host=os.environ.get("DD_AGENT_HOST", "localhost"),
statsd_port=int(os.environ.get("DD_DOGSTATSD_PORT", "8125"))
)
API_KEY = os.environ["CAPTCHAAI_API_KEY"]
session = requests.Session()
def track_captcha_metrics(captcha_type="recaptcha_v2"):
"""Decorator to track solve metrics."""
def decorator(func):
@functools.wraps(func)
def wrapper(*args, **kwargs):
tags = [f"captcha_type:{captcha_type}"]
statsd.increment("captcha.solve.count", tags=tags)
start = time.time()
try:
result = func(*args, **kwargs)
elapsed = time.time() - start
if "solution" in result:
statsd.increment("captcha.solve.success", tags=tags)
statsd.histogram("captcha.solve.latency", elapsed, tags=tags)
else:
error = result.get("error", "unknown")
statsd.increment(
"captcha.solve.error",
tags=tags + [f"error:{error}"]
)
return result
except Exception as e:
statsd.increment(
"captcha.solve.error",
tags=tags + [f"error:{type(e).__name__}"]
)
raise
return wrapper
return decorator
@track_captcha_metrics(captcha_type="recaptcha_v2")
def solve_recaptcha(sitekey, pageurl):
resp = session.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"]
for _ in range(60):
time.sleep(5)
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:
return {"solution": result["request"]}
if result.get("request") != "CAPCHA_NOT_READY":
return {"error": result.get("request")}
return {"error": "TIMEOUT"}
def report_balance():
"""Send balance as a gauge metric."""
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"])
statsd.gauge("captcha.balance", balance)
return balance
return None
def report_queue_depth(depth):
"""Report current queue depth."""
statsd.gauge("captcha.queue.depth", depth)
def report_worker_count(active, total):
"""Report worker health."""
statsd.gauge("captcha.worker.active", active)
statsd.gauge("captcha.worker.total", total)
JavaScript — Datadog Integration
const { StatsD } = require("hot-shots");
const axios = require("axios");
const API_KEY = process.env.CAPTCHAAI_API_KEY;
const dogstatsd = new StatsD({
host: process.env.DD_AGENT_HOST || "localhost",
port: parseInt(process.env.DD_DOGSTATSD_PORT || "8125", 10),
prefix: "captcha.",
globalTags: [`env:${process.env.NODE_ENV || "development"}`],
});
async function solveCaptchaWithMetrics(sitekey, pageurl, captchaType = "recaptcha_v2") {
const tags = [`captcha_type:${captchaType}`];
dogstatsd.increment("solve.count", 1, tags);
const startTime = Date.now();
try {
const result = await solveCaptcha(sitekey, pageurl);
const elapsed = (Date.now() - startTime) / 1000;
if (result.solution) {
dogstatsd.increment("solve.success", 1, tags);
dogstatsd.histogram("solve.latency", elapsed, tags);
} else {
dogstatsd.increment("solve.error", 1, [...tags, `error:${result.error}`]);
}
return result;
} catch (err) {
dogstatsd.increment("solve.error", 1, [...tags, `error:${err.message}`]);
throw err;
}
}
async function solveCaptcha(sitekey, pageurl) {
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) {
return { error: submitResp.data.request };
}
const captchaId = submitResp.data.request;
for (let i = 0; i < 60; i++) {
await new Promise((r) => setTimeout(r, 5000));
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) return { solution: pollResp.data.request };
if (pollResp.data.request !== "CAPCHA_NOT_READY") {
return { error: pollResp.data.request };
}
}
return { error: "TIMEOUT" };
}
async function reportBalance() {
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);
dogstatsd.gauge("balance", balance);
return balance;
}
} catch (err) {
console.error("Balance check failed:", err.message);
}
return null;
}
// Report balance every minute
setInterval(reportBalance, 60000);
module.exports = { solveCaptchaWithMetrics, reportBalance };
Datadog Dashboard JSON
Import this JSON template into Datadog to create a CAPTCHA monitoring dashboard:
{
"title": "CaptchaAI Pipeline",
"widgets": [
{
"definition": {
"type": "timeseries",
"title": "Solve Rate (Success vs Error)",
"requests": [
{"q": "sum:captcha.solve.success{*}.as_count()"},
{"q": "sum:captcha.solve.error{*}.as_count()"}
]
}
},
{
"definition": {
"type": "timeseries",
"title": "Solve Latency (p50, p95, p99)",
"requests": [
{"q": "avg:captcha.solve.latency{*}"},
{"q": "percentile:captcha.solve.latency{*},0.95"},
{"q": "percentile:captcha.solve.latency{*},0.99"}
]
}
},
{
"definition": {
"type": "query_value",
"title": "API Balance",
"requests": [{"q": "avg:captcha.balance{*}"}]
}
},
{
"definition": {
"type": "timeseries",
"title": "Queue Depth",
"requests": [{"q": "avg:captcha.queue.depth{*}"}]
}
}
]
}
Alert Definitions
| Alert | Condition | Severity |
|---|---|---|
| Low balance | captcha.balance < 10 |
Warning |
| Critical balance | captcha.balance < 2 |
Critical |
| High error rate | Error rate > 10% over 5 minutes | Warning |
| Latency spike | p95 latency > 120s over 10 minutes | Warning |
| Queue backup | Queue depth > 100 growing for 5 min | Warning |
| Worker down | captcha.worker.active == 0 |
Critical |
# Datadog monitor definition (API create)
- type: metric alert
name: "CaptchaAI Low Balance"
query: "avg(last_5m):avg:captcha.balance{*} < 10"
message: "CaptchaAI balance is low: {{value}}. Top up to avoid solve failures."
tags:
- team:scraping
- service:captcha
Troubleshooting
| Issue | Cause | Fix |
|---|---|---|
| Metrics not appearing | DogStatsD agent not running | Verify DD_AGENT_HOST; check docker ps for agent container |
| Latency histogram empty | No successful solves tracked | Check that statsd.histogram() is called on success path |
| Tags missing | Wrong tag format | Use key:value format; no spaces in tags |
| Duplicate metrics | Multiple reporters running | Ensure only one balance reporter per deployment |
FAQ
Do I need a Datadog agent on every worker?
Run one DogStatsD agent per host. All workers on that host send metrics to the local agent, which forwards to Datadog's intake.
How much does Datadog custom metrics cost?
Datadog charges per custom metric time series. The 7 metrics above with a few tag combinations typically stay within free-tier limits. Check Datadog's pricing for exact costs.
Can I use Datadog APM traces instead of custom metrics?
Yes. Wrap your solve function with ddtrace to get automatic tracing. Custom metrics give you more control over aggregation and alerting, though.
Related Articles
- Build Review Monitoring System Captchaai
- Build Content Change Monitoring Bot Captchaai
- Building Captchaai Usage Dashboard Monitoring
Next Steps
Get observability into your CAPTCHA pipeline — start with a CaptchaAI API key and connect to Datadog.
Related guides:
Discussions (0)
Join the conversation
Sign in to share your opinion.
Sign InNo comments yet.