La lenteur de vos appels à une API de résolution CAPTCHA ne vient presque jamais du solveur : elle vient du temps passé à rouvrir une connexion à chaque requête. Sans réutilisation, chaque envoi et chaque interrogation repaie un établissement TCP et une négociation TLS complets — 100 à 300 ms à chaque fois. Deux leviers suppriment ce gaspillage : les connexions persistantes (keep-alive) et le multiplexage HTTP/2, activés côté client avec CaptchaAI en Python comme en Node.js.
Pourquoi l'ouverture de connexion coûte si cher
Une résolution reCAPTCHA v2 n'est pas une requête isolée : elle enchaîne un envoi vers in.php puis quatre à six interrogations vers res.php, soit cinq à sept requêtes HTTP pour un seul token. Le coût ne tient pas dans les données transférées, mais dans l'ouverture de connexion — voici l'écart, poignées de main TCP/TLS comprises :
| Scénario | Connexions ouvertes | Surcharge réseau |
|---|---|---|
| Sans keep-alive | 5 (une par requête) | ~750 ms |
| Avec keep-alive | 1 réutilisée | ~170 ms |
Soit environ 580 ms gagnées par résolution. À 10 000 résolutions/jour, cela fait près de 1,6 heure de latence en moins — et, pour un worker qui interroge l'API en continu depuis Paris (OVHcloud, Scaleway, région AWS eu-west-3), autant de débit gagné sans threads supplémentaires.
HTTP/2 ou HTTP/1.1 keep-alive : lequel choisir
Avant d'écrire une ligne de code, tranchez le protocole. Le keep-alive HTTP/1.1 réutilise une connexion mais traite les requêtes en file, ce qui suffit pour des résolutions séquentielles ; HTTP/2 les multiplexe sur une seule connexion et prend l'avantage dès que vous résolvez en parallèle.
| Critère | HTTP/1.1 keep-alive | HTTP/2 |
|---|---|---|
| Réutilisation de connexion | Oui (séquentielle) | Oui (multiplexée) |
| Flux simultanés | 1 par connexion | Jusqu'à 100+ par connexion |
| Compression des en-têtes | Non | Oui (HPACK) |
| Support navigateur requis | Non | Non (appels API) |
| Cas d'usage idéal | Résolutions séquentielles | Résolutions en parallèle |
Python : réutiliser la connexion avec requests.Session
- Instanciez un objet
Sessionplutôt que d'appeler les fonctions de module derequests. - Le premier appel ouvre la connexion ; les suivants la réutilisent, keep-alive activé par défaut.
# 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 avec httpx
# 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()
Node.js : un agent Axios avec keep-alive
- Créez des agents
httpethttpsaveckeepAlive: true. - Attachez-les à une instance Axios réutilisée pour tous les appels — côté Node.js, le keep-alive n'est pas actif par défaut.
// 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();
})();
Dimensionner le pool, sans surdimensionner
| Résolutions simultanées | Taille de pool conseillée |
|---|---|
| 1–5 | 5 connexions |
| 5–20 | 10 connexions |
| 20–50 | 25 connexions |
| 50–100 | 50 connexions |
| 100+ | Passez à HTTP/2 (1 connexion) |
Un pool trop grand laisse dormir des connexions et gaspille de la mémoire ; un pool trop petit rouvre sans cesse et annule le gain du keep-alive. Un worker Scaleway qui résout trente CAPTCHA en parallèle tourne bien avec dix connexions ; au-delà de cent en simultané, une connexion HTTP/2 unique remplace tout le pool.
Dépannage
| Problème | Cause | Correctif |
|---|---|---|
| Connexions fermées entre deux interrogations | Timeout côté serveur ou proxy | Portez le timeout keep-alive au-delà de 30 s dans la configuration du client |
| Aucun gain de performance | Le keep-alive est déjà actif (par défaut dans certaines bibliothèques) | Vérifiez avec un outil de surveillance réseau |
| Erreurs « connection refused » | Pool épuisé | Augmentez maxSockets ou réduisez la simultanéité |
| HTTP/2 non négocié | Le serveur n'annonce pas h2 | Revenez au keep-alive HTTP/1.1 |
FAQ
Le keep-alive accélère-t-il la résolution du CAPTCHA elle-même ?
Non. Le temps de résolution dépend du solveur, pas de votre client HTTP. Le keep-alive et HTTP/2 ne suppriment que la surcharge réseau des allers-retours (envoi et interrogations) — c'est cela que vous optimisez, pas la résolution elle-même.
Combien de connexions faut-il garder ouvertes ?
Alignez le pool sur votre simultanéité réelle :
- 5 résolutions en parallèle → 5 connexions
- 20 et au-delà → une dizaine de connexions
- 100+ → une seule connexion HTTP/2, qui multiplexe tout
Que faire si une connexion tombe en pleine interrogation du résultat ?
Le client rouvre une connexion à la requête suivante : vous perdez le gain sur cette résolution, pas le résultat. Si les coupures se répètent, augmentez le timeout keep-alive et enveloppez vos appels dans une nouvelle tentative.
Pour aller plus loin
Réduisez la surcharge de connexion sur chaque résolution — récupérez votre clé API CaptchaAI. Pour approfondir :