Quick answer: The "Just a moment..." page is Cloudflare's browser challenge (often called the JS challenge or Turnstile interstitial). It runs JavaScript checks and inspects your browser fingerprint before letting you through. A plain HTTP client cannot pass it because it never executes that JavaScript. The legitimate fixes are a real browser fingerprint, a properly configured headless browser, or a fetch API that handles the challenge for you on public pages.
What the "Just a moment" page actually is
When you request a page and get HTML that says "Just a moment..." with a spinner instead of the content you wanted, you have hit a Cloudflare challenge. Cloudflare sits in front of the origin, and before passing your request through, it wants proof you are a real browser.
That proof is a short JavaScript program the page runs in the background. It measures things a real browser can do and a script usually cannot: execute JS, hold cookies, present a consistent TLS handshake, and complete a Turnstile check. If the checks pass, Cloudflare sets a clearance cookie and redirects you to the real content. If they fail or never run, you stay stuck on the interstitial.
This is different from a hard 403 block. The "Just a moment" page is an invitation to prove yourself, not a flat refusal. That distinction matters, because it tells you what kind of fix will work.
Why your scraper hits it
A few things trigger the challenge, sometimes together:
- You are not running JavaScript.
requests,curl,httpx, and similar clients fetch HTML and stop. The challenge script never executes, so the clearance cookie is never set. - Your TLS fingerprint looks automated. Cloudflare reads the TLS handshake. A Python client claiming to be Chrome has a handshake that does not match Chrome, and that mismatch flags you before the JS even matters.
- Your IP has low trust. Datacenter and known-proxy IPs get shown the challenge far more aggressively than residential ones.
- Your headers are thin. Missing
Accept-Language, client hints, orSec-Fetch-*headers is a giveaway.
This post is specifically about the interstitial. If you want the broader picture of Cloudflare's protections, WAF rules, and rate controls, see our guide to scraping Cloudflare-protected sites. Here we stay narrow: getting past "Just a moment" on public content.
The legitimate options
| Approach | Passes the challenge | Effort | Best for |
|---|---|---|---|
| Plain HTTP client | No | Low | Nothing behind the challenge |
| TLS-impersonating client | Sometimes | Low | Light challenges, good IP |
| Real headless browser | Usually | High | JS-heavy public pages |
| Fetch API (link.sc) | Usually | Low | Public data at scale |
Option 1: A TLS-impersonating client
If the challenge is light and your IP is clean, matching a real browser's TLS handshake is sometimes enough. A library like curl_cffi impersonates Chrome's handshake, which clears the fingerprint hurdle.
from curl_cffi import requests
resp = requests.get(
"https://example.com",
impersonate="chrome",
timeout=20,
)
# Check whether you got real content or the interstitial
if "Just a moment" in resp.text:
print("Still challenged, escalate to a real browser")
else:
print(resp.status_code, len(resp.text))
This will not run the challenge JavaScript, so it only works when Cloudflare decides your fingerprint and IP are trustworthy enough to skip the interactive check.
Option 2: A properly configured headless browser
A real browser executes the challenge JavaScript, which is the reliable way through. The catch is that a default headless browser leaks automation signals (the navigator.webdriver flag, missing plugins, an off fingerprint), and those get caught. You need a browser configured to look like a normal user session.
from playwright.sync_api import sync_playwright
with sync_playwright() as p:
browser = p.chromium.launch(headless=True)
context = browser.new_context(
user_agent=(
"Mozilla/5.0 (Windows NT 10.0; Win64; x64) "
"AppleWebKit/537.36 (KHTML, like Gecko) "
"Chrome/125.0.0.0 Safari/537.36"
),
locale="en-US",
)
page = context.new_page()
page.goto("https://example.com", wait_until="networkidle")
# Give the challenge time to resolve and set the clearance cookie
page.wait_for_timeout(5000)
print(page.title())
browser.close()
Stealth plugins and hardened builds exist to reduce those leaks, but they need ongoing maintenance as detection evolves. If you are weighing this against lighter tools, our comparison of curl vs headless vs stealth browser lays out the tradeoffs.
Option 3: A fetch API that handles the challenge
If your goal is the content, not the puzzle, a fetch API absorbs the whole thing. link.sc runs a real browser stack with the right fingerprint and IP behind one HTTP call, and returns clean content.
curl https://link.sc/v1/fetch \
-H "Authorization: Bearer lsc_..." \
-H "Content-Type: application/json" \
-d '{"url": "https://example.com", "format": "markdown"}'
No browser to maintain, no fingerprint to patch. See the link.sc docs for options like waiting on selectors or returning JSON.
What NOT to expect
Be realistic about the limits:
- No plain HTTP client will reliably pass it. If a tutorial promises
requestsalone defeats the challenge, it is either outdated or the site was not really challenging. - Passing the JS challenge does not defeat everything. Cloudflare also runs managed rules, rate limiting, and Turnstile with interactive checks. Clearing "Just a moment" is one layer, not all of them.
- Solutions decay. Whatever works today may need updating in a month. Detection and evasion are a moving target, which is exactly why offloading it is attractive.
An ethics note
The reason "Just a moment" appears is that a lot of automated traffic misbehaves. Keep yourself in the well-behaved category. Only fetch public content, honor robots.txt, keep your rate polite, and identify yourself where a site asks you to. Never route around a login, a paywall, or region locks: a challenge that guards private content is doing its job, and getting past it is not a technical exercise you should be running. Passing a challenge to read a public article is reasonable. Using the same trick to hammer an origin or scrape gated data is not.
Stuck on the "Just a moment" screen? link.sc runs the browser, fingerprint, and IP for you and returns clean content from public pages. Try it free.