Tutorials

Verbindungs-Keep-Alive und HTTP/2 für schnellere CAPTCHA-API-Aufrufe

Der größte Hebel für Ihre CaptchaAI-Integration ist selten die Lösungszeit selbst – es ist der Verbindungsaufbau davor. Jede Lösung besteht aus mehreren HTTP-Anfragen: eine Übermittlung an in.php und mehrere Statusabfragen an res.php. Baut Ihr Client für jede dieser Anfragen eine neue Verbindung auf, zahlt er jedes Mal für TCP-Handshake und TLS-Aushandlung – typischerweise 100–300 ms pro Verbindung. Mit Keep-Alive und HTTP/2 halten Sie eine Verbindung offen und wiederverwenden sie über Dutzende Lösungen hinweg. Dieser Leitfaden zeigt die konkrete Umsetzung in Python und JavaScript mit CaptchaAI.

Warum Verbindungswiederverwendung die Latenz senkt

Der Overhead entsteht nicht bei der eigentlichen CAPTCHA-Lösung, sondern beim wiederholten Verbindungsaufbau. Eine typische reCAPTCHA-v2-Lösung besteht aus einer Übermittlung an in.php und 4–6 Statusabfragen an res.php – zusammen 5–7 HTTP-Anfragen. Ob jede davon einen frischen Handshake bezahlt oder nicht, entscheidet über den gesamten Overhead:

Szenario Verbindungsaufbau Overhead pro Lösung
Ohne Keep-Alive 5 × (TCP-Handshake ~50 ms + TLS ~100 ms) 750 ms
Mit Keep-Alive 1 × (TCP + TLS) + 4 × (~5 ms Wiederverwendung) 170 ms

Ersparnis: ~580 ms pro Lösung. Bei 10.000 Lösungen pro Tag summiert sich das auf rund 1,6 Stunden eingesparte Latenz – Zeit, die Ihre Worker stattdessen für die nächste Lösung nutzen. Je höher Ihr Durchsatz, desto stärker fällt der Effekt ins Gewicht.

HTTP/2 oder HTTP/1.1 Keep-Alive – was wann?

Bevor Sie den Client bauen, sollten Sie den Mechanismus wählen. Beide Ansätze wiederverwenden Verbindungen, unterscheiden sich aber im Umgang mit Parallelität. HTTP/1.1 Keep-Alive verarbeitet Anfragen sequenziell über eine Verbindung; HTTP/2 multiplext viele Streams über dieselbe Verbindung.

Funktion HTTP/1.1 Keep-Alive HTTP/2
Verbindungswiederverwendung Ja (sequenziell) Ja (multiplext)
Gleichzeitige Streams 1 pro Verbindung über 100 pro Verbindung
Header-Komprimierung Nein HPACK-Komprimierung
Latenzreduktion ~60 % ~70 %
Browser-Unterstützung nötig Nein Nein (API-Aufrufe)
Am besten für Sequenzielle Lösungen Parallele Lösungen

Faustregel: Lösen Sie ein CAPTCHA nach dem anderen, genügt HTTP/1.1 Keep-Alive vollkommen. Erst bei echter Parallelität – mehrere Lösungen gleichzeitig in Bearbeitung – zahlt sich HTTP/2-Multiplexing zusätzlich aus, weil alle Streams eine einzige Verbindung teilen.

Python: Keep-Alive mit requests.Session

Die requests-Bibliothek aktiviert Keep-Alive automatisch, sobald Sie ein Session-Objekt statt einzelner requests.get-Aufrufe verwenden. Der Schlüssel ist, die Session einmal anzulegen und über alle Lösungen hinweg wiederzuverwenden – nicht pro Anfrage neu zu erstellen:

# keepalive_solver.py
import os
import time
import requests

API_KEY = os.environ.get("CAPTCHAAI_KEY", "YOUR_API_KEY")

# Create a session — reuses TCP connections across requests
session = requests.Session()
session.headers.update({"Connection": "keep-alive"})

def solve_captcha(sitekey, pageurl):
    """Solve reCAPTCHA v2 using a persistent connection."""
    # Submit — uses existing connection if available
    resp = session.get("https://ocr.captchaai.com/in.php", params={
        "key": API_KEY,
        "method": "userrecaptcha",
        "googlekey": sitekey,
        "pageurl": pageurl,
        "json": "1",
    })
    result = resp.json()

    if result.get("status") != 1:
        raise Exception(f"Submit failed: {result.get('request')}")

    task_id = result["request"]

    # Poll — reuses the same connection
    time.sleep(15)
    for _ in range(25):
        poll = session.get("https://ocr.captchaai.com/res.php", params={
            "key": API_KEY,
            "action": "get",
            "id": task_id,
            "json": "1",
        })
        poll_result = poll.json()

        if poll_result.get("status") == 1:
            return poll_result["request"]
        if poll_result.get("request") != "CAPCHA_NOT_READY":
            raise Exception(f"Error: {poll_result.get('request')}")

        time.sleep(5)

    raise Exception("Timeout")

# Solve multiple CAPTCHAs reusing the same connection
for i in range(5):
    token = solve_captcha(
        "6Le-wvkSAAAAAPBMRTvw0Q4Muexq9bi0DJwx_mJ-",
        "https://www.google.com/recaptcha/api2/demo"
    )
    print(f"Solve {i+1}: {token[:30]}...")

Python: HTTP/2 mit httpx

requests unterstützt kein HTTP/2. Wenn Sie mehrere CAPTCHAs parallel lösen, spielt httpx seine Stärke aus: Über eine einzige HTTP/2-Verbindung laufen viele Streams gleichzeitig (Multiplexing), sodass Sie sich nicht um mehrere offene Verbindungen kümmern müssen:

# http2_solver.py
import os
import time
import httpx

API_KEY = os.environ.get("CAPTCHAAI_KEY", "YOUR_API_KEY")
BASE_URL = "https://ocr.captchaai.com"

# HTTP/2 client with connection pooling
client = httpx.Client(http2=True, timeout=30.0)

def solve_captcha(sitekey, pageurl):
    """Solve using HTTP/2 multiplexed connections."""
    resp = client.get(f"{BASE_URL}/in.php", params={
        "key": API_KEY,
        "method": "userrecaptcha",
        "googlekey": sitekey,
        "pageurl": pageurl,
        "json": "1",
    })
    result = resp.json()

    if result.get("status") != 1:
        raise Exception(f"Submit failed: {result.get('request')}")

    task_id = result["request"]
    time.sleep(15)

    for _ in range(25):
        poll = client.get(f"{BASE_URL}/res.php", params={
            "key": API_KEY, "action": "get",
            "id": task_id, "json": "1",
        })
        poll_result = poll.json()

        if poll_result.get("status") == 1:
            return poll_result["request"]
        if poll_result.get("request") != "CAPCHA_NOT_READY":
            raise Exception(f"Error: {poll_result.get('request')}")

        time.sleep(5)

    raise Exception("Timeout")

# Multiple solves over a single HTTP/2 connection
for i in range(5):
    token = solve_captcha(
        "6Le-wvkSAAAAAPBMRTvw0Q4Muexq9bi0DJwx_mJ-",
        "https://www.google.com/recaptcha/api2/demo"
    )
    print(f"Solve {i+1}: {token[:30]}...")

client.close()

JavaScript: Axios-Instanz mit Keep-Alive-Agent

In Node.js aktivieren Sie Keep-Alive über explizite http.Agent- und https.Agent-Instanzen mit keepAlive: true. Diese Agents binden Sie an eine wiederverwendbare Axios-Instanz. Über maxSockets begrenzen Sie zugleich die Poolgröße:

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

const API_KEY = process.env.CAPTCHAAI_KEY || 'YOUR_API_KEY';

// Create agents with keep-alive enabled
const httpAgent = new http.Agent({ keepAlive: true, maxSockets: 10 });
const httpsAgent = new https.Agent({ keepAlive: true, maxSockets: 10 });

// Axios instance with persistent connections
const api = axios.create({
  baseURL: 'https://ocr.captchaai.com',
  httpAgent,
  httpsAgent,
  timeout: 30000,
});

async function solveCaptcha(sitekey, pageurl) {
  // Submit — reuses connection
  const submit = await api.get('/in.php', {
    params: {
      key: API_KEY, method: 'userrecaptcha',
      googlekey: sitekey, pageurl, json: '1',
    },
  });

  if (submit.data.status !== 1) throw new Error(submit.data.request);
  const taskId = submit.data.request;

  // Poll — reuses same connection
  await new Promise(r => setTimeout(r, 15000));
  for (let i = 0; i < 25; i++) {
    const poll = await api.get('/res.php', {
      params: { key: API_KEY, action: 'get', id: taskId, json: '1' },
    });

    if (poll.data.status === 1) return poll.data.request;
    if (poll.data.request !== 'CAPCHA_NOT_READY') throw new Error(poll.data.request);
    await new Promise(r => setTimeout(r, 5000));
  }
  throw new Error('Timeout');
}

(async () => {
  for (let i = 0; i < 5; i++) {
    const token = await solveCaptcha(
      '6Le-wvkSAAAAAPBMRTvw0Q4Muexq9bi0DJwx_mJ-',
      'https://www.google.com/recaptcha/api2/demo'
    );
    console.log(`Solve ${i + 1}: ${token.slice(0, 30)}...`);
  }

  // Clean up agents
  httpAgent.destroy();
  httpsAgent.destroy();
})();

Verbindungspool richtig dimensionieren

Die Poolgröße sollte zu Ihrer tatsächlichen Parallelität passen. Diese ist bei CaptchaAI durch Ihre Thread-Zuteilung begrenzt: Der ADVANCE-Plan (90 $/Monat, 50 Threads) erlaubt etwa 50 gleichzeitige Lösungen, der PREMIUM-Plan (170 $/Monat, 100 Threads) entsprechend mehr. Da CaptchaAI Thread-basiert abrechnet – pro gleichzeitiger Lösung, nicht pro CAPTCHA – ist Ihre Thread-Zahl die natürliche Obergrenze für die Poolgröße.

Gleichzeitige Lösungen Empfohlene Poolgröße
1–5 5 Verbindungen
5–20 10 Verbindungen
20–50 25 Verbindungen
50–100 50 Verbindungen
über 100 HTTP/2 nutzen (1 Verbindung)

Zu große Pools verschwenden Speicher und offene Sockets, ohne den Durchsatz zu erhöhen. Zu kleine Pools erzwingen ständig neue Verbindungen und machen die Keep-Alive-Vorteile wieder zunichte.

Praxisbeispiel: Worker in einem deutschen Rechenzentrum

Angenommen, Ihre Scraping-Worker laufen auf einem Hetzner- oder netcup-Server in Nürnberg und sprechen ocr.captchaai.com an. Bei einem Batch von 30 parallelen reCAPTCHA-v2-Lösungen dominiert ohne Keep-Alive der wiederholte TLS-Handshake die Antwortzeit. Setzen Sie einen httpx-Client mit HTTP/2 und einem Pool von 25 Verbindungen ein, laufen die Statusabfragen über bestehende Streams – der spürbare Latenzanteil verschiebt sich vollständig auf die reine Lösungszeit. Denselben Effekt erreichen Sie in einer GitLab-CI-Pipeline, in der ein Test-Job viele Formulare hintereinander gegen eine Staging-Umgebung prüft.

Typische Probleme und Lösungen

Problem Ursache Lösung
Verbindung wird trotz Keep-Alive zwischen Abfragen getrennt Server- oder Proxy-Timeout ist kürzer als das Polling-Intervall Keep-Alive-Timeout im Client auf über 30 s setzen und Connection: keep-alive explizit senden
Keine spürbare Verbesserung Session wird pro Anfrage neu erstellt statt wiederverwendet Das Session- bzw. Client-Objekt einmal anlegen und über alle Lösungen hinweg nutzen
Connection refused unter Last Pool erschöpft (maxSockets zu niedrig) maxSockets erhöhen oder die Parallelität senken
HTTP/2 wird nicht ausgehandelt Client oder Bibliothek unterstützt kein h2 httpx (Python) mit http2=True verwenden oder auf HTTP/1.1 Keep-Alive zurückfallen

Fazit

Spürbare Latenz sparen Sie nicht durch einen schnelleren Solver, sondern indem Sie den Verbindungsaufbau nur einmal bezahlen. Legen Sie ein Session- bzw. Client-Objekt einmal an, verwenden Sie es über alle Lösungen hinweg und dimensionieren Sie den Pool nach Ihrer Thread-Zuteilung – dann verschiebt sich der spürbare Zeitanteil vollständig auf die reine Lösungszeit. Bei echter Parallelität nehmen Sie HTTP/2, sonst genügt HTTP/1.1 Keep-Alive.

Häufige Fragen

Wie viel Latenz spart Keep-Alive pro Lösung wirklich?

Etwa 580 ms bei einer typischen reCAPTCHA-v2-Lösung mit 5–7 Anfragen. Der Wert steigt mit der Zahl der Statusabfragen: Je mehr Abfragen, desto häufiger wird die bestehende Verbindung wiederverwendet, statt jedes Mal einen neuen TCP- und TLS-Handshake zu bezahlen.

Brauche ich HTTP/2, oder reicht Keep-Alive?

Für sequenzielles Lösen reicht HTTP/1.1 Keep-Alive. HTTP/2 lohnt sich erst, wenn Sie viele CAPTCHAs gleichzeitig in Bearbeitung haben – dann teilen sich alle parallelen Streams eine einzige Verbindung, was Speicher und Sockets spart.

Wie groß sollte mein Verbindungspool sein?

Ungefähr so groß wie Ihre gleichzeitige Lösungslast, begrenzt durch Ihre Thread-Zuteilung im CaptchaAI-Plan. 25 Verbindungen decken 20–50 parallele Lösungen ab; ab 100 gleichzeitigen Lösungen ist eine einzige HTTP/2-Verbindung meist effizienter als ein großer HTTP/1.1-Pool.

Muss ich die Session zwischen einzelnen Batches schließen?

Nein. Lassen Sie die Session bei periodischen Lösungen geöffnet und schließen Sie sie erst beim Herunterfahren der Anwendung. Jedes Schließen und Neuöffnen verwirft die wiederverwendbare Verbindung und macht den Keep-Alive-Vorteil zunichte.


Verwandte Leitfäden

Kommentare sind für diesen Artikel deaktiviert.