Флаг WebDriver, canvas-сигнатура, скорость движения курсора, TLS-подпись клиента — reCAPTCHA складывает эти сигналы в единый score ещё до того, как пользователь вообще увидел чекбокс.
Проверка идёт в пять слоёв: JS-окружение, Canvas/WebGL, поведение, сеть/IP и память между сессиями. Ниже — как устроен каждый слой и почему API-решатели вроде CaptchaAI не запускают ни один из них, отправляя запрос напрямую в отдельную решающую среду.
| Слой | Что проверяет reCAPTCHA | Типичный сигнал |
|---|---|---|
| 1. JS-окружение | headless-признаки браузера | navigator.webdriver |
| 2. Canvas/WebGL | сигнатура рендеринга | GPU vendor/renderer |
| 3. Поведение | мышь, клавиатура, скролл | ритм и траектория |
| 4. Сеть/IP/TLS | репутация IP, TLS-подпись | JA3/JA4 |
| 5. Кросс-сессии | память между сайтами | повторяющиеся паттерны |
Флаг WebDriver: что видит reCAPTCHA
Первым делом reCAPTCHA прогоняет набор JS-проверок, которые отличают headless-браузер и фреймворки автоматизации от обычного Chrome. Главный индикатор автоматизации:
// Selenium/Puppeteer set this automatically
navigator.webdriver === true // → Automation detected
// Real browser
navigator.webdriver === undefined // or false → Normal browser
Как только флаг WebDriver возвращает true, reCAPTCHA сразу помечает сессию как автоматизированную — обычно это даёт score 0,1 и ниже.
Это первая и самая грубая проверка: она отсекает автоматизацию до того, как reCAPTCHA вообще начинает смотреть на поведение или сеть.
Каких браузерных API не хватает в headless-режиме
reCAPTCHA опрашивает API, которые headless-браузеры либо не реализуют, либо реализуют иначе:
// Probes reCAPTCHA performs (simplified)
const checks = {
// Chrome-specific object
hasChrome: !!window.chrome,
hasChromeRuntime: !!(window.chrome && window.chrome.runtime),
// Plugin and MIME type arrays
pluginCount: navigator.plugins.length,
mimeTypeCount: navigator.mimeTypes.length,
// Notification permission
notificationPermission: Notification.permission,
// Speech synthesis voices
speechVoices: window.speechSynthesis.getVoices().length,
// Performance observer
hasPerformanceObserver: typeof PerformanceObserver !== "undefined",
};
| Проверка | Ожидаемое значение (обычный Chrome) | Headless Chrome | Результат |
|---|---|---|---|
window.chrome |
объект | undefined или минимальный набор |
автоматизация |
navigator.plugins |
2–5 плагинов | пустой массив | автоматизация |
navigator.permissions |
объект с методом query() |
может выбросить ошибку или отсутствовать | автоматизация |
Notification.permission |
"default" |
может выбросить ошибку | автоматизация |
window.speechSynthesis |
объект со списком голосов | пуст или отсутствует | автоматизация |
Подмена методов через прототипы
Продвинутые инструменты автоматизации переопределяют браузерные API, чтобы спрятать своё присутствие. reCAPTCHA проверяет именно это вмешательство:
// reCAPTCHA may check if native functions were modified
const nativeToString = Function.prototype.toString;
const pluginsToString = navigator.plugins.toString();
// Overridden functions have different toString output:
// Native: "function get plugins() { [native code] }"
// Overridden: "function () { return [...fakePlugins] }"
Canvas-сигнатура окружения
reCAPTCHA рисует скрытые элементы на canvas и считывает пиксели обратно. Результат зависит от ОС, GPU, движка рендеринга шрифтов и настроек сглаживания — то есть от конкретной машины:
// Simplified canvas сигналы браузера
const canvas = document.createElement("canvas");
const ctx = canvas.getContext("2d");
ctx.textBaseline = "alphabetic";
ctx.font = "14px Arial";
ctx.fillStyle = "#f60";
ctx.fillRect(125, 1, 62, 20);
ctx.fillStyle = "#069";
ctx.fillText("CaptchaTest,!", 2, 15);
const fingerprint = canvas.toDataURL();
// Unique per browser/OS/GPU combination
На что смотрит reCAPTCHA:
| Наблюдение | Вывод |
|---|---|
| одна и та же сигнатура при разных заявленных ОС/браузерах | похоже на спуфинг |
| canvas возвращает однородные или пустые данные | признак headless-среды |
| сигнатура совпадает с известным паттерном headless Chrome | сессия помечается как автоматизация |
WebGL: vendor и renderer
const gl = document.createElement("canvas").getContext("webgl");
const debugInfo = gl.getExtension("WEBGL_debug_renderer_info");
const vendor = gl.getParameter(debugInfo.UNMASKED_VENDOR_WEBGL);
const renderer = gl.getParameter(debugInfo.UNMASKED_RENDERER_WEBGL);
// Real browser: "ANGLE (NVIDIA GeForce RTX 3060 Direct3D11 vs_5_0 ps_5_0)"
// Headless Chrome: "Google Inc. (Google SwiftShader)" ← Strong bot signal
SwiftShader — программный GPU-рендерер Google, который включается, когда нет доступного физического GPU. Само его наличие — сильный сигнал headless-среды.
Движения курсора
Поведенческий анализ — самый сильный уровень детекции reCAPTCHA: он снимает поведение пользователя от загрузки страницы до отправки формы.
reCAPTCHA records:
├─ Mouse coordinates at ~60fps intervals
├─ Velocity and acceleration at each point
├─ Trajectories between clickable elements
├─ Hover patterns over links and buttons
├─ Micro-movements while "stationary"
└─ Natural overshoot when targeting elements
Human pattern:
- Curved paths with variable speed
- Natural acceleration/deceleration (Fitts's Law)
- Random micro-jitter during hovering
- Occasional overshoot and correction
Bot pattern:
- Zero mouse events (no mouse simulation)
- Straight lines at constant speed
- Perfect targeting (no overshoot)
- Identical patterns across sessions
Клавиатурный почерк
reCAPTCHA records:
├─ Inter-key interval for each key pair
├─ Key hold duration (keydown to keyup)
├─ Error rate (backspace frequency)
├─ Typing rhythm consistency
└─ Input method (keyboard vs paste vs JavaScript)
Human pattern:
- Variable intervals (80-300ms typical)
- Faster for common character pairs
- Occasional errors and corrections
- keydown → keypress → keyup sequence
Bot pattern:
- Constant intervals or instant input
- No keypress events (value set via JS)
- Zero errors
- All characters appear simultaneously
Тайминг взаимодействия со страницей
reCAPTCHA records:
├─ Time from page load to first interaction
├─ Time from CAPTCHA rendering to click
├─ Scroll events and depths
├─ Focus/blur events on form fields
└─ Tab between fields vs click between fields
Suspicious patterns:
- First interaction < 1 second after page load
- CAPTCHA clicked immediately after rendering
- No scroll events before interacting with below-fold content
- All form fields filled in <500ms
Репутация IP-адреса в базе reCAPTCHA
reCAPTCHA также анализирует сеть, IP-адрес и TLS-рукопожатие. У Google есть обширная база данных по IP:
| Признак | Пример |
|---|---|
| Диапазоны дата-центров | AWS (52.x.x.x, 54.x.x.x), GCP, Azure, DigitalOcean |
| Прокси/VPN-провайдеры | NordVPN, ExpressVPN, коммерческие прокси |
| Выходные узлы Tor | публичный список, обновляется регулярно |
| История злоупотреблений | IP, ранее замеченные в спаме, парсинге, массовом решении CAPTCHA |
| Гео-паттерны | резкая смена локации между запросами → VPN-перескок |
TLS-сигнатура (JA3/JA4)
Каждый HTTP-клиент оставляет уникальную подпись TLS-рукопожатия:
Chrome 120: JA3 = 771,4865-4866-4867-49195-49199-49196..
Python/requests: JA3 = 771,4866-4867-4865-49196-49200..
curl/libcurl: JA3 = 771,49196-49200-159-52393-52392..
reCAPTCHA сверяет, соответствует ли TLS-сигнатура заявленному User-Agent. Chrome в User-Agent при Python-подписи TLS — прямой повод пометить сессию как автоматизацию.
HTTP-заголовки
Real Chrome headers:
Accept: text/html,application/xhtml+xml,application/xml;q=0.9,...
Accept-Language: en-US,en;q=0.9
Accept-Encoding: gzip, deflate, br
Sec-CH-UA: "Not_A Brand";v="8", "Chromium";v="120"
Sec-CH-UA-Platform: "Windows"
Sec-Fetch-Dest: document
Sec-Fetch-Mode: navigate
Automation headers (missing or different):
- Missing Sec-CH-UA headers
- Missing Accept-Language
- Non-standard Accept header
- Missing Sec-Fetch-* headers
Память reCAPTCHA между сайтами и сессиями
reCAPTCHA сопоставляет паттерны сразу по нескольким сессиям и сайтам.
Корреляция сессий
Один и тот же браузерный профиль, делающий быстрые запросы на множестве сайтов подряд, — заметный сигнал. Правильные ответы, приходящие в стабильно одинаковые интервалы времени, тоже выделяются: у живого человека время решения всегда «плавает».
Совпадающие ответы и история cookie
- Несколько сессий решают идентичные задачи за считаные секунды.
- Много свежих сессий с одного IP без сохранения cookie между заходами.
Как API-решатели проходят все пять слоёв
API-решатели вроде CaptchaAI не пытаются обмануть детектор в вашем окружении — они вообще не появляются в нём. Задача решается в отдельной инфраструктуре решателя:
Your automation:
Extracts sitekey + pageurl from target page
↓
Sends to CaptchaAI API (HTTPS request to ocr.captchaai.com)
↓
CaptchaAI's solver environment:
├─ Real browser with genuine сигналы браузера (not headless)
├─ Human-like behavioral patterns
├─ Clean residential IP
├─ Valid cookies and session history
├─ Matching TLS/header fingerprints
└─ Solves the challenge with human-like behavior
↓
Returns valid g-recaptcha-response token
↓
Your automation:
Submits token to target website
↓
Target website validates token with Google
→ Google sees a legitimate solve from a trusted environment
→ Token validated: success = true
Главное: ваш код никогда не взаимодействует с reCAPTCHA напрямую — всю работу со средой, поведением и прохождением задачи берёт на себя решатель. От кода требуется только отправить готовый токен в форму.
Практический пример: QA-тестирование чекаута
Команда, которая гоняет regression-тесты интернет-магазина в headless Chrome, обычно первой ловит reCAPTCHA v2 на форме оплаты — headless-флаг убивает сценарий раньше, чем тест успевает дойти до логики корзины. Вместо патчей браузера тесты просто отправляют sitekey и pageurl в API CaptchaAI и ждут токен: для одного CI/CD-пайплайна хватает BASIC ($15/мес, 5 потоков), для параллельных прогонов — STANDARD ($30/мес, 15 потоков). Если тест заодно собирает логи со страницы, ограничьте сбор минимумом — разумная гигиена и по 152-ФЗ, и по GDPR.
Пример на Python
import requests
import time
API_KEY = "YOUR_API_KEY"
# Your automation only needs sitekey and pageurl
submit = requests.post("https://ocr.captchaai.com/in.php", data={
"key": API_KEY,
"method": "userrecaptcha",
"googlekey": "6LcR_RsTAAAAAN_r0GEkGBfq3L7KmU5JbPHJtwNp",
"pageurl": "https://staging.example.com/qa-login",
"json": 1,
})
task_id = submit.json()["request"]
# Poll for token
for _ in range(60):
time.sleep(5)
result = requests.get("https://ocr.captchaai.com/res.php", params={
"key": API_KEY,
"action": "get",
"id": task_id,
"json": 1,
}).json()
if result.get("status") == 1:
token = result["request"]
# Submit this token to the target site's form
print("Token received — submit to target form")
break
Пример на Node.js
const axios = require("axios");
async function solveRecaptcha(sitekey, pageurl) {
const API_KEY = "YOUR_API_KEY";
const { data: submit } = await axios.post(
"https://ocr.captchaai.com/in.php",
new URLSearchParams({
key: API_KEY,
method: "userrecaptcha",
googlekey: sitekey,
pageurl: pageurl,
json: 1,
})
);
const taskId = submit.request;
for (let i = 0; i < 60; i++) {
await new Promise(r => setTimeout(r, 5000));
const { data: result } = await axios.get(
"https://ocr.captchaai.com/res.php",
{ params: { key: API_KEY, action: "get", id: taskId, json: 1 } }
);
if (result.status === 1) return result.request;
}
throw new Error("Timeout");
}
Частые вопросы
Влияет ли API-решение на итоговый score reCAPTCHA v3?
Да, но не в худшую сторону, если решатель отработал честно. reCAPTCHA v3 не даёт бинарного «прошёл/не прошёл» — она возвращает score от 0 до 1 по тем же пяти слоям. Если среда решателя вела себя как обычный браузер, Google засчитывает нормальный сеанс, и score получается не хуже, чем при обычном визите.
Обнаруживает ли reCAPTCHA обычный Selenium без дополнительных настроек?
Да, почти мгновенно — из-за WebDriver = true, отсутствующих Chrome API и заголовков ChromeDriver. Маскировка (undetected-chromedriver, доп. плагины) снижает риск, но не убирает его полностью. Решение через API снимает проблему целиком: reCAPTCHA вообще не видит ваш браузер.
Нужно ли моей автоматизации самой имитировать движения мыши и ввод с клавиатуры?
Нет — если задача уходит на решение через API, все поведенческие сигналы (мышь, клавиатура, скролл) генерирует среда решателя, а не ваш скрипт. Вашему коду достаточно передать sitekey и pageurl, дождаться готового g-recaptcha-response и подставить его в форму.
Как долго можно ждать с отправкой полученного токена?
Токен reCAPTCHA действителен ограниченное время — не кешируйте его «про запас», запрашивайте перед самой отправкой формы и отправляйте сразу после получения. Если между получением и сабмитом проходят десятки минут, запросите новый.
Как часто reCAPTCHA обновляет методы детекции, и не устареет ли этот разбор?
Google обновляет эвристики детекции постоянно, крупные изменения выходят раз в несколько месяцев. Новые способы вычислять headless-браузеры обычно закрываются в течение нескольких недель после релиза инструмента. Решатели вроде CaptchaAI подстраиваются сразу, потому что сами поддерживают свою решающую среду, а не полагаются на статичный набор патчей.
Итог
reCAPTCHA считает score по пяти слоям: JS-окружение (headless-детекция), Canvas/WebGL-сигнатура, поведение (мышь, клавиатура, скролл), репутация сети/IP и память между сессиями. API-решатели вроде CaptchaAI закрывают все пять слоёв разом, решая задачу в отдельной подготовленной среде и возвращая уже валидный токен. Код автоматизации не соприкасается с reCAPTCHA напрямую — детектировать нечего.