Любой серьёзный проект по веб-скрейпингу рано или поздно упирается в одну и ту же стену: запросы начинают возвращать CAPTCHA, ошибки 403 или пустые страницы. Сайты научились отлично распознавать автоматизированный трафик, и гонка вооружений между скреперами и антибот-системами как никогда обострилась. Неважно, собираете ли вы данные о ценах, мониторите контент конкурентов или формируете датасеты для обучения ИИ — умение парсить сайты без блокировок уже не опция, а обязательное условие надёжного data-пайплайна.
В этом руководстве разбираем технические причины блокировок, сигналы обнаружения, на которые опираются современные антибот-системы, и проверенные стратегии, позволяющие сохранять работоспособность скреперов. Приводим рабочие примеры кода с использованием резидентных прокси, чтобы показать, как эти концепции применяются на практике.
Почему сайты блокируют скреперы
Прежде чем решать проблему, стоит разобраться, с чем вы имеете дело. Сайты внедряют антибот-защиту по ряду обоснованных причин:
- Защита инфраструктуры — агрессивный скрейпинг может перегрузить серверы, ухудшить работу для реальных пользователей и раздуть расходы на хостинг.
- Защита контента — издатели, интернет-магазины и поставщики данных хотят предотвратить массовое копирование информации конкурентами.
- Безопасность — паттерны автоматизированного трафика пересекаются с credential stuffing, DDoS-атаками и сканированием уязвимостей.
- Регуляторные требования — сайты, обрабатывающие персональные данные, могут ограничивать автоматический доступ для соответствия законодательству о конфиденциальности.
Современные сайты полагаются на специализированные антибот-сервисы: Cloudflare Bot Management, Akamai Bot Manager, PerimeterX и DataDome. Эти сервисы анализируют трафик в реальном времени по совокупности сигналов и обмениваются разведданными между своими сетями — а значит, паттерн, замеченный на одном сайте, может вызвать блокировку на тысячах других.
Сигналы обнаружения, из-за которых вас блокируют
Антибот-системы редко опираются на один-единственный индикатор. Они формируют оценку риска по совокупности сигналов и блокируют запросы, превышающие пороговое значение. Вот основные векторы обнаружения:
Репутация IP-адреса
Это самый фундаментальный сигнал. Диапазоны IP дата-центров хорошо задокументированы и несут изначально повышенный уровень риска. Если ваши запросы идут с AWS, Google Cloud или любого известного хостинг-провайдера, многие антибот-системы немедленно выставят челлендж или заблокируют их. Даже с резидентными IP слишком большое количество запросов с одного адреса приведёт к его флагированию. Базы репутации IP обновляются в реальном времени, и «сожжённый» IP может оставаться в чёрном списке неделями.
Частота и паттерны запросов
Люди не запрашивают 50 страниц в секунду с идеально равными интервалами. Антибот-системы отслеживают частоту запросов, тайминг и навигационный поток. Скрейпинг, который проходит по результатам пагинации строго последовательно с одинаковыми задержками между запросами, выглядит механическим, даже если скорость невысока.
HTTP-фингерпринтинг
У каждого HTTP-клиента есть характерный отпечаток, складывающийся из комбинации отправляемых заголовков: порядка заголовков, характеристик TLS-рукопожатия (JA3/JA4 fingerprint), фреймов настроек HTTP/2 и значений заголовков. У Python-библиотеки requests совершенно другой fingerprint, чем у Chrome. Антибот-системы ведут базы отпечатков реальных браузеров и флагируют всё, что не совпадает.
Браузерный фингерпринтинг и JavaScript-челленджи
Продвинутые антибот-системы выдают JavaScript-челленджи, которые инспектируют окружение браузера: рендеринг canvas, возможности WebGL, установленные шрифты, разрешение экрана, часовой пояс, языковые настройки и сотни других сигналов. Headless-браузеры вроде Puppeteer и Playwright можно обнаружить по тонким различиям — отсутствию плагинов, некорректным дескрипторам свойств объекта navigator или отсутствию ожидаемого поведения при рендеринге.
Поведенческий анализ
Некоторые системы отслеживают движения мыши, паттерны прокрутки и кликов. Сессия, которая переходит сразу на страницы с данными, минуя главную страницу, или в которой мышь вообще не двигается, сигнализирует об автоматизации.
| Сигнал обнаружения | Уровень риска | Сложность нейтрализации | Основная защита |
|---|---|---|---|
| IP-диапазон дата-центра | Критический | Легко | Резидентные прокси |
| Высокая частота запросов | Высокий | Легко | Rate limiting + случайные задержки |
| Отсутствие/неверные заголовки | Высокий | Средне | Реалистичные профили заголовков |
| Несоответствие TLS fingerprint | Высокий | Сложно | Библиотеки подмены TLS fingerprint |
| Провал JavaScript-челленджа | Критический | Сложно | Реальный браузер (Playwright/Puppeteer) |
| Поведенческие аномалии | Средний | Сложно | Имитация поведения пользователя |
| Аномалии cookie/сессий | Средний | Средне | Корректное управление сессиями |
Стратегии парсинга без блокировок
1. Используйте резидентные прокси для ротации IP
Самая эффективная защита от IP-блокировки — маршрутизация запросов через резидентные прокси. Резидентные IP принадлежат реальным интернет-провайдерам и обладают той же репутацией, что и обычные домашние подключения. Антибот-системы не могут массово блокировать резидентные диапазоны, не задев реальных пользователей.
Эффективная ротация прокси означает назначение нового IP каждому запросу или небольшой группе запросов. Для скрейпинга, требующего сохранения состояния сессии (авторизация, многостраничная навигация), используйте sticky-сессии, которые удерживают один IP на заданное время перед ротацией.
ProxyHat обеспечивает автоматическую ротацию с настраиваемым управлением сессиями. Вы можете выбрать IP из конкретной страны, региона или города для доступа к гео-ограниченному контенту с сохранением резидентного уровня доверия.
2. Формируйте реалистичные HTTP-заголовки
Заголовки по умолчанию из библиотек для скрейпинга — верный признак бота. Запрос из Python-библиотеки requests отправляет User-Agent: python-requests/2.31.0 — и моментально детектируется как автоматизированный. Составляйте профили заголовков, точно совпадающие с реальными браузерами:
- Установите актуальную полную строку
User-Agent, соответствующую реальной версии браузера - Включите заголовки
Accept,Accept-Language,Accept-EncodingиSec-CH-UA - Соблюдайте порядок заголовков, характерный для имитируемого браузера
- Ротируйте несколько браузерных профилей, чтобы избежать единого fingerprint
- Добавляйте правдоподобный заголовок
Referer(например, страницу выдачи поисковика)
3. Внедрите умный rate limiting
Равномерные задержки подозрительны почти так же, как их полное отсутствие. Реализуйте рандомизированные задержки с реалистичным распределением:
- Базовая задержка 2–5 секунд между запросами
- Случайный джиттер в пределах 30–50%
- Длинные паузы (15–30 секунд) каждые 20–50 запросов
- Ограничение параллелизма на домен — максимум 2–3 одновременных запроса
- Экспоненциальный backoff при получении сигналов rate limit (коды 429)
4. Корректно управляйте сессиями и cookie
Многие сайты назначают отслеживающие cookie при первом визите и ожидают их в последующих запросах. Скрепер, который никогда не отправляет cookie или отправляет свежие при каждом запросе, попадает под детекцию аномалий. Поддерживайте cookie jar для каждой сессии и передавайте cookie между запросами в рамках логической сессии браузера.
5. Обрабатывайте контент, рендерящийся через JavaScript
Для сайтов, требующих выполнения JavaScript, используйте реальный браузерный движок через Playwright или Puppeteer. Но запуск headless-браузера без мер предосторожности легко детектируется. Ключевые шаги по «закалке»:
- Используйте
playwright-extraилиpuppeteer-extraсо stealth-плагинами - Установите реалистичный размер viewport (не дефолтный 800x600)
- Включите WebGL и подставьте непротиворечивые строки GPU renderer
- Установите часовой пояс и локаль, совпадающие с географией вашего прокси
- Добавьте случайные движения мыши и прокрутку перед извлечением данных
6. Уважайте robots.txt и реализуйте backoff
Хотя robots.txt юридически не обязателен во всех юрисдикциях, его соблюдение демонстрирует добросовестность. На практике сайты, замечающие игнорирование robots.txt, с большей вероятностью применят агрессивную блокировку. Всегда реализуйте автоматический backoff при получении ответов 429 (Too Many Requests) или 503 (Service Unavailable) — это явные сигналы притормозить.
Примеры кода: скрейпинг с резидентными прокси ProxyHat
Следующие примеры демонстрируют настройку ротации резидентных прокси с реалистичными заголовками. В каждом примере используется ProxyHat SDK для соответствующего языка. Полную документацию по API смотрите в документации ProxyHat.
Пример на Python
Установка SDK: pip install proxyhat (GitHub)
import time
import random
from proxyhat import ProxyHatClient
client = ProxyHatClient(
api_key="your_api_key",
country="US",
session_type="rotating", # New IP per request
)
headers = {
"User-Agent": "Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/131.0.0.0 Safari/537.36",
"Accept": "text/html,application/xhtml+xml,application/xml;q=0.9,image/avif,image/webp,*/*;q=0.8",
"Accept-Language": "en-US,en;q=0.9",
"Accept-Encoding": "gzip, deflate, br",
"Sec-CH-UA": '"Chromium";v="131", "Not_A Brand";v="24"',
"Sec-CH-UA-Mobile": "?0",
"Sec-CH-UA-Platform": '"Windows"',
}
urls = [
"https://example.com/page/1",
"https://example.com/page/2",
"https://example.com/page/3",
]
for url in urls:
response = client.get(url, headers=headers)
print(f"{response.status_code} - {url} via {response.proxy_ip}")
# Randomized delay: 2-5 seconds with jitter
delay = random.uniform(2.0, 5.0)
time.sleep(delay)
Пример на Node.js
Установка SDK: npm install @proxyhat/sdk (GitHub)
const { ProxyHatClient } = require("@proxyhat/sdk");
const client = new ProxyHatClient({
apiKey: "your_api_key",
country: "US",
sessionType: "rotating",
});
const headers = {
"User-Agent":
"Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/131.0.0.0 Safari/537.36",
Accept:
"text/html,application/xhtml+xml,application/xml;q=0.9,image/avif,image/webp,*/*;q=0.8",
"Accept-Language": "en-US,en;q=0.9",
};
const urls = [
"https://example.com/page/1",
"https://example.com/page/2",
"https://example.com/page/3",
];
async function scrape() {
for (const url of urls) {
const response = await client.get(url, { headers });
console.log(`${response.status} - ${url} via ${response.proxyIp}`);
// Randomized delay between requests
const delay = 2000 + Math.random() * 3000;
await new Promise((r) => setTimeout(r, delay));
}
}
scrape();
Пример на Go
Установка SDK: go get github.com/ProxyHatCom/go-sdk (GitHub)
package main
import (
"fmt"
"math/rand"
"time"
proxyhat "github.com/ProxyHatCom/go-sdk"
)
func main() {
client := proxyhat.NewClient(&proxyhat.Config{
APIKey: "your_api_key",
Country: "US",
SessionType: proxyhat.Rotating,
})
headers := map[string]string{
"User-Agent": "Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/131.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",
}
urls := []string{
"https://example.com/page/1",
"https://example.com/page/2",
"https://example.com/page/3",
}
for _, url := range urls {
resp, err := client.Get(url, proxyhat.WithHeaders(headers))
if err != nil {
fmt.Printf("Error: %v\n", err)
continue
}
fmt.Printf("%d - %s via %s\n", resp.StatusCode, url, resp.ProxyIP)
// Randomized delay: 2-5 seconds
delay := time.Duration(2000+rand.Intn(3000)) * time.Millisecond
time.Sleep(delay)
}
}
Sticky-сессии для многостраничных сценариев
Некоторые задачи скрейпинга требуют сохранения одного IP-адреса на протяжении нескольких запросов — например, при навигации по пагинированному каталогу товаров, поддержании авторизованной сессии или прохождении многошагового формы. ProxyHat поддерживает sticky-сессии, которые удерживают один и тот же резидентный IP на настраиваемый период.
# Python: Sticky session example
from proxyhat import ProxyHatClient
client = ProxyHatClient(
api_key="your_api_key",
country="DE",
session_type="sticky",
session_ttl=300, # Same IP for 5 minutes
)
# All requests within the session use the same IP
response1 = client.get("https://example.com/login", headers=headers)
response2 = client.post("https://example.com/login", data=credentials, headers=headers)
response3 = client.get("https://example.com/dashboard", headers=headers)
print(f"Session IP: {response1.proxy_ip}") # Same IP for all three requests
Типичные ошибки, приводящие к блокировкам
Даже опытные разработчики допускают эти ошибки. Каждая из них расходует трафик и приводит к ненужному сжиганию IP:
- Использование заголовков по умолчанию — строка User-Agent
python-requestsесть в каждом блоклисте. Всегда задавайте кастомные заголовки. - Игнорирование TLS fingerprint — ваши заголовки могут говорить «Chrome», но TLS-рукопожатие выдаёт Python. Используйте библиотеки вроде
curl_cffiилиtls-client, имитирующие TLS fingerprint реального браузера. - Слишком быстрый старт — начинайте медленно. Наращивайте частоту запросов постепенно, за часы, а не за минуты.
- Некорректная обработка ошибок — немедленная повторная отправка заблокированного запроса с той же конфигурацией тратит трафик и подтверждает, что вы бот. Реализуйте backoff и переключайте прокси-сессию при ошибках.
- Повторное использование «сожжённых» IP — если запрос вернул CAPTCHA или страницу блокировки, этот IP скомпрометирован для данного сайта. Немедленно переключайтесь на новую сессию.
- Игнорирование географической согласованности — запросы с американского IP с заголовком
Accept-Language: jaи смещением часового пояса +9 выглядят подозрительно. Согласовывайте заголовки и настройки браузера с локацией прокси. - Отсутствие мониторинга success rate — без отслеживания процента блокировок вы не поймёте, работает ли ваша стратегия. Логируйте статус каждого ответа и настройте алерты при падении success rate.
Продвинутые техники для защищённых сайтов
Рандомизация fingerprint
Для сайтов с серьёзной защитой ротируйте не только IP, но и целые профили браузерного fingerprint. Каждая сессия должна иметь согласованную комбинацию User-Agent, разрешения экрана, часового пояса, языка и платформы — и эти комбинации должны соответствовать реальным. Windows User-Agent с Linux platform string — очевидный красный флаг.
Имитация цепочки запросов
Реальные пользователи не переходят сразу на страницы товаров. Они приходят из поисковых систем, просматривают категории и переходят по внутренним ссылкам. Стройте скрепер так, чтобы он имитировал реалистичные навигационные пути: загрузите главную страницу, перейдите на страницы категорий, а затем обратитесь к целевым данным. Это формирует правдоподобный паттерн сессии.
Особенности парсинга поисковой выдачи
Скрейпинг поисковых систем имеет свои особенности, поскольку Google, Bing и другие используют особенно агрессивную антибот-защиту. Резидентные прокси обязательны для стабильного мониторинга SERP, и запросы стоит распределять по нескольким географическим локациям, чтобы не попасть под rate limit из одного региона.
Выбор подходящего типа прокси
Не каждая задача скрейпинга требует резидентных прокси. Правильный выбор зависит от защиты целевого сайта и вашего бюджета. Подробное сравнение — в нашей статье о типах прокси: резидентные, дата-центр и мобильные. А вот краткая матрица решений:
| Сценарий | Рекомендуемый тип прокси | Причина |
|---|---|---|
| Общий веб-скрейпинг | Резидентные ротируемые | Лучший баланс доверия и стоимости |
| Мониторинг цен в e-commerce | Резидентные ротируемые | Серьёзная антибот-защита у большинства ритейлеров |
| Мониторинг SERP | Резидентные с геотаргетингом | Поисковики агрессивно блокируют IP дата-центров |
| Парсинг соцсетей | Мобильные прокси | Максимальное доверие для платформ, ожидающих мобильный трафик |
| Доступ к публичным API | Дата-центр | Низкий риск антибот-защиты, самый бюджетный вариант |
| Сникер/билетные сайты | Резидентные sticky | Персистентность сессии с резидентным доверием |
Для большинства проектов скрейпинга резидентные ротируемые прокси обеспечивают лучшее сочетание надёжности и экономичности. Тарифы ProxyHat рассчитываются по потреблению трафика — вы платите только за успешную передачу данных.
Ключевые выводы
- Резидентные прокси — основа — IP дата-центров блокируются мгновенно на большинстве защищённых сайтов. Резидентные IP обладают естественным доверием.
- Заголовки важны не меньше IP — резидентный IP с дефолтными заголовками Python всё равно блокируется. Формируйте полные реалистичные профили заголовков.
- Рандомизируйте всё — задержки, комбинации заголовков, навигационные пути. Предсказуемые паттерны — детектируемые паттерны.
- Мониторьте и адаптируйтесь — отслеживайте success rate. При росте блокировок разбирайтесь в причинах и корректируйте стратегию, прежде чем сжечь пул прокси.
- Согласовывайте fingerprint — каждый сигнал должен рассказывать единую историю: User-Agent, TLS fingerprint, часовой пояс, язык и геолокация должны совпадать.
- Начинайте медленно, масштабируйте постепенно — стартуйте с консервативных rate limit и увеличивайте только после подтверждения стабильной работы.
- Sticky-сессии для stateful-сценариев — авторизация и многостраничная навигация требуют постоянства IP. Используйте sticky-сессии с подходящим TTL.
Часто задаваемые вопросы
Как понять, что мой скрепер блокируют?
Типичные признаки: HTTP-коды 403 или 429, редирект на страницу CAPTCHA, пустое тело ответа вместо ожидаемого HTML или содержимое, отличающееся от того, что видно в обычном браузере. Отслеживайте статус-коды и размер ответа — резкое падение среднего размера часто указывает на «мягкие» блокировки, когда сайт возвращает страницу челленджа вместо реального контента.
Достаточно ли резидентных прокси, чтобы избежать всех блокировок?
Резидентные прокси устраняют IP-блокировку — самый распространённый метод детекции, — но сами по себе не являются полным решением. Вам по-прежнему нужны реалистичные заголовки, грамотный rate limiting и управление сессиями. Думайте о резидентных прокси как о фундаменте: они решают самую сложную проблему (репутация IP), но остальные слои вашего скрейпинг-стека тоже должны быть на высоте. Для самых защищённых сайтов комбинируйте резидентные прокси с имитацией браузерного fingerprint через curl_cffi или Playwright со stealth-настройками.
Сколько запросов в секунду можно отправлять без блокировки?
Универсального ответа нет — всё зависит от защиты целевого сайта. Как консервативная точка отсчёта: ограничьтесь 1 запросом каждые 2–5 секунд на домен при ротации IP. Для менее защищённых сайтов можно постепенно увеличить до 5–10 параллельных запросов. Для серьёзно защищённых сайтов вроде Google или Amazon держитесь в рамках 1 запроса за 3 секунды даже с резидентными прокси. Наращивайте постепенно и следите за success rate — если он падает ниже 95%, вы идёте слишком быстро.
В чём разница между rotating и sticky прокси-сессиями?
Rotating-сессии назначают новый IP каждому запросу — это идеальный вариант для парсинга независимых страниц, где состояние между запросами не сохраняется. Sticky-сессии удерживают один IP на заданное время (обычно 1–30 минут), что необходимо для авторизации, пагинации и любых многошаговых процессов, где сервер отслеживает ваш IP. Используйте rotating по умолчанию и переключайтесь на sticky только тогда, когда ваш сценарий действительно требует непрерывности сессии.
Легален ли веб-скрейпинг?
Легальность веб-скрейпинга зависит от юрисдикции, типа собираемых данных и способа их использования. В США решение по делу hiQ Labs против LinkedIn (2022) установило, что скрейпинг публично доступных данных не нарушает Computer Fraud and Abuse Act. В ЕС на персональные данные распространяется GDPR вне зависимости от способа сбора. Общее правило: скрейпинг публично доступных неперсональных данных в легитимных коммерческих целях в целом считается допустимым. Всегда изучайте Terms of Service целевого сайта, уважайте robots.txt и проконсультируйтесь с юристом для вашего конкретного случая.






