Если парсер простаивает по 20–30 секунд между отправкой CAPTCHA и получением токена, виноват обычно не решатель, а то, как вы его вызываете.
Задержка одного решения складывается из четырёх частей:
- отправка запроса на сервер CaptchaAI;
- ожидание задачи в очереди;
- работа самого решателя;
- получение результата опросом или через callback.
Повлиять вы можете на всё, кроме времени самого решения, — этому и посвящена статья.
Ориентир: сколько задержки нормально для каждого типа CAPTCHA
Прежде чем оптимизировать, полезно знать, к чему стремиться: официальный потолок SLA и результат, который реально получают команды после приёмов из этой статьи.
| Тип CAPTCHA | Потолок SLA | Достижимый результат |
|---|---|---|
| Image/OCR | <0,5 с | 0,2–0,4 с |
| reCAPTCHA v2 | <60 с | 10–20 с |
| reCAPTCHA v3 | <4 с | 1–3 с |
| Cloudflare Turnstile | <10 с | 4–8 с |
| GeeTest v3 | <12 с | 6–10 с |
Часть задержки — не на стороне CaptchaAI, а в сети: при хостинге в Европе RTT до
ocr.captchaai.comобычно ниже, чем при более длинном маршруте (мобильный канал, хостинг в Центральной Азии). Перед тюнингом кода измерьте фактический RTT — так вы поймёте, сколько съедает сеть, а сколько реально даёт оптимизация.
1. Настройте адаптивный опрос вместо фиксированного интервала
Опрос раз в 5 секунд по умолчанию часто тратит время впустую: решение готово, а вы всё равно ждёте до следующего цикла.
Адаптивный опрос устраняет это — начинайте агрессивно, затем снижайте частоту:
Python
import time
import requests
API_KEY = "YOUR_API_KEY"
RESULT_URL = "https://ocr.captchaai.com/res.php"
def adaptive_poll(task_id, timeout=120):
"""Start polling at 3s, increase to 5s after 4 polls."""
start = time.time()
interval = 3 # start aggressive
polls = 0
while time.time() - start < timeout:
time.sleep(interval)
polls += 1
resp = requests.get(RESULT_URL, params={
"key": API_KEY, "action": "get",
"id": task_id, "json": "1"
}).json()
if resp["status"] == 1:
elapsed = time.time() - start
print(f"Solved in {elapsed:.1f}s ({polls} polls)")
return resp["request"]
if resp["request"] != "CAPCHA_NOT_READY":
raise Exception(resp["request"])
# Back off after initial fast polls
if polls >= 4:
interval = 5
raise TimeoutError(f"Task {task_id} timed out")
Та же логика на JavaScript:
JavaScript
async function adaptivePoll(taskId, apiKey, timeout = 120000) {
const start = Date.now();
let interval = 3000;
let polls = 0;
while (Date.now() - start < timeout) {
await new Promise(r => setTimeout(r, interval));
polls++;
const resp = await fetch(
`https://ocr.captchaai.com/res.php?key=${apiKey}&action=get&id=${taskId}&json=1`
);
const data = await resp.json();
if (data.status === 1) {
console.log(`Solved in ${((Date.now() - start) / 1000).toFixed(1)}s (${polls} polls)`);
return data.request;
}
if (data.request !== 'CAPCHA_NOT_READY') {
throw new Error(data.request);
}
if (polls >= 4) interval = 5000;
}
throw new Error(`Task ${taskId} timed out`);
}
В среднем это экономит 1–4 секунды по сравнению с фиксированным пятисекундным интервалом. Пара нюансов при подборе параметров:
- для reCAPTCHA v2 стартовый интервал 3 с почти всегда оправдан — решение редко готово раньше;
- для быстрых типов вроде Image/OCR выигрыш от агрессивного старта скромнее (см. FAQ ниже).
2. Переиспользуйте HTTP-соединения (пул соединений)
Каждое новое TCP/TLS-соединение — лишний round-trip ещё до самого запроса.
Переиспользуйте соединение вместо того, чтобы открывать новое на каждый опрос:
Python
session = requests.Session()
# Use session.get() and session.post() instead of requests.get/post
# The session reuses TCP connections automatically
Аналог на Node.js:
JavaScript (Node.js)
const { Agent } = require('http');
const axios = require('axios');
const client = axios.create({
httpAgent: new Agent({ keepAlive: true, maxSockets: 10 }),
timeout: 10000,
});
// Use client.get() and client.post() for all API calls
Экономия обычно 50–100 мс на запрос за счёт пропуска повторных TCP/TLS-рукопожатий. Проверить эффект просто:
- сравните P95 из раздела 7 до и после перехода на
Session/Agent; - если разница почти незаметна, скорее всего сессия уже переиспользуется где-то в коде.
3. Отправляйте CAPTCHA заранее (prefetch)
Не ждите, когда токен понадобится, — отправляйте задачу заранее. Пока парсер обрабатывает страницу N, отправьте CAPTCHA для N+1:
from concurrent.futures import ThreadPoolExecutor
SUBMIT_URL = "https://ocr.captchaai.com/in.php"
def prefetch_submit(sitekey, page_url):
resp = session.post(SUBMIT_URL, data={
"key": API_KEY,
"method": "userrecaptcha",
"googlekey": sitekey,
"pageurl": page_url,
"json": "1",
})
data = resp.json()
if data["status"] == 1:
return data["request"]
raise Exception(data["request"])
# Submit next page's CAPTCHA while processing current page
with ThreadPoolExecutor(max_workers=2) as pool:
# Submit CAPTCHA for page 2 while processing page 1
future_task = pool.submit(prefetch_submit, "6Le-SITEKEY", "https://example.com/page/2")
# Process page 1...
process_page(current_data)
# Now get the pre-submitted task ID and poll
task_id = future_task.result()
token = adaptive_poll(task_id)
Так решение перекрывается с обработкой страницы, и суммарное ожидание в пайплайне уходит почти в ноль.
Ограничение одно: не отправляйте задачи слишком далеко вперёд. Токен CaptchaAI не бессрочный, и prefetch на 10+ страниц вперёд рискует истечь до использования.
4. Выбирайте более быстрый метод API, если он есть
Для части сценариев у CaptchaAI есть альтернатива быстрее опроса:
| Сценарий | Медленный вариант | Более быстрая альтернатива |
|---|---|---|
| reCAPTCHA v2 с настроенным callback | userrecaptcha + опрос |
userrecaptcha с pingback (URL обратного вызова) |
| Текстовая CAPTCHA-картинка | base64 в высоком разрешении |
base64 с numeric=1, если ответ — только цифры |
5. Не подключайте прокси без необходимости
Маршрутизация через прокси добавляет задержку. Прокси нужен не всегда:
- целевой сайт требует запросов с определённого IP или гео — прокси обязателен;
- сайт не проверяет источник запроса — быстрее отправлять напрямую.
Передавайте параметры прокси только в первом случае:
# Without proxy — faster for most use cases
data = {
"key": API_KEY,
"method": "userrecaptcha",
"googlekey": sitekey,
"pageurl": page_url,
"json": "1",
}
# With proxy — only when required
data["proxy"] = "user:[email protected]:8080"
data["proxytype"] = "HTTP"
Тестируйте оба варианта на реальном трафике, а не только локально: разница в задержке между «с прокси» и «без прокси» может отличаться от прогноза из-за состояния конкретного прокси-пула.
6. Заменяйте опрос колбэком pingback
Параметр pingback убирает цикл опроса полностью:
resp = session.post(SUBMIT_URL, data={
"key": API_KEY,
"method": "userrecaptcha",
"googlekey": sitekey,
"pageurl": page_url,
"json": "1",
"pingback": "https://your-server.com/captcha-callback",
})
CaptchaAI сам отправит результат на указанный URL — опрашивать res.php не придётся.
По нашим внутренним замерам pingback стабильно быстрее регулярного опроса за счёт меньшего числа HTTP-запросов.
7. Измеряйте эффект оптимизаций
Не полагайтесь на ощущения — снимайте цифры до и после:
import statistics
def benchmark(solve_func, iterations=20):
times = []
for i in range(iterations):
start = time.time()
try:
solve_func()
times.append(time.time() - start)
except Exception:
pass
if times:
print(f"Samples: {len(times)}/{iterations}")
print(f"Mean: {statistics.mean(times):.1f}s")
print(f"Median: {statistics.median(times):.1f}s")
print(f"P95: {sorted(times)[int(len(times)*0.95)]:.1f}s")
print(f"Min: {min(times):.1f}s")
print(f"Max: {max(times):.1f}s")
Частые проблемы при оптимизации задержки
- Задержка опроса не изменилась. Скорее всего код всё ещё использует
requests.get()без сессии — перейдите наsession.get(). - Токены prefetch истекают до использования. Обработка страницы занимает слишком много времени — сократите окно prefetch или отправляйте задачу ближе к моменту использования.
- Callback URL не получает данные. Сервер недоступен со стороны CaptchaAI — убедитесь, что URL публичный, и проверьте правила файрвола.
- Более частый опрос упирается в лимит запросов. Опрос слишком агрессивный (< 2 с) — держите минимальный интервал в 3 секунды.
Вопросы, которые обычно возникают
Коротко отвечаем на то, что чаще всего спрашивают при внедрении этих приёмов.
Что оптимизировать в первую очередь, если время на доработку ограничено?
Prefetch: он перекрывает решение со временем обработки страницы и сильнее всего снижает воспринимаемую задержку в последовательных пайплайнах.
Даёт ли адаптивный опрос ощутимый выигрыш для Image/OCR?
Не сильно. Image/OCR решается за 0,2–0,4 секунды, и первый опрос на 3-й секунде почти всегда застаёт результат готовым. Заметнее — на reCAPTCHA v2 (10–20 секунд).
Почему подключение прокси иногда добавляет секунды к решению?
Прокси — лишний сетевой узел, часто более медленный. Подключайте его только там, где сайт требует запросов с определённого IP, — в остальных случаях идите напрямую.
Как проверить, сколько задержки добавляет сеть, а не решатель?
Замерьте RTT до https://ocr.captchaai.com и сравните с показаниями benchmark() из раздела 7. Разница — то, что реально можно сократить кодом.
Сколько потоков нужно, чтобы задержка одной задачи не тормозила весь пайплайн?
Это вопрос пропускной способности, а не задержки одной задачи.
CaptchaAI тарифицирует по числу одновременных потоков, а не по числу решений. На плане BASIC ($15/мес, 5 потоков) вы решаете до 5 задач параллельно — если нужно больше, увеличивайте план.
Сократите задержку решения CAPTCHA с CaptchaAI
Все приёмы из статьи работают с одним и тем же API-ключом — менять инфраструктуру не нужно.
Получите ключ на captchaai.com и подключите адаптивный опрос и pingback.
Похожие руководства
Если задержка — не единственное, что нужно оптимизировать, посмотрите смежные темы: