# Cloudflare "Just a Moment" на Python: Почему requests не работает

Страница Cloudflare 'Just a moment...' представляет собой JavaScript-задачу, и Python requests не может выполнять JavaScript. Вот как её обнаружить, почему она сильнее нагружает серверы, чем ноутбуки, почему трюки в стиле cloudscraper перестали быть достаточными, и что прошло в нашем тесте 29 сентября 2026 года.

'Just a moment...' — это страница с задачей от Cloudflare. Она просит клиента выполнить JavaScript и доказать, что это браузер, прежде чем сайт ответит. Python requests не может выполнять JavaScript, и с IP-адреса датацентра его IP и TLS рукопожатие уже выглядят автоматизированными. То, что проходит, — это реальный браузер на чистом IP или веб-разблокировщик, который его использует.

Это руководство показывает, как обнаружить задачу на Python, почему тот же скрипт проходит на вашем ноутбуке и не проходит на вашем сервере, почему трюки эпохи cloudscraper перестали быть достаточными, и что на самом деле прошло, когда мы тестировали это 29 сентября 2026 года.

- **Это задача, а не ошибка.** Cloudflare маркирует ответы с задачей заголовком `cf-mitigated: challenge`. В нашем тесте они приходили как HTTP 403.
- **Заголовки не исправят это.** 'Enable JavaScript and cookies to continue' означает, что странице нужен JavaScript-движок. Ни одна строка User-Agent его не предоставляет.
- **Сервер против ноутбука** — это в основном репутация IP плюс TLS отпечаток. Один только жилой IP не прошел Indeed или Glassdoor в нашем тесте.
- **Что прошло:** Web Unlocker прошел Glassdoor (после безголового браузера, 17,2 с) и Indeed (с первой попытки, 2,6 с).
- **Закрепите сессию.** Повторное использование clearance браузера сократило второй запрос к Glassdoor с 14,0 с до 1,4 с в нашем тесте.

## Что на самом деле представляет собой страница "Just a moment..."

Cloudflare называет это промежуточной страницей с задачей: это полностраничный барьер между посетителем и сайтом, пока Cloudflare решает, является ли посетитель автоматизированным. В её [документации по страницам с задачами](https://developers.cloudflare.com/cloudflare-challenges/challenge-types/challenge-pages/) описаны три вида. Неинтерактивная задача требует только, чтобы браузер выполнил внедренный JavaScript. Управляемая задача позволяет Cloudflare выбрать тип задачи из сигналов запроса. Интерактивная задача просит посетителя что-то сделать. Когда проверка проходит, оригинальный запрос продолжается к сайту, и браузер получает cookie `cf_clearance`, которое позволяет ему пропускать барьер на некоторое время.

Клиент HTTP на Python никогда не доходит так далеко. Он загружает страницу с задачей, не имеет движка для выполнения скрипта и передает вам HTML барьера вместо страницы, которую вы запросили.

## Почему задача возвращается как 403 и как её обнаружить

В нашем тесте каждая страница с задачей приходила со статусом 403, поэтому `raise_for_status()` выдает `403 Client Error: Forbidden`, и люди ищут 'cloudflare just a moment 403'. Один статус не может отличить задачу от любого другого отказа. Надежный сигнал — это заголовок: Cloudflare [документирует, что ответ с задачей несет cf-mitigated: challenge](https://developers.cloudflare.com/cloudflare-challenges/challenge-types/challenge-pages/detect-response/), независимо от запрашиваемого ресурса. Сначала проверьте это, затем заголовок как запасной вариант:

```python
import re
import requests

URL = "https://www.glassdoor.com/Reviews/Google-Reviews-E9079.htm"
HEADERS = {
    "User-Agent": (
        "Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 "
        "(KHTML, like Gecko) Chrome/150.0.0.0 Safari/537.36"
    ),
    "Accept-Language": "en-US,en;q=0.9",
}

def title_of(html: str) -> str:
    m = re.search(r"<title[^>]*>(.*?)</title>", html, re.I | re.S)
    return m.group(1).strip() if m else ""

def is_cloudflare_challenge(r: requests.Response) -> bool:
    if r.headers.get("cf-mitigated") == "challenge":      # documented by Cloudflare
        return True
    if "just a moment" in title_of(r.text).lower():
        return True
    return "enable javascript and cookies to continue" in r.text[:20000].lower()

r = requests.get(URL, headers=HEADERS, timeout=30)
print(r.status_code, is_cloudflare_challenge(r), title_of(r.text))
# 29 Sep 2026, plain request through a residential proxy (US exit):
# 403, body asking to 'Enable JavaScript and cookies to continue'
```

Не повторяйте запрос с задачей в плотном цикле с тем же клиентом. Каждая повторная попытка загружает тот же барьер, и некоторые сайты отвечают на повторные неудачи более строгими правилами. Так скрейперы застревают в цикле 'Just a moment'.

## "Enable JavaScript and cookies to continue" и "your browser does not support JavaScript"

Эти строки — резервный текст страницы с задачей, показываемый клиентам, которые не выполняют её скрипт. Когда Python requests показывает вам одну из них, сайт не жалуется на ваши заголовки. Он буквально говорит вам, что ему нужен JavaScript-движок и контейнер для cookie, который сохраняет то, что устанавливает скрипт.

Это именно то, что наш простой жилой запуск получил от Indeed и Glassdoor: 403 с 'Enable JavaScript and cookies to continue', с чистого домашнего IP. Добавление Chrome User-Agent, заголовка Accept-Language или Referer ничего не меняет, потому что страница не читает их для принятия решения. Она ждет выполнения скрипта.

## Почему ваш скрейпер работает локально, но блокируется Cloudflare на сервере

Это самая распространенная версия жалобы: скрипт работает на ноутбуке, затем получает 'Just a moment', как только запускается на облачном VM. Две вещи меняются между этими машинами.

- **IP.** На вашем ноутбуке скрипт выходит с адреса домашнего интернет-провайдера. На VM он выходит из диапазона хостинг-провайдера, который защиты от ботов оценивают как вероятно автоматизированный, прежде чем они читают что-либо еще. Наш сервер в датацентре во Франкфурте был отклонен Glassdoor, Indeed, Zillow и Leboncoin, среди прочих.
- **TLS отпечаток.** Рукопожатие Python выглядит как Python на обеих машинах, но на домашнем IP сайт может его терпеть, а на хостинговом IP редко будет. Наше объяснение на [curl_cffi vs requests](https://quantumproxies.io/blog/curl-cffi-vs-requests) показывает, насколько рукопожатие контролируется библиотекой.

Жилая колонка нашего теста показывает предел исправления только IP. Zillow и Leboncoin обслужили реальную страницу на простой запрос через жилой прокси. Indeed и Glassdoor все еще ответили JavaScript-задачей. Ваш ноутбук может столкнуться с той же стеной на более строгом сайте. Он просто сталкивается с ней реже.

![Один и тот же скрипт на Python requests на двух машинах: с ноутбука на домашнем IP провайдера страница часто загружается, а с облачного сервера на хостинговом IP Cloudflare отвечает проверкой «Just a moment». Карточка показывает, что меняется (выходной IP), а что нет: TLS-рукопожатие Python и отсутствие JavaScript-движка.](https://res.cloudinary.com/dmqliab0t/image/upload/f_auto,q_auto,w_1200/v1790701776/blog/generated/qp-unl-g3-diag1.png)
*Тот же скрипт, две машины. IP меняется; TLS рукопожатие Python и отсутствие JavaScript-движка не меняются.*

## Почему трюки эпохи cloudscraper перестают работать

[cloudscraper](https://github.com/VeNoMouS/cloudscraper) был создан для старой страницы Cloudflare 'I'm Under Attack'. Эта страница в основном проверяла, может ли клиент выполнить JavaScript-вычисление, поэтому библиотека загружала задачу, решала скрипт в встроенном интерпретаторе, отправляла ответ обратно и сохраняла cookie, все это поверх `requests`. Долгое время этого было достаточно, и это причина, по которой 'cloudscraper alternative' теперь является популярным поисковым запросом.

С тех пор многое изменилось, и это не зависит от какой-либо одной версии библиотеки:

- **Рукопожатие все еще говорит Python.** Библиотека, построенная на requests, подключается через TLS стек Python, поэтому ClientHello не соответствует браузеру, которым заявляет быть его User-Agent. Это несоответствие видно до того, как запускается любой JavaScript.
- **Задача больше не только арифметическая.** Управляемые задачи выбирают проверку из сигналов запроса, и JavaScript-детекции Cloudflare читают окружение браузера. Интерпретатор, который оценивает скрипт, не является браузером, который рендерит страницу.
- **Clearance привязан к клиенту.** Документация Cloudflare по [clearance](https://developers.cloudflare.com/cloudflare-challenges/concepts/clearance/) говорит, что cookie cf_clearance привязано к посетителю и устройству, которому оно было выдано, чтобы предотвратить повторное использование на других машинах. Копирование одного из вашего браузера в скрипт на другой машине предназначено для неудачи.
- **IP все еще ваш.** Решение страницы не меняет IP из диапазона хостинга, и некоторые сайты отказываются от них до того, как будет выдана какая-либо задача.

На 29 сентября 2026 года последний push в репозитории cloudscraper был в июне 2025 года. Это не приговор для какого-либо конкретного сайта, и мы не проводили его бенчмаркинг для этой статьи. Это означает, что вы должны тестировать его на своих собственных целях, а не предполагать, что он работает. Альтернативы исправляют каждую часть проблемы. curl_cffi воспроизводит рукопожатие браузера TLS, но не выполняет JavaScript. Playwright или другой реальный браузер выполняет задачу, но все же нуждается в чистом IP, и его тяжело использовать в больших объемах. Разблокировщик комбинирует оба и сообщает вам, когда ни один из них не сработал.

## Что проходит: путь веб-разблокировщика

Web Unlocker от QuantumProxies.io обрабатывает GET поэтапно. Сначала до трех попыток TLS, каждая на свежем жилом выходе под разным отпечатком браузера. Если каждая попытка возвращается с задачей, он переходит к безголовому браузеру, который выполняет задачу. Если страница все еще заблокирована после этого, вы получаете статус ошибки с `x-qp-unlocker-blocked` и классом блокировки, никогда не страницу задачи, замаскированную под 200. С Python это настройка прокси:

```python
import os
import time
import requests
import urllib3

urllib3.disable_warnings(urllib3.exceptions.InsecureRequestWarning)

user = os.environ["QP_UNLOCK_USER"] + "-country-us"          # unlock-XXXXXXXX-country-us
PROXY = f"http://{user}:{os.environ['QP_UNLOCK_PASSWORD']}@unlock.quantumproxies.io:9000"

s = requests.Session()
s.proxies = {"http": PROXY, "https": PROXY}
s.verify = False                     # or the unlocker CA file from /api/v1/scraper/unlock/ca
s.headers["x-qp-session"] = "glassdoor-01"   # same value on every call: same exit, reusable clearance

for attempt in (1, 2):               # same page twice here; in practice, the next page
    t0 = time.monotonic()
    r = s.get(URL, timeout=120)
    print(attempt, r.status_code, f"{time.monotonic() - t0:.1f}s",
          "rendered:", r.headers.get("x-qp-unlocker-rendered"),
          "clearance:", r.headers.get("x-qp-clearance"),
          "block:", r.headers.get("x-qp-block-class"))
```

Заголовки `x-qp-*` читаются разблокировщиком и никогда не пересылаются на сайт. Если вы предпочитаете вообще не иметь дело с сертификатом, REST endpoint `POST https://app.quantumproxies.io/api/v1/scraper/unlock` принимает URL в теле JSON с вашим API ключом и возвращает `blocked`, `blockClass` и `vendor` в ответе. Наш [учебник по API веб-разблокировщика](https://quantumproxies.io/blog/web-unlocker-api-tutorial-python) проходит через оба.

## Измерено: два типа защиты в стиле Cloudflare, которые были пройдены

Измерено 29 сентября 2026 года. Простые запросы были curl с Chrome User-Agent, с сервера в датацентре во Франкфурте и через жилой прокси с выходом в США. Разблокировщик использовал жилой уровень с выходом в США. Время указано по часам для одного запроса.

| Сайт | Простой, сервер датацентра | Простой, жилой прокси | Web Unlocker |
| --- | --- | --- | --- |
| Glassdoor (обзоры компаний) | 403, страница 'Безопасность' | 403, 'Enable JavaScript and cookies to continue' | 200, 2 попытки + безголовый браузер, 17,2 с |
| Indeed (поиск работы) | 403, страница 'Проверка безопасности' | 403, 'Enable JavaScript and cookies to continue' | 200, 1 попытка, без браузера, 2,6 с |

Glassdoor — это полный путь. Две попытки TLS были с задачей, затем безголовый браузер выполнил задачу и вернул страницу с обзорами. Indeed — это интересный случай: задача, которую простой жилой запрос получил, никогда не появилась для первой попытки разблокировщика. Отпечаток браузера TLS на свежем жилом выходе был достаточным, без браузера.

[Обходите JavaScript-задачи с помощью Web Unlocker](https://quantumproxies.io/web-unlocker)

## Повторное использование clearance: почему второй запрос быстрый

Эскалация браузера — это медленная часть, и вы не хотите платить за неё на каждой странице. Когда безголовый браузер проходит задачу, он зарабатывает clearance. Отправьте то же значение `x-qp-session`, или сохраните тот же `-session-<id>` в имени пользователя прокси, на следующих запросах, и они будут выходить из того же выхода, повторно используя этот clearance вместо повторного запуска браузера. Заголовок `x-qp-clearance` сообщает вам, что произошло на каждом вызове: `minted`, когда был заработан новый clearance, `hit`, когда использовался сохраненный, `miss`, когда не было ничего для повторного использования.

В тесте Glassdoor 29 сентября 2026 года, с закрепленной сессией в имени пользователя прокси и двумя отдельными соединениями, первый запрос прошел через браузер за 14,0 секунды (`minted`), а второй вернулся за 1,4 секунды (`hit`). Закрепление имеет значение из-за того, как Cloudflare связывает clearance: он привязан к посетителю и устройству, которое его заработало, и остается действительным на время, которое сайт настраивает, если только Cloudflare не решит, что сессия выглядит подозрительно. Измените выход или отпечаток, и вы снова новый посетитель.

![Два запроса к Glassdoor в одной закрепленной сессии Web Unlocker: первый проходит проверку Cloudflare в безголовом браузере и получает clearance за 14,0 с, второй повторно использует этот clearance на том же выходе и возвращается за 1,4 с; замер от 29 сентября 2026 года.](https://res.cloudinary.com/dmqliab0t/image/upload/f_auto,q_auto,w_1200/v1790701776/blog/generated/qp-unl-g3-diag2.png)
*Первый запрос оплачивает браузер; последующие запросы в той же закрепленной сессии повторно используют clearance.*

## Когда простые запросы все еще подходят на сайте Cloudflare

Множество сайтов работают за Cloudflare только как CDN или с правилами ботов, которые пропускают обычный трафик, и простые запросы работают на них. Быть 'на Cloudflare' не является причиной обращаться к браузеру. Сигнал — это ответ. Если нет заголовка `cf-mitigated: challenge`, нет заголовка 'Just a moment' и нет 403, сохраняйте простой запрос и эскалируйте только те URL, которые действительно получают задачу. Помощник plain-first в нашем учебнике делает именно это.

Две соседние проблемы имеют свои собственные руководства. Страница, которая говорит 'Error 1020 Access denied', — это правило брандмауэра, отказывающее вам, а не задача, и никакое количество JavaScript это не исправит; см. [что вызывает ошибку Cloudflare 1020 и что её исправляет](https://quantumproxies.io/blog/cloudflare-error-1020-access-denied). Для более широкой картины защит Cloudflare за пределами Python, читайте [как обойти задачи Cloudflare в 2026 году](https://quantumproxies.io/blog/how-to-bypass-cloudflare-challenges-in-2026-what-actually-matters-now). Если страница за стеной — это Glassdoor, наше [руководство по скрейпингу зарплат и отзывов Glassdoor](https://quantumproxies.io/blog/scrape-glassdoor-salary-reviews) охватывает сторону данных.

## Часто задаваемые вопросы

### Почему мой скрейпер работает локально, но блокируется Cloudflare в облаке?

Потому что IP меняется. Дома ваш скрипт выходит с адреса жилого интернет-провайдера; на облачном VM он выходит из диапазона хостинга, которому защиты от ботов не доверяют с первого взгляда. TLS рукопожатие Python одинаково на обоих, и на более строгом сайте оно получает задачу даже из дома. В нашем тесте один жилой IP не прошел Indeed или Glassdoor.

### Почему страница Cloudflare "Just a moment" возвращает 403?

Страница с задачей выдается вместо страницы, которую вы запросили, и в нашем тесте она приходила со статусом 403, поэтому requests выдает '403 Client Error: Forbidden'. Статус не специфичен для задач. Проверьте заголовок ответа cf-mitigated, который Cloudflare документирует как установленный на challenge на каждом ответе страницы с задачей, или заголовок 'Just a moment'.

### Работает ли cloudscraper, и какая есть хорошая альтернатива?

Он может все еще работать на сайтах с мягкими настройками, поэтому тестируйте его на своих целях. Он работает на TLS стеке Python и решает скрипты в интерпретаторе, в то время как текущие задачи также смотрят на рукопожатие и окружение браузера. Альтернативы: curl_cffi для рукопожатия браузера, реальный браузер для JavaScript или веб-разблокировщик, который делает и то, и другое.

### Может ли Python requests самостоятельно пройти задачу Cloudflare?

Нет. requests не выполняет JavaScript, поэтому не может завершить задачу, которая зависит от выполнения скрипта страницы. Он может загружать страницы с сайтов Cloudflare, которые не бросают вам вызов. Как только появляется cf-mitigated: challenge, вам нужен реальный браузер, напрямую или через сервис, который его использует, и, желательно, чистый жилой IP.

### Как долго длится clearance Cloudflare?

Настолько долго, насколько сайт его настраивает. Cloudflare называет эту настройку Challenge Passage, и clearance может закончиться раньше, если Cloudflare решит, что сессия выглядит подозрительно. Cookie cf_clearance привязано к посетителю и устройству, которое его заработало, поэтому оно помогает только если последующие запросы сохраняют тот же выход и отпечаток, что и закрепление x-qp-session.

Краткая версия: 'Just a moment...' просит браузер, поэтому никакой трюк с заголовками в requests не удовлетворит её. Обнаружьте её с помощью `cf-mitigated`, сохраняйте простые запросы для всего, что не бросает вызов, отправляйте URL с задачами через что-то, что запускает реальный браузер с чистого IP, и закрепите сессию, чтобы платить за этот браузер один раз, а не на каждой странице.

[Попробуйте Web Unlocker на жилых выходах](https://quantumproxies.io/web-unlocker/residential)
