Как работает обнаружение Cloudflare
Cloudflare — наиболее широко развёрнутая антибот-служба, защищающая более 20% всех сайтов. Понимание механизмов обнаружения автоматизированного трафика необходимо для всех, кто создаёт легитимные инструменты скрапинга. Cloudflare использует многоуровневый конвейер обнаружения:
- Оценка репутации IP: Cloudflare ведёт глобальную базу данных угроз. IP дата-центров, диапазоны VPN и ранее помеченные адреса получают более высокую оценку риска.
- TLS-фингерпринтинг: Cloudflare анализирует TLS-сообщения ClientHello для определения соответствия клиента заявленной идентичности.
- Браузерный фингерпринтинг: JavaScript-вызовы проверяют canvas, WebGL, свойства navigator и десятки других сигналов.
- JavaScript-вызовы: Cloudflare выдаёт JavaScript, который должен корректно выполниться в реальной среде браузера.
- Поведенческий анализ: Анализируются тайминг запросов, паттерны навигации, движения мыши и сигналы взаимодействия.
- Модели машинного обучения: Все сигналы передаются в ML-модели, непрерывно адаптирующиеся к новым паттернам автоматизации.
Общий обзор — в нашем комплексном руководстве по антибот-системам.
Уровни защиты Cloudflare
| Уровень | Методы обнаружения | Сложность | Типичные сайты |
|---|---|---|---|
| Basic (бесплатный) | Репутация IP, базовый JS-вызов | Низкая | Маленькие блоги, личные сайты |
| Pro | + WAF-правила, ограничение скорости | Средняя | Средний бизнес, SaaS |
| Business | + Продвинутое управление ботами | Высокая | Электронная коммерция, корпоративные сайты |
| Enterprise | + ML-скоринг ботов, поведенческий анализ | Очень высокая | Крупные ритейлеры, финансовые сервисы |
Этические рамки доступа к сайтам с Cloudflare
Перед реализацией технических подходов установите чёткие этические границы:
- Проверьте наличие API: Многие сайты с Cloudflare предлагают официальные API. Всегда предпочитайте их.
- Уважайте robots.txt: Если сайт явно запрещает скрапинг определённых путей, соблюдайте эти директивы.
- Изучите условия использования: Поймите, что сайт разрешает в отношении автоматизированного доступа.
- Только публичные данные: Никогда не пытайтесь обойти аутентификацию или получить доступ к приватным данным.
- Минимальная нагрузка на сервер: Используйте разумную частоту запросов и не перегружайте целевой сервер.
- Рассмотрите лицензирование данных: Для коммерческих случаев изучите соглашения о лицензировании данных.
Техники в этом руководстве предназначены для легитимного доступа к публично доступным данным. Они не должны использоваться для обхода защиты ради несанкционированного доступа, кражи учётных данных или атак типа «отказ в обслуживании».
Стратегия 1: Резидентные прокси с чистыми IP
Наиболее эффективный первый шаг — обеспечить чистую репутацию IP-адресов. Скоринг IP Cloudflare сильно штрафует дата-центровые и VPN-адреса.
# Python: резидентные прокси для сайтов с Cloudflare
from curl_cffi import requests as curl_requests
response = curl_requests.get(
"https://cloudflare-protected-site.com",
impersonate="chrome",
proxies={
"http": "http://USERNAME:PASSWORD@gate.proxyhat.com:8080",
"https": "http://USERNAME:PASSWORD@gate.proxyhat.com:8080"
},
timeout=30
)
if response.status_code == 200:
print("Access granted")
elif response.status_code == 403:
print("Blocked — may need additional measures")
elif response.status_code == 503:
print("Cloudflare challenge page — need browser execution")
Резидентные прокси ProxyHat обеспечивают IP, классифицированные как подлинные резидентные адреса в базе Cloudflare, обходя уровень репутации IP. Подробнее — в нашем сравнении резидентных прокси и VPN.
Стратегия 2: TLS-отпечатки браузерного уровня
Cloudflare проверяет TLS-отпечатки JA3/JA4 для идентификации подключающегося клиента. Python requests, Go net/http и стандартные клиенты Node.js создают небраузерные TLS-сигнатуры, которые Cloudflare помечает.
| Клиент | Результат Cloudflare | Причина |
|---|---|---|
| Python requests | Блокировка или вызов | OpenSSL TLS-отпечаток не является браузерным |
| curl_cffi (impersonate="chrome") | Обычно проходит | Имитирует отпечаток Chrome BoringSSL |
| Безголовый Chrome (Puppeteer/Playwright) | Обычно проходит | Реальный TLS-стек BoringSSL |
| Go net/http | Блокировка или вызов | Отпечаток Go crypto/tls характерен |
| Go с uTLS (Chrome hello) | Обычно проходит | Имитирует отпечаток Chrome |
Стратегия 3: Обработка JavaScript-вызовов
JavaScript-вызовы Cloudflare требуют реальной среды браузера. Два подхода:
Подход A: Безголовый браузер
// Node.js: Playwright со стелсом для вызовов Cloudflare
const { chromium } = require('playwright');
async function accessCloudflare(url) {
const browser = await chromium.launch({
proxy: {
server: 'http://gate.proxyhat.com:8080',
username: 'USERNAME',
password: 'PASSWORD'
}
});
const context = await browser.newContext({
locale: 'en-US',
timezoneId: 'America/New_York',
viewport: { width: 1920, height: 1080 }
});
const page = await context.newPage();
// Навигация и ожидание решения вызова Cloudflare
await page.goto(url, { waitUntil: 'networkidle', timeout: 60000 });
// Вызовы Cloudflare обычно редиректят после завершения
await page.waitForSelector('body', { timeout: 30000 });
// Проверка прохождения вызова
const title = await page.title();
if (title.includes('Just a moment') || title.includes('Attention Required')) {
// Вызов ещё не решён — ждём дольше
await page.waitForNavigation({ waitUntil: 'networkidle', timeout: 30000 });
}
const content = await page.content();
await browser.close();
return content;
}
Подход B: Извлечение и повторное использование куки
Решите вызов один раз в безголовом браузере, извлеките куки (особенно cf_clearance), затем используйте их в лёгком HTTP-клиенте:
// Node.js: извлечение куки Cloudflare для повторного использования
const { chromium } = require('playwright');
async function extractCfCookies(url) {
const browser = await chromium.launch({
proxy: {
server: 'http://gate.proxyhat.com:8080',
username: 'USERNAME-session-cf1',
password: 'PASSWORD'
}
});
const context = await browser.newContext({
locale: 'en-US',
timezoneId: 'America/New_York',
});
const page = await context.newPage();
await page.goto(url, { waitUntil: 'networkidle', timeout: 60000 });
// Ожидание решения вызова
await page.waitForTimeout(10000);
// Извлечение куки
const cookies = await context.cookies();
const cfClearance = cookies.find(c => c.name === 'cf_clearance');
const userAgent = await page.evaluate(() => navigator.userAgent);
await browser.close();
return { cookies, userAgent, cfClearance };
}
// Повторное использование куки с got-scraping (та же сессия прокси!)
import { gotScraping } from 'got-scraping';
const { cookies, userAgent } = await extractCfCookies('https://example.com');
const cookieString = cookies.map(c => `${c.name}=${c.value}`).join('; ');
const response = await gotScraping({
url: 'https://example.com/api/data',
proxyUrl: 'http://USERNAME-session-cf1:PASSWORD@gate.proxyhat.com:8080',
headers: {
'Cookie': cookieString,
'User-Agent': userAgent, // Должен совпадать с браузером, решившим вызов
}
});
Важно: Куки cf_clearance привязаны к IP-адресу и user-agent, решившим вызов. При повторном использовании обязательно используйте ту же сессию прокси (sticky IP) и идентичный user-agent.
Стратегия 4: Оптимизация паттернов запросов
Поведенческий анализ Cloudflare помечает нечеловеческие паттерны запросов. Следуйте этим паттернам для легитимного доступа:
Реалистичный поток навигации
# Python: реалистичный паттерн навигации
from curl_cffi import requests as curl_requests
import time
import random
session = curl_requests.Session(impersonate="chrome")
session.proxies = {
"http": "http://USERNAME:PASSWORD@gate.proxyhat.com:8080",
"https": "http://USERNAME:PASSWORD@gate.proxyhat.com:8080"
}
# Шаг 1: сначала главная страница
home = session.get("https://example.com")
time.sleep(random.uniform(2.0, 4.0))
# Шаг 2: переход к категории (с Referer)
category = session.get(
"https://example.com/products",
headers={"Referer": "https://example.com"}
)
time.sleep(random.uniform(1.5, 3.5))
# Шаг 3: просмотр товаров (с правильной цепочкой Referer)
for item_url in item_urls[:20]:
item = session.get(
item_url,
headers={"Referer": "https://example.com/products"}
)
time.sleep(random.uniform(1.0, 3.0))
Рекомендации по ограничению скорости
| Уровень Cloudflare | Безопасная частота запросов | Задержка между запросами |
|---|---|---|
| Basic/Free | 20-30 запр/мин | 2-3 секунды |
| Pro | 10-20 запр/мин | 3-6 секунд |
| Business | 5-10 запр/мин | 6-12 секунд |
| Enterprise | 2-5 запр/мин | 12-30 секунд |
Стратегия 5: Обработка типичных ответов Cloudflare
| Код статуса | Значение | Действие |
|---|---|---|
| 200 | Успех | Парсинг контента как обычно |
| 403 | Запрещено — IP или отпечаток заблокирован | Ротация на новый IP, проверка TLS-отпечатка |
| 429 | Ограничение скорости | Экспоненциальный откат, снижение частоты |
| 503 | JavaScript-вызов | Использование безголового браузера |
| 520-527 | Ошибки сервера Cloudflare | Повтор с задержкой — проблема origin-сервера |
# Python: обработка ответов с логикой повторов
import time
import random
def cloudflare_resilient_request(session, url, max_retries=3):
for attempt in range(max_retries):
try:
response = session.get(url, timeout=30)
if response.status_code == 200:
return response
if response.status_code == 403:
# IP помечен — ротация сессии
print(f"403 on attempt {attempt + 1} — rotating IP")
session = create_new_session()
time.sleep(random.uniform(5, 10))
continue
if response.status_code == 429:
# Ограничение скорости — экспоненциальный откат
wait = (2 ** attempt) * 5 + random.uniform(0, 5)
print(f"429 — waiting {wait:.1f}s")
time.sleep(wait)
continue
if response.status_code == 503:
# JS-вызов — нужен безголовый браузер
print("503 — JavaScript challenge detected")
return None # Эскалация на браузерный подход
except Exception as e:
print(f"Error: {e}")
time.sleep(random.uniform(2, 5))
return None
Комплексный многоуровневый подход
Наиболее надёжная стратегия объединяет все уровни:
- Резидентные прокси: Резидентные IP ProxyHat для чистой репутации IP.
- TLS браузерного уровня:
curl_cffiили безголовый браузер для корректных отпечатков. - Согласованные заголовки: Полные наборы заголовков, соответствующие заявленному браузеру.
- Естественный тайминг: Рандомизированные задержки по паттернам человеческого просмотра.
- Управление куки: Принятие и поддержание куки на протяжении сессий.
- Цепочки Referer: Правильный поток навигации от главной к целевым страницам.
Комплексные стратегии снижения обнаружения — в нашем полном руководстве по антидетекту. Интеграция прокси для языков программирования — в руководствах по Python, Node.js и Go.
Когда не стоит скрапить
Распознавайте ситуации, когда скрапинг — неправильный подход:
- У сайта есть публичный API: Всегда используйте официальные API, когда они доступны.
- Данные за аутентификацией: Доступ к данным за логином через скрапинг обычно нарушает ToS.
- Сайт явно запрещает скрапинг: Уважайте чёткие запреты в условиях использования.
- Доступно лицензирование данных: Для коммерческого использования покупка лицензий часто надёжнее и легальнее.
- Контент защищён авторским правом: Скрапинг для перераспространения вызывает правовые вопросы.
Руководство по ответственному использованию — в документации ProxyHat.






