Skip to content

Explainer

Cloudflare Waiting Room vs a Challenge Page: What Crawlers See

A Cloudflare Waiting Room is a queue, not a bot check. How to tell it from a challenge page, how its cookie and JSON mode work, and how to wait your turn.

By 5 min readPublished

A Cloudflare Waiting Room is a queue, not a bot check. It holds visitors when traffic to a page passes limits the site owner set (“total active users” and “new users per minute”), shows them a waiting page that refreshes itself every 20 seconds, and keeps their place in an encrypted cookie named __cfwaitingroom. A challenge page is different: it answers HTTP 403 with the header cf-mitigated: challenge, and waiting does not help, while a waiting room answers 200 by default and waiting is the whole point. An automated client should keep its cookie, ask again at the room’s interval, and never open new sessions to jump the line.

This explainer compares the two, shows the JSON mode Cloudflare offers for non-browser clients, and gives a polite client that waits its turn. Facts are from Cloudflare’s documentation as checked on 1 October 2026.

Waiting room or challenge page?

Waiting room Challenge page
Why you see it Traffic passed the owner’s limits A rule, Bot Management or Under Attack mode challenged your request
Status 200 by default; the owner can pick another code 403
Marker The __cfwaitingroom cookie; with JSON mode, a cfWaitingRoom object Header cf-mitigated: challenge
What passes it Time: the queue lets you in when there is room Passing the challenge, which sets cf_clearance
What a client should do Wait, with its cookie, at the room’s interval Back off, or pass it where allowed

A waiting room can also include a Cloudflare Turnstile widget. Its settings offer the modes off, invisible, visible_non_interactive and visible_managed (default invisible), and two actions for a failed check, log (the default) and infinite_queue. In Cloudflare’s analytics for that widget, an infinite queue shows up as “the number of refresh requests from bots in the infinite queue”: a client judged a bot keeps waiting and never gets in.

How the queue works

  • Limits: the owner sets the number of active users the site can take at once and how many new users may enter per minute; the room queues everyone beyond them.
  • Order: “First In First Out (FIFO)” by default. Some plans can use Random, Passthrough (let everyone through) or Reject (let nobody through).
  • Refresh: in a browser, “the user’s browser automatically refreshes every 20 seconds”.
  • Cookie: __cfwaitingroom holds “a unique group ID corresponding to when the visitor entered the waiting room” and an acceptedAt value. While queued, its “expiration is always set to five minutes, but renews every 20 seconds”; once in, it lasts for the room’s session duration, 5 minutes by default and up to 30.
  • Cookies are required: “When a waiting room is actively queueing, users cannot visit that host and path combination without enabling cookies.”

JSON mode for non-browser clients

A site owner can turn on JSON responses for “mobile and other non-browser traffic” (the json_response_enabled setting, off by default). The client must send exactly Accept: application/json: “If it is anything else or has any additional content such as Accept: application/json, text/html the response will not return in the JSON format.” The reply while queued looks like this, in Cloudflare’s example:

{
"cfWaitingRoom": {
"inWaitingRoom": true,
"waitTime": 5,
"waitTimeKnown": true,
"waitTimeFormatted": "5 minutes",
"queueIsFull": false,
"queueAll": false,
"lastUpdated": "2021-08-03T23:46:00.000Z",
"refreshIntervalSeconds": 20
}
}

The client must “retry the request every refreshIntervalSeconds in order for users to advance in the queue”, sending the cookie and keeping it updated from each response. Without the cookie, the room treats the client as new, at the back of the queue.

A client that waits its turn

This Python function waits in a room with one session, at the interval the room asks for, and gives up after a limit you choose. It returns the first response that is not a queue reply; ask for the page again with your usual headers once it returns.

import time
import requests
def wait_in_queue(session, url, max_wait_seconds=1800):
deadline = time.monotonic() + max_wait_seconds
while time.monotonic() < deadline:
response = session.get(url, headers={"Accept": "application/json"}, timeout=30)
try:
state = response.json().get("cfWaitingRoom")
except (ValueError, AttributeError):
state = None
if not state or not state.get("inWaitingRoom"):
return response
print("queued, estimated wait:", state.get("waitTimeFormatted", "unknown"))
time.sleep(state.get("refreshIntervalSeconds", 20))
raise TimeoutError(f"still queued after {max_wait_seconds} seconds")
with requests.Session() as session:
wait_in_queue(session, "https://tickets.example.com/event/42")
page = session.get("https://tickets.example.com/event/42", timeout=30)
print(page.status_code)

If the owner has not turned on JSON mode, the queue page is HTML: wait 20 seconds between requests, keep the same session, and look for the page you asked for.

Three rules keep a crawler from hurting the queue it is in:

  • One session per place in line. Opening many sessions puts many places in the queue, which pushes real visitors back. Don’t.
  • Honour the interval. Asking faster than refreshIntervalSeconds does not move you up.
  • Set a limit. A queue can be long, and a client judged a bot may be put in an infinite queue. Give up after a time that fits your job.

Where ZeroCaptcha fits, and where it doesn’t

A waiting room has nothing to solve, and ZeroCaptcha does not move anyone up a queue. What it covers are the checks that sit in front of pages: Cloudflare Turnstile widgets in forms, through the Cloudflare Turnstile solver, and Cloudflare challenge pages, through the Cloudflare WAF and 5-second challenge solver. If a site answers with a challenge rather than a queue, see Cloudflare challenge types; if it answers 429 with error 1015, you are being rate limited, which Cloudflare error 1015 covers.

Sources

The team that builds and runs the ZeroCaptcha API. Articles are drafted with AI tools, then checked against the API's code and the primary sources each one cites.

Questions

Is a Cloudflare Waiting Room a bot check?

No. It is a queue that holds visitors when traffic passes the limits the site owner set, total active users and new users per minute. A waiting room can also run a Cloudflare Turnstile widget, but its main job is pacing, not detecting bots.

How does a script wait in a Cloudflare Waiting Room?

Keep the __cfwaitingroom cookie and ask again at the interval the room gives. If the owner turned on JSON responses, send exactly Accept: application/json and retry every refreshIntervalSeconds with the updated cookie; without the cookie you go to the back of the queue.

Can a solving API skip a Cloudflare Waiting Room?

No, and it should not. There is nothing to solve: the queue lets visitors in as the site has room for them. Wait your turn with one session and a time limit.

Read next

This article is part of the Cloudflare WAF and 5-second challenge solver hub. Every task is charged only when a token is ready.

Get an API key