Tutorials

CAPTCHA-Lösungsdurchsatz: So verarbeiten Sie 10.000 Aufgaben pro Stunde

Hoher Durchsatz beim CAPTCHA-Lösen ist keine Frage der Geschwindigkeit, sondern der Parallelität. Ob CaptchaAI ein einzelnes reCAPTCHA v2 in 12 oder 15 Sekunden löst, ändert am Stundenwert wenig – entscheidend ist, wie viele Lösungen gleichzeitig laufen. Für 10.000 Aufgaben pro Stunde genügen rund 42 parallele Anfragen. Dieser Leitfaden zeigt die Rechnung dahinter, eine einsatzfertige asynchrone Pipeline in Python und Node.js sowie die Stellschrauben, mit denen Sie diesen Durchsatz stabil halten.

Die Rechnung: wie viele Lösungen gleichzeitig?

Rechnen wir mit einer medianen Lösungszeit von 15 Sekunden für reCAPTCHA v2:

  • Sequentiell: 3.600 s / 15 s = 240 Lösungen pro Stunde
  • Für 10.000 pro Stunde: durchgehend rund 42 gleichzeitige Lösungen im Flug

Der Kern: Sie warten nicht darauf, dass die API schneller wird. Sie überlappen so viele Anfragen, dass in jedem 15-Sekunden-Fenster 42 Lösungen fertig werden. Aus 240 pro Stunde werden so über 10.000 – bei identischer Lösungszeit, allein durch Parallelität.

Architektur der Pipeline

Die Pipeline besteht aus vier Bausteinen, die über Warteschlangen voneinander entkoppelt sind:

┌──────────┐     ┌────────────┐     ┌─────────────┐     ┌──────────┐
│  Task     │────▶│  Submit    │────▶│  CaptchaAI  │────▶│  Result  │
│  Queue    │     │  Workers   │     │  API        │     │  Store   │
│  (Redis)  │     │  (async)   │     │             │     │  (DB)    │
└──────────┘     └────────────┘     └─────────────┘     └──────────┘
                       │                    ▲
                       │    ┌──────────┐    │
                       └───▶│  Poll    │────┘
                            │  Workers │
                            └──────────┘

Die vier Komponenten im Überblick:

Komponente Aufgabe
Aufgabenwarteschlange hält offene CAPTCHA-Aufgaben mit Sitekeys und URLs bereit; Redis eignet sich dafür gut
Submit-Worker senden die Aufgaben gleichzeitig an die CaptchaAI-API
Poll-Worker fragen die Ergebnisse in optimierten Abständen ab
Ergebnisspeicher legt die Token ab, sobald sie eintreffen

Der Vorteil dieser Trennung: Submit und Polling skalieren unabhängig voneinander, und ein Ausfall der Datenbank blockiert nicht das Einreichen neuer Aufgaben.

Python: asynchrone Lösungs-Pipeline

Die folgende Implementierung nutzt asyncio und aiohttp. Ein Semaphore begrenzt die Zahl gleichzeitiger Lösungen, eine gemeinsame Session hält die Verbindungen offen (Connection-Pooling) und asyncio.gather verarbeitet den Stapel nebenläufig:

# high_throughput_solver.py
import os
import asyncio
import time
import aiohttp

API_KEY = os.environ.get("CAPTCHAAI_KEY", "YOUR_API_KEY")
BASE_URL = "https://ocr.captchaai.com"
MAX_CONCURRENT = 50  # Max simultaneous solves
POLL_INTERVAL = 5    # Seconds between polls
INITIAL_WAIT = 12    # Seconds before first poll

semaphore = asyncio.Semaphore(MAX_CONCURRENT)
stats = {"submitted": 0, "solved": 0, "failed": 0, "start": 0}

async def solve_one(session, sitekey, pageurl, task_num):
    """Submit and poll a single CAPTCHA."""
    async with semaphore:
        try:
            # Submit
            async with session.get(f"{BASE_URL}/in.php", params={
                "key": API_KEY, "method": "userrecaptcha",
                "googlekey": sitekey, "pageurl": pageurl, "json": "1",
            }) as resp:
                result = await resp.json(content_type=None)

            if result.get("status") != 1:
                stats["failed"] += 1
                return None

            stats["submitted"] += 1
            task_id = result["request"]

            # Wait before first poll
            await asyncio.sleep(INITIAL_WAIT)

            # Poll
            for _ in range(25):
                async with session.get(f"{BASE_URL}/res.php", params={
                    "key": API_KEY, "action": "get",
                    "id": task_id, "json": "1",
                }) as resp:
                    poll_result = await resp.json(content_type=None)

                if poll_result.get("status") == 1:
                    stats["solved"] += 1
                    return poll_result["request"]

                if poll_result.get("request") != "CAPCHA_NOT_READY":
                    stats["failed"] += 1
                    return None

                await asyncio.sleep(POLL_INTERVAL)

            stats["failed"] += 1
            return None

        except Exception as e:
            stats["failed"] += 1
            return None

async def run_batch(tasks):
    """Process a batch of CAPTCHA tasks concurrently."""
    connector = aiohttp.TCPConnector(
        limit=MAX_CONCURRENT,
        keepalive_timeout=60,
    )
    async with aiohttp.ClientSession(connector=connector) as session:
        coros = [
            solve_one(session, task["sitekey"], task["pageurl"], i)
            for i, task in enumerate(tasks)
        ]
        results = await asyncio.gather(*coros)
    return results

async def main():
    # Generate test tasks (replace with your task source)
    tasks = [
        {
            "sitekey": "6Le-wvkSAAAAAPBMRTvw0Q4Muexq9bi0DJwx_mJ-",
            "pageurl": "https://www.google.com/recaptcha/api2/demo",
        }
        for _ in range(100)  # Start with 100 tasks
    ]

    stats["start"] = time.time()
    print(f"Processing {len(tasks)} tasks with {MAX_CONCURRENT} concurrent workers")

    results = await run_batch(tasks)
    elapsed = time.time() - stats["start"]

    print(f"\nCompleted in {elapsed:.0f}s")
    print(f"Submitted: {stats['submitted']}")
    print(f"Solved: {stats['solved']}")
    print(f"Failed: {stats['failed']}")
    print(f"Throughput: {stats['solved'] / (elapsed / 3600):.0f} solves/hour")

asyncio.run(main())

Node.js: gleichzeitige Pipeline

Dasselbe Muster in Node.js, hier mit axios und einem HTTPS-Agent, der Keep-Alive-Verbindungen wiederverwendet. Statt eines Semaphores steuert eine Set-basierte Drossel, wie viele Anfragen gleichzeitig laufen:

// high_throughput_solver.js
const axios = require('axios');
const https = require('https');

const API_KEY = process.env.CAPTCHAAI_KEY || 'YOUR_API_KEY';
const BASE = 'https://ocr.captchaai.com';
const MAX_CONCURRENT = 50;

const agent = new https.Agent({ keepAlive: true, maxSockets: MAX_CONCURRENT });
const api = axios.create({ baseURL: BASE, httpsAgent: agent, timeout: 30000 });

const stats = { submitted: 0, solved: 0, failed: 0 };

async function solveOne(sitekey, pageurl) {
  try {
    const submit = await api.get('/in.php', {
      params: { key: API_KEY, method: 'userrecaptcha', googlekey: sitekey, pageurl, json: '1' },
    });
    if (submit.data.status !== 1) { stats.failed++; return null; }
    stats.submitted++;

    await new Promise(r => setTimeout(r, 12000));

    for (let i = 0; i < 25; i++) {
      const poll = await api.get('/res.php', {
        params: { key: API_KEY, action: 'get', id: submit.data.request, json: '1' },
      });
      if (poll.data.status === 1) { stats.solved++; return poll.data.request; }
      if (poll.data.request !== 'CAPCHA_NOT_READY') { stats.failed++; return null; }
      await new Promise(r => setTimeout(r, 5000));
    }
    stats.failed++;
    return null;
  } catch { stats.failed++; return null; }
}

async function runWithConcurrency(tasks, limit) {
  const results = [];
  const executing = new Set();

  for (const task of tasks) {
    const p = solveOne(task.sitekey, task.pageurl).then(r => {
      executing.delete(p);
      return r;
    });
    executing.add(p);
    results.push(p);

    if (executing.size >= limit) {
      await Promise.race(executing);
    }
  }
  return Promise.all(results);
}

(async () => {
  const tasks = Array.from({ length: 100 }, () => ({
    sitekey: '6Le-wvkSAAAAAPBMRTvw0Q4Muexq9bi0DJwx_mJ-',
    pageurl: 'https://www.google.com/recaptcha/api2/demo',
  }));

  const start = Date.now();
  console.log(`Processing ${tasks.length} tasks, ${MAX_CONCURRENT} concurrent`);

  await runWithConcurrency(tasks, MAX_CONCURRENT);
  const elapsed = (Date.now() - start) / 1000;

  console.log(`\nDone in ${elapsed.toFixed(0)}s`);
  console.log(`Solved: ${stats.solved}, Failed: ${stats.failed}`);
  console.log(`Throughput: ${(stats.solved / (elapsed / 3600)).toFixed(0)} solves/hour`);

  agent.destroy();
})();

Hinweis: Ein Token läuft nach rund 120 Sekunden ab. Lösen Sie es unmittelbar vor der Übermittlung und halten Sie die Zeit zwischen Lösung und Einreichung kurz – sonst wird es beim Zielsystem abgelehnt.

Threads richtig dimensionieren für hohen Durchsatz

CaptchaAI rechnet pro Thread ab – nicht pro Lösung. Ein Thread ist eine laufende CAPTCHA-Lösung; sobald sie fertig ist, nimmt derselbe Thread die nächste Aufgabe. Für die rund 42 parallelen Lösungen aus der Rechnung oben brauchen Sie also mindestens 42 Threads:

  • ADVANCE (90 $/Monat, 50 Threads) deckt die 42 parallelen Lösungen mit etwas Reserve ab – und passt genau zum MAX_CONCURRENT-Wert von 50 im Code oben.
  • PREMIUM (170 $/Monat, 100 Threads) gibt Ihnen Luft für Lastspitzen oder ein aggressiveres Tuning in Richtung 18.000 pro Stunde.

Jeder Tarif enthält unbegrenzte Lösungen pro Thread; es gibt keine Tageslimits und keine Aufschläge nach CAPTCHA-Typ. Der Durchsatz wird allein durch die Lösungszeit pro Typ und Ihre Thread-Zahl begrenzt. Die Preise verstehen sich in US-Dollar.

Parameter feinjustieren

Parameter Konservativ Ausgewogen Aggressiv
MAX_CONCURRENT 20 50 100
INITIAL_WAIT 15 s 12 s 10 s
POLL_INTERVAL 7 s 5 s 3 s
MAX_POLL_ATTEMPTS 30 25 20
Erwarteter Durchsatz ~4.800/h ~10.000/h ~18.000/h

Beginnen Sie konservativ und erhöhen Sie MAX_CONCURRENT schrittweise, bis Erfolgsquote oder Fehlerrate kippen. INITIAL_WAIT orientiert sich an der medianen Lösungszeit des jeweiligen CAPTCHA-Typs: zu kurz, und die ersten Abfragen laufen ins Leere; zu lang, und Sie verschenken Durchsatz.

Durchsatz überwachen

Behalten Sie diese Kennzahlen in Echtzeit im Blick:

Kennzahl Zielwert Maßnahme bei Abweichung
Lösungen pro Minute ~167 für 10.000 pro Stunde fällt der Wert, die Parallelität erhöhen
Fehlerrate unter 5 % bei Spitzen die Parallelität senken
Warteschlangentiefe stabil wächst sie, mehr Worker; bleibt sie leer, sind Sie überdimensioniert
P90-Lösungszeit stabil steigt sie, drosselt die API möglicherweise – Last kurz senken

Fehlerbehebung

Problem Ursache Lösung
Token entsteht, wird aber vom Ziel abgelehnt sitekey, pageurl oder Session-Kontext passen nicht zusammen Erfassen Sie die Parameter erneut und verwenden Sie das Token in derselben Browser- oder HTTP-Sitzung
Das Polling läuft ins Timeout Intervall, Wartezeit oder Fehlerbehandlung sind zu eng gesetzt Fragen Sie alle 5–10 Sekunden ab, trennen Sie das Timeout von echten Fehlercodes und protokollieren Sie die Ursache
Beispiel läuft lokal, aber nicht im Workflow Callback, Formularfeld oder das Einfügen des Tokens fehlt in der echten Zielkette Prüfen Sie den genauen Übergabepfad vom Solver bis zur finalen Zielanfrage
Die Fehlerrate steigt über 10 % Zu hohe Parallelität oder schlechte Proxys Senken Sie MAX_CONCURRENT und prüfen Sie die Qualität Ihrer Proxys

Häufige Fragen

Wie viele Threads brauche ich für 10.000 Lösungen pro Stunde?

Rund 42 parallele Lösungen, also mindestens 42 Threads. ADVANCE (90 $/Monat, 50 Threads) reicht dafür aus; PREMIUM (170 $/Monat, 100 Threads) lässt Luft für Lastspitzen. Da jeder Thread unbegrenzte Lösungen enthält, zahlen Sie nicht pro einzelnem CAPTCHA.

Welche CAPTCHA-Typen kann ich in dieser Pipeline verarbeiten?

Die Pipeline ist typ-agnostisch. CaptchaAI löst reCAPTCHA v2 und v3, Cloudflare Turnstile und Challenge, GeeTest v3 sowie Bild- und Grid-CAPTCHAs; CaptchaFox, Friendly Captcha und Lemin befinden sich in der Beta. Sie passen lediglich das method-Feld und die typspezifischen Parameter an.

Wie verteile ich die Last auf mehrere Server?

Nutzen Sie eine gemeinsame Warteschlange (Redis, RabbitMQ) und starten Sie das Worker-Skript auf mehreren Maschinen – etwa auf günstigen VPS bei Hetzner oder netcup, ausgerollt über GitLab CI. Jeder Worker zieht seine Aufgaben unabhängig und schreibt in denselben Ergebnisspeicher.

Was ist bei Web-Scraping in großem Umfang rechtlich zu beachten?

Das hängt von Ihren Daten ab. IP-Adressen und personenbezogene Inhalte fallen unter die DSGVO; prüfen Sie Rechtsgrundlage und Datenflüsse, bevor Sie in großem Umfang extrahieren. CaptchaAI löst nur die CAPTCHA-Abfrage – für die Rechtmäßigkeit Ihres Workflows sind Sie selbst verantwortlich.

Kann ich den Durchsatz über 10.000 pro Stunde hinaus steigern?

Ja. Erhöhen Sie MAX_CONCURRENT und die Thread-Zahl gemeinsam – mit der aggressiven Konfiguration und PREMIUM (170 $/Monat, 100 Threads) sind rund 18.000 pro Stunde realistisch. Beobachten Sie dabei Fehlerrate und P90-Lösungszeit, um den optimalen Betriebspunkt zu finden.


Verwandte Leitfäden

Kommentare sind für diesen Artikel deaktiviert.