Every CAPTCHA solve involves multiple HTTP requests: one submit and 3–10 polls. Without connection reuse, each request pays the cost of a new TCP handshake and TLS negotiation — 100–300ms per connection. This guide shows how to eliminate that overhead using keep-alive connections and HTTP/2 multiplexing with CaptchaAI.
Why Connection Reuse Matters
A typical reCAPTCHA v2 solve requires:
- 1 submit request to
in.php - 4–6 poll requests to
res.php - Total: 5–7 HTTP requests
Without keep-alive:
- 5 × (TCP handshake ~50ms + TLS ~100ms) = 750ms overhead
With keep-alive:
- 1 × (TCP + TLS) + 4 × (~5ms reuse) = 170ms overhead
Savings: ~580ms per solve. At 10,000 solves/day, that's 1.6 hours of saved latency.
Python: Using requests.Session
The requests library supports keep-alive by default when you use a Session object:
# 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 with httpx
For HTTP/2 support, use 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()
JavaScript: Using an Axios Instance with Keep-Alive
// 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();
})();
HTTP/2 vs HTTP/1.1 for CAPTCHA Solving
| Feature | HTTP/1.1 Keep-Alive | HTTP/2 |
|---|---|---|
| Connection reuse | Yes (sequential) | Yes (multiplexed) |
| Concurrent streams | 1 per connection | Up to 100+ per connection |
| Header compression | No | HPACK compression |
| Latency reduction | ~60% | ~70% |
| Browser support needed | No | No (API calls) |
| Best for | Sequential solves | Parallel solves |
For sequential solving (one CAPTCHA at a time), HTTP/1.1 keep-alive is sufficient. For parallel solving (multiple CAPTCHAs simultaneously), HTTP/2 multiplexing provides additional benefit by sharing a single connection.
Connection Pool Sizing
Match your pool size to your concurrency level:
| Concurrent solves | Recommended pool size |
|---|---|
| 1–5 | 5 connections |
| 5–20 | 10 connections |
| 20–50 | 25 connections |
| 50–100 | 50 connections |
| 100+ | Use HTTP/2 (1 connection) |
Oversized pools waste memory. Undersized pools force new connections, negating keep-alive benefits.
Troubleshooting
| Issue | Cause | Fix |
|---|---|---|
| Connections closing between polls | Server or proxy timeout | Set keep-alive timeout > 30s in client config |
| No performance improvement | Already using keep-alive (default in some libraries) | Verify with network monitoring tools |
| Connection refused errors | Pool exhausted | Increase maxSockets or reduce concurrency |
| HTTP/2 not negotiated | Server doesn't support h2 | Fall back to HTTP/1.1 keep-alive |
FAQ
Does CaptchaAI support HTTP/2?
Test with curl --http2 https://ocr.captchaai.com/res.php to verify. If the server negotiates h2, your HTTP/2 client will benefit. If not, fall back to HTTP/1.1 keep-alive.
Should I close sessions after each batch?
No. Keep the session open between batches if you're running periodic solves. Close only when your application shuts down.
Does this work with proxy servers?
Yes, but your proxy must also support keep-alive and HTTP/2. Some SOCKS5 proxies don't maintain persistent connections.
Related Articles
Next Steps
Reduce connection overhead on every solve — get your CaptchaAI API key.
Related guides:
Discussions (0)
Join the conversation
Sign in to share your opinion.
Sign InNo comments yet.