Бот упирается в CAPTCHA ровно там, где автоматизация должна была работать без вас. API CaptchaAI решает CAPTCHA программно и отдаёт боту готовый токен, так что скрипт продолжает без паузы на человека.
Что нужно, чтобы бот сам проходил CAPTCHA:
- API-ключ CaptchaAI и метод под конкретный тип CAPTCHA (
userrecaptcha,turnstile,base64,cloudflare_challenge). - Опрос
res.phpс паузами, а не одиночный запрос — решение занимает секунды, а не миллисекунды. - Обработка тайм-аута и повторной попытки на случай, если
CAPCHA_NOT_READYдержится дольше обычного.
Где боты чаще всего упираются в CAPTCHA
Пять типичных сценариев:
| Сценарий | Типичная CAPTCHA | Метод CaptchaAI |
|---|---|---|
| Отправка формы | reCAPTCHA v2 | method=userrecaptcha |
| Регистрация аккаунта | reCAPTCHA v2/v3 | method=userrecaptcha |
| Массовый ввод данных | Капча-изображение | method=base64 |
| Бронирование | Cloudflare Turnstile | method=turnstile |
| Доступ к API-шлюзу | Cloudflare Challenge | method=cloudflare_challenge |
Сколько потоков нужно боту
CaptchaAI тарифицирует по потокам, а не по числу решённых капч, поэтому расчёт до старта простой:
- Один бот с последовательными запросами — это один поток.
- Пять параллельных ботов на пике трафика обычно закрывает план BASIC ($15/мес, 5 потоков) с запасом.
- Счёт в долларах не меняется от количества заявок в пиковый час — тариф привязан к потокам, а не к объёму решённых CAPTCHA.
Универсальный каркас: один класс на все типы CAPTCHA
Соберите один класс, который отправляет любую капчу в CaptchaAI и дожидается токена — каждый бот вызывает один и тот же метод solve():
import requests
import time
import logging
logger = logging.getLogger(__name__)
class CaptchaBot:
def __init__(self, api_key):
self.api_key = api_key
self.session = requests.Session()
self.session.headers.update({
"User-Agent": "Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36"
})
def solve(self, method, **params):
"""Solve any CAPTCHA type."""
params["key"] = self.api_key
params["method"] = method
resp = requests.get("https://ocr.captchaai.com/in.php", params=params)
if not resp.text.startswith("OK|"):
raise Exception(f"Submit error: {resp.text}")
task_id = resp.text.split("|")[1]
logger.info(f"Task submitted: {task_id}")
for _ in range(60):
time.sleep(5)
result = requests.get("https://ocr.captchaai.com/res.php", params={
"key": self.api_key, "action": "get", "id": task_id
})
if result.text == "CAPCHA_NOT_READY": continue
if result.text.startswith("OK|"): return result.text.split("|")[1]
raise Exception(f"Error: {result.text}")
raise TimeoutError("CAPTCHA solve timed out")
def submit_form(self, url, form_data, captcha_field="g-recaptcha-response",
site_key=None, captcha_method="userrecaptcha"):
"""Submit a form with CAPTCHA solving."""
if site_key:
if captcha_method == "userrecaptcha":
token = self.solve(captcha_method, googlekey=site_key, pageurl=url)
elif captcha_method == "turnstile":
token = self.solve(captcha_method, sitekey=site_key, pageurl=url)
form_data[captcha_field] = token
return self.session.post(url, data=form_data)
Что делает класс:
solve()— универсальная отправка и опрос: один метод обслуживает любой тип CAPTCHA из таблицы выше.submit_form()— берётsite_keyиpageurlстраницы, получает токен и сразу подставляет его в нужное поле формы.
Пример 1 — бот, который сам проходит форму с reCAPTCHA
Контактная форма, закрытая reCAPTCHA v2 — CaptchaBot решает капчу и подставляет токен в запрос.
bot = CaptchaBot("YOUR_API_KEY")
# Submit a contact form protected by reCAPTCHA
result = bot.submit_form(
url="https://example.com/contact",
form_data={
"name": "John Doe",
"email": "[email protected]",
"message": "Inquiry about your service"
},
site_key="6Le-wvkS...",
captcha_method="userrecaptcha"
)
print(f"Form submitted: {result.status_code}")
На что обратить внимание:
site_keyберётся из атрибутаdata-sitekeyвиджета на странице — его нужно найти до вызоваsolve().- Токен подставляется в то же поле, что ждёт форма (
g-recaptcha-responseдля reCAPTCHA), иначе сервер отклонит отправку.
Пример 2 — многошаговый сценарий бронирования
Бот проходит шаги выбора даты и ввода данных и решает CAPTCHA только на последнем — на подтверждении:
def appointment_booking_bot(date, time_slot, user_info):
bot = CaptchaBot("YOUR_API_KEY")
# Step 1: Load booking page
page = bot.session.get("https://example.com/book")
# Step 2: Select date and time
resp = bot.session.post("https://example.com/book/select", data={
"date": date,
"time": time_slot
})
# Step 3: Fill personal info with CAPTCHA
result = bot.submit_form(
url="https://example.com/book/confirm",
form_data={
"name": user_info["name"],
"email": user_info["email"],
"phone": user_info["phone"],
"date": date,
"time": time_slot
},
site_key="6Le-wvkS...",
captcha_method="userrecaptcha"
)
return result.status_code == 200
# Run
success = appointment_booking_bot(
date="2025-02-15",
time_slot="10:00",
user_info={"name": "John Doe", "email": "[email protected]", "phone": "555-0100"}
)
Почему CAPTCHA решается только на последнем шаге:
- Промежуточные шаги (выбор даты, ввод данных) обычно не защищены — капча стоит перед финальной отправкой.
- Решать её раньше времени бессмысленно: токен CAPTCHA действует ограниченное время и может истечь до момента реальной отправки формы.
Пример 3 — ввод данных с капчей-изображением
Порталы ввода данных чаще защищены капчей-изображением: бот кодирует картинку в base64 и передаёт в method=base64. Если бот сохраняет чужие данные — собирайте только то, что вправе обрабатывать по 152-ФЗ:
import base64
def data_entry_bot(entries, captcha_image_url):
bot = CaptchaBot("YOUR_API_KEY")
for entry in entries:
# Load the form page
page = bot.session.get("https://portal.example.com/entry")
# Download and solve image CAPTCHA
img = bot.session.get(captcha_image_url)
img_b64 = base64.b64encode(img.content).decode()
captcha_text = bot.solve("base64", body=img_b64)
# Submit entry
resp = bot.session.post("https://portal.example.com/entry", data={
**entry,
"captcha": captcha_text
})
logger.info(f"Entry submitted: {resp.status_code}")
time.sleep(random.uniform(2, 5))
Что важно в этом сценарии:
- Картинка передаётся в
bodyуже закодированной в base64 — скачивать и сохранять файл на диск не нужно. - Пауза между записями снижает риск упереться в ограничение частоты запросов на самом портале, а не только на стороне CaptchaAI.
Тот же каркас на Node.js
Логика та же — отправить, опросить, получить токен:
const axios = require("axios");
class CaptchaBot {
constructor(apiKey) {
this.apiKey = apiKey;
}
async solve(method, params) {
params.key = this.apiKey;
params.method = method;
const submit = await axios.get("https://ocr.captchaai.com/in.php", {
params,
});
const taskId = submit.data.split("|")[1];
while (true) {
await new Promise((r) => setTimeout(r, 5000));
const result = await axios.get("https://ocr.captchaai.com/res.php", {
params: { key: this.apiKey, action: "get", id: taskId },
});
if (result.data === "CAPCHA_NOT_READY") continue;
if (result.data.startsWith("OK|")) return result.data.split("|")[1];
throw new Error(result.data);
}
}
async submitForm(url, formData, siteKey, method = "userrecaptcha") {
const token = await this.solve(method, {
googlekey: siteKey,
pageurl: url,
});
formData["g-recaptcha-response"] = token;
return axios.post(url, new URLSearchParams(formData));
}
}
// Usage
const bot = new CaptchaBot("YOUR_API_KEY");
const result = await bot.submitForm(
"https://example.com/submit",
{ name: "John", email: "[email protected]" },
"6Le-wvkS..."
);
Отличие от Python-версии минимальное — axios вместо requests, async/await вместо синхронных вызовов, но структура запроса и порядок опроса res.php те же.
Частые сбои и что с ними делать
Ниже — сбои, с которыми боты сталкиваются чаще всего в проде, и что с ними делать без переписывания каркаса:
| Проблема | Решение |
|---|---|
| Токен CAPTCHA отклонён | Используйте токен в течение 120 секунд после решения. |
| Бот распознаётся, хотя токен верный | Приблизьте заголовки и паузы между действиями к поведению обычного браузера. |
| Форма требует дополнительных полей | Проверьте форму на скрытые поля — обычно это CSRF-токен. |
| Повторные отправки упираются в ограничение частоты | Добавьте задержки и распределите нагрузку через несколько прокси. |
Часто задаваемые вопросы
Сколько типов CAPTCHA реально закрывает один бот на CaptchaAI?
12 типов в GA (reCAPTCHA, Turnstile, Challenge, GeeTest v3, капча-изображение, grid-image, BLS) плюс CaptchaFox, Friendly Captcha и Lemin в бета-статусе.
Можно ли обрабатывать несколько ботов одновременно на одном API-ключе?
Да, лимит идёт по числу потоков в плане, а не по числу ботов или ключей.
Что делать, если res.php подолгу отвечает CAPCHA_NOT_READY?
Для reCAPTCHA v2 это нормально в пиковой нагрузке — опрос рассчитан на 60 попыток с паузой 5 секунд. Если тайм-аут регулярный, проверьте sitekey и pageurl.
Нужно ли ставить бота на паузу, пока CaptchaAI решает капчу?
Запрос к res.php неблокирующий, но опрос выше синхронный. При десятках ботов в процессе вынесите solve() в очередь.
Что делать, если сайт использует reCAPTCHA v3, а не v2?
Передайте в solve() дополнительно version=v3 и action — остальной каркас не меняется, submit_form() подставит токен в то же поле.