Почему CAPTCHA — главное препятствие для скрапера
CAPTCHA существуют для разделения людей и ботов, и они становятся всё эффективнее. Когда скрапер сталкивается с CAPTCHA, это значит, что целевой сайт обнаружил автоматизированное поведение — частота запросов была слишком высокой, IP имеет низкий уровень доверия или отпечаток браузера выглядел подозрительно. Лучшая стратегия CAPTCHA — предотвращение, а не решение.
Это руководство охватывает типы CAPTCHA, с которыми вы столкнётесь, почему предотвращение эффективнее и дешевле решения, и как прокси играют ключевую роль в полном избежании CAPTCHA.
Эта статья — часть нашей серии Полное руководство по прокси для веб-скрапинга. О системах обнаружения — Как антибот-системы обнаруживают прокси.
Типы CAPTCHA в 2026 году
| Тип | Как работает | Сложность обхода |
|---|---|---|
| reCAPTCHA v2 (чекбокс) | Клик «Я не робот» + возможная визуальная задача | Средняя |
| reCAPTCHA v3 (невидимая) | Оценивает поведение 0.0-1.0 без взаимодействия | Высокая |
| hCaptcha | Задачи выбора изображений (аналог reCAPTCHA v2) | Средняя |
| Cloudflare Turnstile | Браузерная проверка, обычно невидимая | Высокая |
| Кастомные CAPTCHA | Специфичные задачи сайта (искажённый текст, пазлы) | Варьируется |
| Proof of Work | Браузер должен вычислить хэш (Cloudflare Under Attack) | Средняя |
Невидимые CAPTCHA — настоящая угроза
Самые опасные CAPTCHA для скраперов — те, которые вы не видите. reCAPTCHA v3 и Cloudflare Turnstile работают в фоне, анализируя движения мыши, поведение прокрутки, паттерны набора и окружение браузера. Они назначают оценку доверия без показа челленджа — и если оценка слишком низкая, запрос тихо блокируется или перенаправляется.
Предотвращение vs решение: почему предотвращение побеждает
| Подход | Стоимость за CAPTCHA | Скорость | Надёжность | Масштабируемость |
|---|---|---|---|---|
| Предотвращение (CAPTCHA не появляются) | $0 | Мгновенно | Наивысшая | Отличная |
| Сервисы решения CAPTCHA | $1-3 за 1000 | 10-60 секунд | 85-95% | Умеренная |
| ИИ-автосолвинг | $2-5 за 1000 | 5-30 секунд | 70-90% | Ограниченная |
В масштабе предотвращение экономит и деньги, и время. Решение 100 000 CAPTCHA в день стоит $100-500 и добавляет часы задержки. Предотвращение не стоит ничего сверх правильного управления прокси и запросами.
Стратегия предотвращения 1: Используйте качественные резидентные прокси
Самая эффективная мера предотвращения CAPTCHA — использование резидентных прокси с высоким уровнем доверия. Резидентные IP назначаются интернет-провайдерами реальным домохозяйствам, поэтому сайты не могут легко отличить ваши запросы от реального пользовательского трафика.
import requests
# Residential proxy — high trust score, fewer CAPTCHAs
PROXY = "http://USERNAME:PASSWORD@gate.proxyhat.com:8080"
def scrape_with_residential(url: str) -> str:
"""Use residential proxies to avoid triggering CAPTCHAs."""
session = requests.Session()
session.proxies = {"http": PROXY, "https": PROXY}
session.headers.update({
"User-Agent": "Mozilla/5.0 (Windows NT 10.0; Win64; x64) "
"AppleWebKit/537.36 (KHTML, like Gecko) "
"Chrome/120.0.0.0 Safari/537.36",
"Accept": "text/html,application/xhtml+xml,application/xml;q=0.9,*/*;q=0.8",
"Accept-Language": "en-US,en;q=0.9",
"Accept-Encoding": "gzip, deflate, br",
})
resp = session.get(url, timeout=30)
return resp.text
Резидентный пул ProxyHat предоставляет IP от реальных провайдеров в 190+ странах, обеспечивая каждому запросу максимально высокий уровень доверия. Смотрите Резидентные vs датацентр-прокси для скрапинга для детального сравнения.
Стратегия предотвращения 2: Реалистичные паттерны запросов
CAPTCHA часто срабатывают от роботизированных паттернов поведения, а не только от репутации IP. Сделайте скрапер похожим на человека:
Реализация на Python
import requests
import random
import time
PROXY = "http://USERNAME:PASSWORD@gate.proxyhat.com:8080"
USER_AGENTS = [
"Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 Chrome/120.0.0.0 Safari/537.36",
"Mozilla/5.0 (Macintosh; Intel Mac OS X 10_15_7) AppleWebKit/537.36 Chrome/120.0.0.0 Safari/537.36",
"Mozilla/5.0 (Windows NT 10.0; Win64; x64; rv:121.0) Gecko/20100101 Firefox/121.0",
"Mozilla/5.0 (Macintosh; Intel Mac OS X 10_15_7) AppleWebKit/605.1.15 Safari/605.1.15",
]
REFERRERS = [
"https://www.google.com/",
"https://www.bing.com/",
"https://duckduckgo.com/",
None, # Direct visit
]
def human_like_scrape(urls: list[str]) -> list[str]:
"""Scrape with realistic human behavior patterns."""
results = []
session = requests.Session()
session.proxies = {"http": PROXY, "https": PROXY}
for url in urls:
# Randomize headers per request
headers = {
"User-Agent": random.choice(USER_AGENTS),
"Accept": "text/html,application/xhtml+xml,application/xml;q=0.9,*/*;q=0.8",
"Accept-Language": "en-US,en;q=0.9",
"Accept-Encoding": "gzip, deflate, br",
"Connection": "keep-alive",
"Upgrade-Insecure-Requests": "1",
}
referrer = random.choice(REFERRERS)
if referrer:
headers["Referer"] = referrer
try:
resp = session.get(url, headers=headers, timeout=30)
results.append(resp.text)
except requests.RequestException:
results.append(None)
# Human-like delays: 1-5 seconds with occasional longer pauses
if random.random() < 0.1:
time.sleep(random.uniform(5, 15)) # 10% chance of long pause
else:
time.sleep(random.uniform(1, 4))
return results
Реализация на Node.js
const HttpsProxyAgent = require('https-proxy-agent');
const fetch = require('node-fetch');
const agent = new HttpsProxyAgent('http://USERNAME:PASSWORD@gate.proxyhat.com:8080');
const USER_AGENTS = [
'Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 Chrome/120.0.0.0 Safari/537.36',
'Mozilla/5.0 (Macintosh; Intel Mac OS X 10_15_7) AppleWebKit/537.36 Chrome/120.0.0.0 Safari/537.36',
'Mozilla/5.0 (Windows NT 10.0; Win64; x64; rv:121.0) Gecko/20100101 Firefox/121.0',
];
function randomDelay() {
const isLongPause = Math.random() < 0.1;
const ms = isLongPause
? 5000 + Math.random() * 10000
: 1000 + Math.random() * 3000;
return new Promise(r => setTimeout(r, ms));
}
async function humanLikeScrape(urls) {
const results = [];
for (const url of urls) {
const headers = {
'User-Agent': USER_AGENTS[Math.floor(Math.random() * USER_AGENTS.length)],
'Accept': 'text/html,application/xhtml+xml,application/xml;q=0.9,*/*;q=0.8',
'Accept-Language': 'en-US,en;q=0.9',
};
try {
const res = await fetch(url, { agent, headers, timeout: 30000 });
results.push(await res.text());
} catch {
results.push(null);
}
await randomDelay();
}
return results;
}
Стратегия предотвращения 3: Умная ротация IP
Способ ротации IP напрямую влияет на частоту CAPTCHA. Агрессивная ротация (новый IP на каждый запрос) может даже увеличить CAPTCHA на некоторых сайтах, потому что серия запросов с разных IP по одному пути сессии выглядит подозрительно.
import requests
import uuid
def create_session_for_site(site_id: str):
"""Create a sticky session that maintains the same IP per site.
This avoids the suspicious pattern of different IPs accessing the same flow."""
session_id = uuid.uuid5(uuid.NAMESPACE_URL, site_id).hex[:8]
proxy = f"http://USERNAME-session-{session_id}:PASSWORD@gate.proxyhat.com:8080"
session = requests.Session()
session.proxies = {"http": proxy, "https": proxy}
return session
# Same IP for all requests to a specific product section
session = create_session_for_site("example.com-electronics")
page1 = session.get("https://example.com/electronics?page=1")
page2 = session.get("https://example.com/electronics?page=2")
page3 = session.get("https://example.com/electronics?page=3")
# Different IP for a different section
session2 = create_session_for_site("example.com-clothing")
clothes1 = session2.get("https://example.com/clothing?page=1")
Подробнее о паттернах ротации — Стратегии ротации прокси для масштабного скрапинга.
Стратегия предотвращения 4: Соблюдайте лимиты скорости
CAPTCHA часто являются эскалацией после ограничения скорости. Если правильно обрабатывать сигналы лимитов, CAPTCHA встречаются редко:
import requests
import time
PROXY = "http://USERNAME:PASSWORD@gate.proxyhat.com:8080"
CAPTCHA_INDICATORS = [
"captcha",
"recaptcha",
"hcaptcha",
"challenge",
"verify you are human",
"please complete the security check",
]
def is_captcha_page(html: str) -> bool:
"""Detect if the response is a CAPTCHA challenge page."""
html_lower = html.lower()
return any(indicator in html_lower for indicator in CAPTCHA_INDICATORS)
def scrape_with_captcha_detection(urls: list[str]) -> list[dict]:
results = []
session = requests.Session()
session.proxies = {"http": PROXY, "https": PROXY}
captcha_count = 0
backoff = 2.0
for url in urls:
try:
resp = session.get(url, timeout=30)
if resp.status_code == 200 and not is_captcha_page(resp.text):
results.append({"url": url, "status": "success", "body": resp.text})
captcha_count = 0
backoff = max(backoff * 0.9, 1.0) # Reduce backoff on success
elif is_captcha_page(resp.text) or resp.status_code == 403:
captcha_count += 1
results.append({"url": url, "status": "captcha"})
if captcha_count >= 3:
# Too many CAPTCHAs — increase backoff significantly
backoff = min(backoff * 3, 60)
print(f"CAPTCHA streak: {captcha_count}. Backing off to {backoff:.0f}s")
else:
backoff = min(backoff * 1.5, 30)
except requests.RequestException as e:
results.append({"url": url, "status": "error", "error": str(e)})
time.sleep(backoff)
return results
Подробнее о стратегиях лимитов скорости — Лимиты скорости при скрапинге.
Когда CAPTCHA неизбежна: обнаружение и маршрутизация
Даже при идеальном предотвращении некоторые CAPTCHA неизбежны. Встройте обнаружение в конвейер для маршрутизации CAPTCHA-страниц на специальную обработку:
import requests
from enum import Enum
PROXY = "http://USERNAME:PASSWORD@gate.proxyhat.com:8080"
class ResponseType(Enum):
SUCCESS = "success"
CAPTCHA = "captcha"
BLOCKED = "blocked"
ERROR = "error"
def classify_response(resp: requests.Response) -> ResponseType:
"""Classify a response to determine next action."""
if resp.status_code == 403:
return ResponseType.BLOCKED
if resp.status_code == 429:
return ResponseType.BLOCKED
if resp.status_code == 200:
html = resp.text.lower()
captcha_signals = ["captcha", "recaptcha", "hcaptcha", "cf-challenge"]
if any(s in html for s in captcha_signals):
return ResponseType.CAPTCHA
return ResponseType.SUCCESS
return ResponseType.ERROR
def scrape_with_routing(urls: list[str]) -> dict:
"""Scrape URLs and route based on response classification."""
session = requests.Session()
session.proxies = {"http": PROXY, "https": PROXY}
results = {"success": [], "captcha": [], "blocked": [], "error": []}
for url in urls:
try:
resp = session.get(url, timeout=30)
response_type = classify_response(resp)
results[response_type.value].append(url)
if response_type == ResponseType.CAPTCHA:
# Route to CAPTCHA queue for manual or service-based solving
print(f"CAPTCHA detected: {url}")
elif response_type == ResponseType.BLOCKED:
# Rotate IP and retry
print(f"Blocked: {url}")
except requests.RequestException:
results["error"].append(url)
print(f"Success: {len(results['success'])}, "
f"CAPTCHAs: {len(results['captcha'])}, "
f"Blocked: {len(results['blocked'])}")
return results
Чек-лист предотвращения CAPTCHA
- Используйте резидентные прокси. У них наивысший уровень доверия и минимальная частота CAPTCHA. Резидентные прокси ProxyHat предоставляют миллионы чистых IP.
- Устанавливайте реалистичные заголовки. Всегда отправляйте User-Agent, Accept, Accept-Language и другие стандартные браузерные заголовки.
- Добавляйте человекоподобные задержки. Случайные 1-5 секундные задержки с периодическими длинными паузами.
- Правильно поддерживайте сессии. Используйте cookies и постоянные IP для связанных запросов через липкие сессии.
- Уважайте robots.txt. Сайты, обнаружившие нарушение robots.txt, быстрее эскалируют до CAPTCHA.
- Мониторьте частоту CAPTCHA. Если процент CAPTCHA превышает 5%, нужно исправлять подход.
- Избегайте скрапинга в пиковые часы. Антибот-системы агрессивнее в периоды высокого трафика.
- Правильно ротируйте User-Agent. Используйте свежие, реалистичные строки браузеров. Не смешивайте мобильные и десктопные UA в одной сессии.
Настройка прокси на вашем языке: Использование прокси в Python, Использование прокси в Node.js или Использование прокси в Go. Изучите ProxyHat для веб-скрапинга.
Часто задаваемые вопросы
Помогают ли прокси избежать CAPTCHA?
Да, значительно. Качественные резидентные прокси имеют чистую репутацию IP, которая редко вызывает CAPTCHA. Датацентр-IP отмечаются чаще, так как являются известными автоматизированными источниками. Комбинация резидентных прокси с правильными паттернами запросов практически устраняет CAPTCHA для большинства целей.
Какой самый дешёвый способ обработки CAPTCHA в масштабе?
Предотвращение. Инвестиции в резидентные прокси и правильные паттерны скрапинга стоят гораздо меньше, чем сервисы решения в масштабе. Решение стоит $1-3 за 1000, но добавляет 10-60 секунд задержки на запрос.
Помогают ли headless-браузеры с CAPTCHA?
Они помогают с невидимыми CAPTCHA (reCAPTCHA v3, Turnstile), предоставляя реальное браузерное окружение с исполнением JavaScript. Однако они медленнее и ресурсоёмче. Используйте только для целей, специально требующих браузерной верификации.
Как узнать, что я получаю CAPTCHA-страницы?
Проверяйте HTML ответов на индикаторы CAPTCHA: «captcha», «recaptcha», «hcaptcha», «challenge» или «verify you are human». Также отслеживайте неожиданные 403 ответы и редиректы на URL челленджей. Встройте автоматическое обнаружение в конвейер скрапинга.
Почему я всё ещё получаю CAPTCHA с резидентными прокси?
Обычно из-за паттернов запросов, а не качества IP. Частые причины: слишком много запросов в минуту, отсутствие браузерных заголовков, проблемы с обработкой cookies или слишком систематичные паттерны. Замедлитесь, добавьте дрожание и используйте липкие сессии для связанных запросов.






