Tutorials

Batch CAPTCHA Solving Cost Estimation and Budget Alerts

A batch of 10,000 reCAPTCHA v2 tasks costs differently than 10,000 image CAPTCHAs. Without cost tracking, a misconfigured loop can drain your balance before you notice. This guide shows how to estimate costs before a batch starts, track spending during execution, and set alerts when budgets are exceeded.

Cost Per CAPTCHA Type

Pricing varies by CAPTCHA complexity. Use these approximate rates for planning (check CaptchaAI pricing for current rates):

CAPTCHA Type Approximate Cost Notes
Image/Text OCR ~$0.001–0.003 Cheapest; high volume
reCAPTCHA v2 ~$0.002–0.004 Most common
reCAPTCHA v3 ~$0.003–0.005 Score-based
reCAPTCHA Enterprise ~$0.005–0.008 Higher complexity
hCaptcha ~$0.003–0.005 Similar to reCAPTCHA v2
Cloudflare Turnstile ~$0.003–0.005 Token-based
GeeTest v3 ~$0.004–0.006 Multi-step challenge

Python: Cost Estimator and Budget Guard

import requests
import time
from dataclasses import dataclass

API_KEY = "YOUR_API_KEY"
SUBMIT_URL = "https://ocr.captchaai.com/in.php"
RESULT_URL = "https://ocr.captchaai.com/res.php"

# Cost per 1,000 tasks (adjust to current pricing)
COST_PER_1K = {
    "userrecaptcha": 3.00,      # reCAPTCHA v2
    "userrecaptcha_v3": 4.00,   # reCAPTCHA v3
    "turnstile": 3.50,          # Cloudflare Turnstile
    "hcaptcha": 3.50,           # hCaptcha
    "base64": 1.50,             # Image/OCR
    "geetest": 5.00,            # GeeTest
}


@dataclass
class CostEstimate:
    task_count: int
    method: str
    cost_per_task: float
    total_estimated: float
    retry_buffer: float  # Extra for retries
    total_with_buffer: float

    def __str__(self):
        return (
            f"Estimate: {self.task_count} × ${self.cost_per_task:.4f} "
            f"= ${self.total_estimated:.2f} "
            f"(+{self.retry_buffer:.0%} retry buffer = ${self.total_with_buffer:.2f})"
        )


def estimate_cost(task_count, method="userrecaptcha", retry_rate=0.15):
    """Estimate total cost for a batch before starting."""
    per_1k = COST_PER_1K.get(method, 3.00)
    per_task = per_1k / 1000
    base_cost = task_count * per_task
    buffer_cost = base_cost * (1 + retry_rate)

    return CostEstimate(
        task_count=task_count,
        method=method,
        cost_per_task=per_task,
        total_estimated=base_cost,
        retry_buffer=retry_rate,
        total_with_buffer=buffer_cost,
    )


def get_balance():
    """Check current CaptchaAI balance."""
    resp = requests.get(RESULT_URL, params={
        "key": API_KEY, "action": "getbalance", "json": 1,
    }, timeout=10).json()
    return float(resp.get("request", 0))


class BudgetGuard:
    """Track spending and enforce budget limits during batch processing."""

    def __init__(self, budget_limit, method="userrecaptcha", alert_threshold=0.8):
        self.budget_limit = budget_limit
        self.alert_threshold = alert_threshold
        self.per_task = COST_PER_1K.get(method, 3.00) / 1000
        self.tasks_submitted = 0
        self.tasks_solved = 0
        self.tasks_failed = 0
        self.estimated_spent = 0.0
        self.alert_sent = False

    def can_submit(self):
        """Check if budget allows another task."""
        projected = self.estimated_spent + self.per_task
        if projected > self.budget_limit:
            print(f"BUDGET EXCEEDED: ${self.estimated_spent:.2f} / ${self.budget_limit:.2f}")
            return False
        return True

    def record_submit(self):
        """Record a submitted task."""
        self.tasks_submitted += 1
        self.estimated_spent += self.per_task

        # Alert at threshold
        if not self.alert_sent and self.estimated_spent >= self.budget_limit * self.alert_threshold:
            pct = (self.estimated_spent / self.budget_limit) * 100
            print(f"BUDGET ALERT: {pct:.0f}% used (${self.estimated_spent:.2f} / ${self.budget_limit:.2f})")
            self.alert_sent = True

    def record_result(self, solved):
        """Record a task result."""
        if solved:
            self.tasks_solved += 1
        else:
            self.tasks_failed += 1

    def summary(self):
        """Return a spending summary."""
        return {
            "submitted": self.tasks_submitted,
            "solved": self.tasks_solved,
            "failed": self.tasks_failed,
            "estimated_spent": round(self.estimated_spent, 4),
            "budget_limit": self.budget_limit,
            "budget_remaining": round(self.budget_limit - self.estimated_spent, 4),
            "cost_per_solved": round(
                self.estimated_spent / self.tasks_solved, 4
            ) if self.tasks_solved else 0,
        }


def solve_with_budget(tasks, budget_limit, method="userrecaptcha"):
    """Process tasks with budget enforcement."""
    # Pre-flight checks
    estimate = estimate_cost(len(tasks), method)
    print(estimate)

    balance = get_balance()
    print(f"Current balance: ${balance:.2f}")

    if estimate.total_with_buffer > balance:
        print(f"WARNING: Estimated cost ${estimate.total_with_buffer:.2f} exceeds balance ${balance:.2f}")
        return []

    effective_budget = min(budget_limit, balance)
    guard = BudgetGuard(effective_budget, method)

    results = []
    for i, task in enumerate(tasks):
        if not guard.can_submit():
            print(f"Budget limit reached after {i} tasks")
            break

        guard.record_submit()

        try:
            params = {"key": API_KEY, "method": method, "json": 1}
            if method == "userrecaptcha":
                params["googlekey"] = task["sitekey"]
                params["pageurl"] = task["pageurl"]
            elif method == "turnstile":
                params["sitekey"] = task["sitekey"]
                params["pageurl"] = task["pageurl"]

            resp = requests.post(SUBMIT_URL, data=params, timeout=30).json()
            if resp.get("status") != 1:
                guard.record_result(False)
                results.append({"index": i, "status": "failed", "error": resp.get("request")})
                continue

            task_id = resp["request"]
            solved = False
            for _ in range(60):
                time.sleep(5)
                poll = requests.get(RESULT_URL, params={
                    "key": API_KEY, "action": "get",
                    "id": task_id, "json": 1,
                }, timeout=15).json()

                if poll.get("request") == "CAPCHA_NOT_READY":
                    continue
                if poll.get("status") == 1:
                    guard.record_result(True)
                    results.append({"index": i, "status": "solved", "token": poll["request"]})
                    solved = True
                    break

                guard.record_result(False)
                results.append({"index": i, "status": "failed", "error": poll.get("request")})
                break

            if not solved and results[-1]["index"] != i:
                guard.record_result(False)
                results.append({"index": i, "status": "failed", "error": "timeout"})

        except Exception as e:
            guard.record_result(False)
            results.append({"index": i, "status": "failed", "error": str(e)})

    print(f"\nSpending summary: {guard.summary()}")
    return results


# Usage
tasks = [
    {"sitekey": "SITE_KEY", "pageurl": f"https://example.com/page{i}"}
    for i in range(100)
]

# Estimate before running
est = estimate_cost(100, "userrecaptcha")
print(est)
# Estimate: 100 × $0.0030 = $0.30 (+15% retry buffer = $0.35)

# Run with $0.50 budget limit
results = solve_with_budget(tasks, budget_limit=0.50, method="userrecaptcha")

JavaScript: Cost Tracker

const API_KEY = "YOUR_API_KEY";
const RESULT_URL = "https://ocr.captchaai.com/res.php";

const COST_PER_1K = {
  userrecaptcha: 3.0,
  turnstile: 3.5,
  hcaptcha: 3.5,
  base64: 1.5,
};

function estimateCost(taskCount, method = "userrecaptcha", retryRate = 0.15) {
  const perTask = (COST_PER_1K[method] || 3.0) / 1000;
  const base = taskCount * perTask;
  return {
    taskCount,
    perTask: perTask.toFixed(4),
    baseCost: base.toFixed(2),
    withRetries: (base * (1 + retryRate)).toFixed(2),
  };
}

class BudgetTracker {
  constructor(limit, method = "userrecaptcha", alertPct = 0.8) {
    this.limit = limit;
    this.perTask = (COST_PER_1K[method] || 3.0) / 1000;
    this.spent = 0;
    this.alertPct = alertPct;
    this.alertFired = false;
    this.solved = 0;
    this.failed = 0;
  }

  canSubmit() {
    return this.spent + this.perTask <= this.limit;
  }

  recordSubmit() {
    this.spent += this.perTask;
    if (!this.alertFired && this.spent >= this.limit * this.alertPct) {
      console.warn(`BUDGET ALERT: ${((this.spent / this.limit) * 100).toFixed(0)}% used`);
      this.alertFired = true;
    }
  }

  recordResult(success) {
    if (success) this.solved++;
    else this.failed++;
  }

  summary() {
    return {
      spent: `$${this.spent.toFixed(4)}`,
      remaining: `$${(this.limit - this.spent).toFixed(4)}`,
      solved: this.solved,
      failed: this.failed,
      costPerSolved: this.solved ? `$${(this.spent / this.solved).toFixed(4)}` : "N/A",
    };
  }
}

async function checkBalance() {
  const url = `${RESULT_URL}?key=${API_KEY}&action=getbalance&json=1`;
  const resp = await (await fetch(url)).json();
  return parseFloat(resp.request);
}

// Usage
const estimate = estimateCost(500, "userrecaptcha");
console.log("Estimate:", estimate);

const tracker = new BudgetTracker(2.0, "userrecaptcha");
// Use tracker.canSubmit() / tracker.recordSubmit() / tracker.recordResult() during batch processing

Budget Planning Table

Batch Size reCAPTCHA v2 Image/OCR Turnstile With 15% Retry Buffer
100 $0.30 $0.15 $0.35 $0.35–0.40
1,000 $3.00 $1.50 $3.50 $3.45–4.03
10,000 $30.00 $15.00 $35.00 $34.50–40.25
100,000 $300.00 $150.00 $350.00 $345–402

Troubleshooting

Issue Cause Fix
Cost higher than estimated Retry rate exceeds buffer Increase retry buffer to 25–30% for challenging CAPTCHAs
Balance drained unexpectedly No budget guard in place Add BudgetGuard with hard limit before production runs
Cost per solved task too high Many failures not counted Track both submitted and solved counts — optimize failure rate first
Estimate doesn't match actual Using wrong cost-per-1K rate Check current CaptchaAI pricing page and update COST_PER_1K
Alert fires too late Threshold set too high Lower alert_threshold to 0.5 (50%) for tighter budgets

FAQ

How accurate are cost estimates?

Within 10–20% for typical batches. The main variable is retry rate — challenging sites or bad proxies increase retries. Run a small test batch (50–100 tasks) to measure your actual retry rate before committing to large batches.

Should I check balance before every task?

No — balance API calls add latency. Track spending locally with a BudgetGuard and check actual balance every 100–500 tasks or at the start/end of each batch.

How do I set up spending alerts for a team?

Run a scheduled balance check (every hour) that compares current balance to previous. If the delta exceeds a threshold (e.g., $5/hour), trigger a notification via Slack webhook, email, or PagerDuty.

Next Steps

Keep your CAPTCHA solving costs predictable — get your CaptchaAI API key and implement budget tracking from the start.

Related guides:

Discussions (0)

No comments yet.

Related Posts

DevOps & Scaling CaptchaAI Monitoring with Datadog: Metrics and Alerts
Monitor Captcha AI performance with Datadog — custom metrics, dashboards, anomaly detection alerts, and solve rate tracking for CAPTCHA solving pipelines.

Monitor Captcha AI performance with Datadog — custom metrics, dashboards, anomaly detection alerts, and solve...

Automation Python All CAPTCHA Types
Feb 19, 2026
Tutorials Webhook Endpoint Monitoring for CAPTCHA Solve Callbacks
Monitor your Captcha AI callback endpoints — track uptime, response latency, error rates, and set up alerts before missed results impact your pipeline.

Monitor your Captcha AI callback endpoints — track uptime, response latency, error rates, and set up alerts be...

Automation Python All CAPTCHA Types
Mar 12, 2026
DevOps & Scaling CaptchaAI Monitoring with New Relic: APM Integration
Integrate Captcha AI with New Relic APM — custom events, transaction tracing, dashboards, and alert policies for CAPTCHA solving performance.

Integrate Captcha AI with New Relic APM — custom events, transaction tracing, dashboards, and alert policies f...

Automation Python All CAPTCHA Types
Jan 31, 2026
DevOps & Scaling Building Custom CaptchaAI Alerts with PagerDuty
Integrate Captcha AI with Pager Duty for incident management — trigger alerts on low balance, high error rates, and pipeline failures with escalation policies.

Integrate Captcha AI with Pager Duty for incident management — trigger alerts on low balance, high error rates...

Automation Python All CAPTCHA Types
Jan 15, 2026
DevOps & Scaling Grafana Dashboard Templates for CaptchaAI Metrics
Ready-to-import Grafana dashboard templates for Captcha AI — solve rate panels, latency histograms, balance gauges, and queue depth monitors.

Ready-to-import Grafana dashboard templates for Captcha AI — solve rate panels, latency histograms, balance ga...

Automation Python All CAPTCHA Types
Feb 21, 2026
API Tutorials Building a CaptchaAI Usage Dashboard and Monitoring
Build a real-time Captcha AI usage dashboard.

Build a real-time Captcha AI usage dashboard. Track solve rates, spending, success/failure ratios, and respons...

Automation Python All CAPTCHA Types
Mar 11, 2026
Reference CAPTCHA Solve Rate SLI/SLO: How to Define and Monitor
Define SLIs and SLOs for CAPTCHA solving — success rate, latency percentiles, availability targets, error budgets, and burn rate alerting with Captcha AI.

Define SLIs and SLOs for CAPTCHA solving — success rate, latency percentiles, availability targets, error budg...

Automation Python All CAPTCHA Types
Mar 05, 2026
Tutorials Discord Webhook Alerts for CAPTCHA Pipeline Status
Send CAPTCHA pipeline alerts to Discord — webhook integration for balance warnings, error spikes, queue status, and daily summary reports with Captcha AI.

Send CAPTCHA pipeline alerts to Discord — webhook integration for balance warnings, error spikes, queue status...

Automation Python All CAPTCHA Types
Tutorials Structured Logging for CAPTCHA Operations
Add structured JSON logging to your CAPTCHA solving workflows — track task IDs, solve times, errors, and costs with Python and Node.js.

Add structured JSON logging to your CAPTCHA solving workflows — track task IDs, solve times, errors, and costs...

Automation Python All CAPTCHA Types
Jan 30, 2026
Tutorials Pytest Fixtures for CaptchaAI API Testing
Build reusable pytest fixtures to test CAPTCHA-solving workflows with Captcha AI.

Build reusable pytest fixtures to test CAPTCHA-solving workflows with Captcha AI. Covers mocking, live integra...

Automation Python reCAPTCHA v2
Apr 08, 2026
Tutorials Using Fiddler to Inspect CaptchaAI API Traffic
How to use Fiddler Everywhere and Fiddler Classic to capture, inspect, and debug Captcha AI API requests and responses — filters, breakpoints, and replay for tr...

How to use Fiddler Everywhere and Fiddler Classic to capture, inspect, and debug Captcha AI API requests and r...

Automation Python All CAPTCHA Types
Mar 05, 2026