Картинка с искажёнными буквами и поле ввода рядом — текстовая CAPTCHA: в автоматизации она закрывается одним запросом к OCR. Сетка фотографий с подписью «выберите все светофоры» — графическая CAPTCHA, для неё нужен решатель под конкретного провайдера. Разница в один экран интерфейса оборачивается разницей в объёме кода и во времени удержания потока.
Короткий ответ: что выбирать под свою задачу
- Текстовая CAPTCHA — автономный фильтр спама без внешних зависимостей, с возможностью добавить аудиоверсию.
- Графическая CAPTCHA — вход в личный кабинет и платежи, где допустимо большее трение ради управляемой защиты.
- Ни та, ни другая, если трафик закрывают невидимые проверки: reCAPTCHA v3 и Cloudflare Turnstile не требуют действий пользователя и доступнее для людей с нарушениями зрения.
Прямое сравнение по десяти параметрам
| Параметр | Текстовая CAPTCHA | Графическая CAPTCHA |
|---|---|---|
| Уровень защиты | Низкий — стандартные наборы читает современный OCR | Высокий — нужна классификация объектов |
| Время решения человеком | 5–10 с | 10–30 с |
| Доля ошибок у людей | 15–20 % | 8–15 % |
| Доступность | Плохо для слабовидящих | Ещё хуже: сетка непригодна для скринридеров |
| Мобильные устройства | Средне — мелкие символы | Хорошо — выбор касанием |
| Сложность автоматизации | Низкая: один запрос к OCR | Высокая: нужен решатель под провайдера |
| Стоимость внедрения | Бесплатно, на своём сервере | От бесплатного до платного SDK провайдера |
| Нагрузка на пул потоков | Поток занят < 0,5 с (image/OCR) | Дольше: grid image < 1 с, reCAPTCHA v2 < 60 с |
| Сбор данных | Нет | Может обучать ML-модели (reCAPTCHA) |
| Объём интеграции | Минимальный — генерация картинки на бэкенде | Средний — JavaScript SDK и токен |
Строка про потоки важнее, чем кажется: тарифы CaptchaAI считаются по числу одновременных потоков, а не решений.
Как устроена текстовая CAPTCHA
Сервер рисует случайную строку как изображение и искажает её, чтобы помешать распознаванию.
Приёмы искажения
| Приём | Зачем нужен |
|---|---|
| Деформация символов | Мешает простому распознаванию |
| Фоновый шум | Линии, точки и градиенты за текстом |
| Наложение символов | Ломает сегментацию букв |
| Рандомизация шрифтов | Свой шрифт и кегль в каждой задаче |
| Вариация цвета | Случайный цвет символов и фона |
Жизненный цикл текстовой проверки
Server generates random string (e.g., "X7mK9p")
↓
Applies distortion: warping, noise, overlap
↓
Renders as PNG/JPEG image
↓
User reads characters, types into input field
↓
Server compares input against stored string (case-insensitive usually)
Компромисс очевиден: чем сильнее искажение, тем чаще ошибается не только машина, но и человек.
Как устроена графическая CAPTCHA
Здесь пользователь выбирает подходящие плитки в сетке, сверка идёт на стороне провайдера, а форма получает только токен.
Основные разновидности
| Разновидность | Задача пользователя | Провайдер |
|---|---|---|
| Выбор в сетке | «Выделите все квадраты со светофорами» | reCAPTCHA v2 |
| Разметка изображений | «Нажмите на все изображения с автобусом» | hCaptcha |
| Подсчёт объектов | «Сколько велосипедов на изображении?» | Самописные решения |
| Поворот | «Поверните изображение в правильное положение» | FunCaptcha |
Жизненный цикл графической проверки
Server selects images from a labeled dataset
↓
Presents 3×3 or 4×4 grid with a text prompt
↓
User clicks matching images
↓
Server validates selections against ground truth
↓
If fading images: new images load in place of selected ones (multi-round)
Многораундовый сценарий превращает одну задачу в несколько последовательных.
Как определить тип CAPTCHA на странице
Тип проверки определяется по разметке: сначала маркеры провайдеров, затем связка «картинка со словом captcha в src» плюс «поле ввода с captcha в name» — почти всегда это самописная текстовая проверка.
Определение на Python
import requests
from bs4 import BeautifulSoup
import re
def detect_captcha_type(url):
"""Detect whether page uses text or image CAPTCHA."""
response = requests.get(url, timeout=10)
soup = BeautifulSoup(response.text, "html.parser")
html = response.text
result = {"text_captcha": False, "image_captcha": False, "provider": None}
# Check for reCAPTCHA (image-based)
if "google.com/recaptcha" in html or "g-recaptcha" in html:
result["image_captcha"] = True
result["provider"] = "reCAPTCHA"
return result
# Check for hCaptcha (image-based)
if "hcaptcha.com" in html or "h-captcha" in html:
result["image_captcha"] = True
result["provider"] = "hCaptcha"
return result
# Check for text CAPTCHA patterns
captcha_images = soup.find_all("img", attrs={
"src": re.compile(r"captcha", re.I)
})
captcha_inputs = soup.find_all("input", attrs={
"name": re.compile(r"captcha", re.I)
})
if captcha_images and captcha_inputs:
# Image with text input = text CAPTCHA
result["text_captcha"] = True
result["provider"] = "custom text CAPTCHA"
return result
# Check for FunCaptcha (image-based rotation)
if "funcaptcha" in html.lower() or "arkoselabs" in html.lower():
result["image_captcha"] = True
result["provider"] = "FunCaptcha"
return result
return result
captcha = detect_captcha_type("https://staging.example.com/qa-login")
print(captcha)
Определение на Node.js
const axios = require("axios");
const cheerio = require("cheerio");
async function detectCaptchaType(url) {
const { data: html } = await axios.get(url, { timeout: 10000 });
const $ = cheerio.load(html);
const result = { textCaptcha: false, imageCaptcha: false, provider: null };
// reCAPTCHA detection
if (html.includes("google.com/recaptcha") || html.includes("g-recaptcha")) {
result.imageCaptcha = true;
result.provider = "reCAPTCHA";
return result;
}
// hCaptcha detection
if (html.includes("hcaptcha.com") || html.includes("h-captcha")) {
result.imageCaptcha = true;
result.provider = "hCaptcha";
return result;
}
// Text CAPTCHA: image + input with "captcha" in name/class
const captchaImgs = $("img[src*='captcha' i]").length;
const captchaInputs = $("input[name*='captcha' i]").length;
if (captchaImgs > 0 && captchaInputs > 0) {
result.textCaptcha = true;
result.provider = "custom text CAPTCHA";
return result;
}
return result;
}
detectCaptchaType("https://staging.example.com/qa-login").then(console.log);
Решение текстовой CAPTCHA через OCR API CaptchaAI
Текстовая CAPTCHA остаётся изображением: искажённый текст приходит в браузер в PNG или JPEG. Отдельный «текстовый» метод не нужен — картинка уходит в OCR-эндпоинт как base64, а ответ возвращает распознанную строку.
import requests
import base64
import time
API_KEY = "YOUR_API_KEY"
# Get the CAPTCHA image
captcha_url = "https://example.com/captcha.png"
image_data = requests.get(captcha_url).content
b64 = base64.b64encode(image_data).decode()
# Submit to CaptchaAI
submit = requests.post("https://ocr.captchaai.com/in.php", data={
"key": API_KEY,
"method": "base64",
"body": b64,
"json": 1,
})
task_id = submit.json()["request"]
# Poll for result
for _ in range(30):
time.sleep(3)
resp = requests.get("https://ocr.captchaai.com/res.php", params={
"key": API_KEY,
"action": "get",
"id": task_id,
"json": 1,
}).json()
if resp.get("status") == 1:
print(f"CAPTCHA text: {resp['request']}")
break
in.php принимает задачу и возвращает её ID, res.php опрашивается до готовности, json: 1 избавляет от разбора текстового ответа. Image/OCR закрывает 27 500+ вариантов изображений и укладывается в < 0,5 с на задачу.
Что CaptchaAI решает, а что нет
| Тип проверки | Статус в CaptchaAI |
|---|---|
| Image / OCR, Grid Image, BLS | ✅ есть, < 0,5–1 с |
| reCAPTCHA v2, v2 Invisible, v3 (+ Enterprise) | ✅ есть |
| Cloudflare Turnstile и Challenge, GeeTest v3 | ✅ есть |
| CaptchaFox, Friendly Captcha, Lemin | ✅ beta |
| hCaptcha, FunCaptcha (Arkose Labs) | ❌ пока нет |
| GeeTest v4 | ❌ скоро, пока недоступно |
Итого 15 методов: 12 в общем доступе и 3 в статусе beta.
Сценарий: ночной регресс на смешанных формах
Знакомая ситуация для команд в Москве, Минске и Алматы: порталу десять лет, новые разделы закрыты reCAPTCHA v2, а старые внутренние формы отдают самописную картинку с буквами. Ночной прогон идёт по обоим типам сразу, и потоки приходится считать по самому медленному:
- текстовые формы держат поток меньше полсекунды — даже BASIC ($15/мес, 5 потоков) закрывает тысячи таких задач за считаные минуты;
- формы с reCAPTCHA v2 держат поток дольше (< 60 с), узким местом становится параллельность — здесь логичнее STANDARD ($30/мес, 15 потоков);
- в логах храните только те данные форм, которые вы вправе обрабатывать: 152-ФЗ и принцип минимизации из GDPR действуют для стендов так же, как для продакшена.
Частые вопросы
Как отличить текстовую CAPTCHA от reCAPTCHA, не открывая браузер?
По HTML. google.com/recaptcha или класс g-recaptcha указывают на reCAPTCHA, hcaptcha.com — на hCaptcha. Если маркеров провайдера нет, но есть картинка с captcha в src и поле ввода с captcha в name, это самописная текстовая проверка.
Сколько потоков нужно, чтобы закрывать тысячу текстовых проверок в час?
Немного. При решении image/OCR меньше полсекунды вы упрётесь в сетевые задержки раньше, чем в лимит потоков: пяти потоков тарифа BASIC ($15/мес) хватает с запасом. Наращивать тариф стоит, когда в прогоне появляются медленные типы вроде reCAPTCHA v2.
Почему распознавание ошибается на сильно искажённом тексте?
Искажение работает против любого читателя: наложенные символы и агрессивная деформация снижают долю успешных решений и у машины, и у человека. Практический вывод: закладывайте повторную попытку с новой картинкой.
Что делать, если форму закрывает hCaptcha или FunCaptcha?
Планировать этот участок отдельно: hCaptcha и FunCaptcha (Arkose Labs) в поддерживаемые типы не входят, GeeTest v4 заявлен как «скоро». Через API доступны:
- reCAPTCHA v2/v3, Cloudflare Turnstile и Challenge, GeeTest v3;
- image/OCR, grid image и BLS;
- CaptchaFox, Friendly Captcha и Lemin — в статусе beta.
Что запомнить
Текстовая CAPTCHA дешева и во внедрении, и в автоматизации: одна картинка — один запрос к OCR API CaptchaAI. Графическая сложнее с обеих сторон: защита сильнее, но нужны SDK провайдера и отдельный решатель. Рынок смещается к невидимым проверкам: меньше трения для пользователя и работа с токеном вместо картинки для автоматизации.