DEV Community

Peak Fo
Peak Fo

Posted on Originally published at blog.peak.fo

Cloudflare Turnstile Token vs Cookie: Which One Do You Actually Need?

Cross-posted from blog.peak.fo. I work on Peak, a Cloudflare Turnstile/5-second-challenge solving API, so the code examples below call it. The distinction between the two values holds regardless of which solver you use.


Someone posts the same question in a scraping Discord every week. "My solver gave me a token but the site still 403s me." Or the reverse: "I got the cookie, so why does the login form reject my submission?" Nine times out of ten the person grabbed one of the two things Cloudflare hands out and tried to use it where the other one belongs. They look similar from the outside. They're not interchangeable.

There are two separate values in play, and they come from two separate Cloudflare products. The Turnstile widget gives you a token called cf-turnstile-response. The full-page "Checking your browser" interstitial gives you a cookie called cf_clearance. Different source, different lifetime, different way to use it, different thing a solver returns. Mix them up and nothing works. Here's how to tell which one your target needs.

The two values, side by side

cf-turnstile-response (the token) cf_clearance (the cookie)
What it is A one-time proof you passed the Turnstile widget A session cookie proving you cleared the full-page challenge
Where it comes from The Turnstile widget embedded in a form The Cloudflare interstitial in front of a whole site
How long it lasts About 300 seconds, and single-use Minutes to a few hours, reusable until it expires
How you use it Submit it as a form field with your request Send it as a Cookie header on every request
IP / UA bound? Bound to the sitekey, not your IP Bound to the IP and user-agent that earned it
Reusable? No, one redemption and it's spent Yes, until it expires, from the same IP and UA

If that already told you what you needed, the code is further down. If not, keep reading, because knowing why they differ saves you the next three debugging sessions.

The token: proof you passed a widget

Turnstile the widget is that little box or invisible check sitting inside a login, signup, or contact form. When it decides you're human enough, it writes a long string into a hidden input named cf-turnstile-response. Your form submits that string along with the email, password, or whatever else the form carries. The origin server takes the value and calls Cloudflare's siteverify endpoint to confirm it's real before it trusts the request.

Three things define the token. It's tied to the sitekey it was minted for, so a token from one site won't validate on another. It's single-use, redeemed once at siteverify and dead after. And it's short-lived, expiring around 300 seconds after issue. It is not welded to your IP address, which is the detail that trips people up when they compare it to the cookie.

The cookie: a pass to browse the site

cf_clearance works through a different mechanism. It comes from the full-page interstitial, the one that stalls for a few seconds with a spinner and the words "Checking your browser" before it lets you see anything. That challenge guards the whole site, not one form. When you clear it, Cloudflare sets a cf_clearance cookie in your browser, and from then on every request carrying the cookie skips the interstitial.

The cookie behaves nothing like the token. It's reusable, good for minutes or hours depending on the site's config. And it's bound to the IP and user-agent that earned it. Send the same cookie from a different IP, or with a different UA string, and Cloudflare throws out the cookie and challenges you again. That binding is the whole point of the interstitial, so a stolen or shared cookie is worthless off its original context.

Which one does your target need?

Look at what's blocking you. There's a clean test.

  • You can load the page fine, but a specific form or endpoint has a Turnstile widget on it. You need the token. Solve the widget, drop cf-turnstile-response into the form, submit. The rest of the site was never gated.
  • You can't reach anything on the site because a "Checking your browser" page sits in front of the whole domain. You need the cookie. Clear the interstitial once, then reuse cf_clearance on every request from the same IP and UA.

Some sites do both. A storefront might put the interstitial in front of the domain and a Turnstile widget on its checkout form. In that case you need the cookie to browse and a fresh token each time you hit the widget. They don't substitute for each other. A valid token won't get you past the interstitial, and a valid cookie won't satisfy a form's siteverify check.

How a solver returns each one

Because they're two different things, a solving API returns them with two different task types. On Peak, the widget token comes from turnstiletaskproxyless (or turnstiletask if you want to pass your own proxy), and the clearance cookie comes from cloudflare5stask.

Getting the token

import requests

resp = requests.post(
    "https://api.peak.fo/solve",
    headers={"X-API-Key": "pk_your_api_key"},
    json={
        "task_type": "turnstiletaskproxyless",
        "url": "https://example.com/login",
        "sitekey": "0x4AAAAAAABxxxxxxxxxxxxx",
    },
    timeout=30,
).json()

token = resp["data"]["token"]   # "1.7Nm..."

# submit it immediately, before the ~300s window closes
requests.post("https://example.com/login", data={
    "email": "you@example.com",
    "password": "...",
    "cf-turnstile-response": token,
})
Enter fullscreen mode Exit fullscreen mode

The response is {"success": true, "data": {"token": "1.7Nm..."}}. That token is an ordinary cf-turnstile-response value; the origin can't tell it apart from one a human's browser produced, because it isn't different.

Getting the cookie

import requests

resp = requests.post(
    "https://api.peak.fo/solve",
    headers={"X-API-Key": "pk_your_api_key"},
    json={
        "task_type": "cloudflare5stask",
        "url": "https://example.com/",
        "proxy": "http://user:pass@ip:port",
    },
    timeout=60,
).json()

data = resp["data"]
clearance = data["cf_clearance"]
headers = data["headers"]   # includes the matching user-agent

# now browse the site, same proxy IP + same UA + the cookie
r = requests.get(
    "https://example.com/pricing",
    headers=headers,
    cookies={"cf_clearance": clearance},
    proxies={"http": "http://user:pass@ip:port",
             "https": "http://user:pass@ip:port"},
)
Enter fullscreen mode Exit fullscreen mode

Notice the proxy appears in both calls. The cookie was earned on that exit IP, so every later request has to leave from the same one, carrying the same UA the solver handed back. Swap either and the cookie stops working.

The mistakes that cause 90% of the tickets

Almost every "it doesn't work" message comes down to one of these.

  • Reusing a one-time token. The token is spent the moment the server redeems it at siteverify. One token per submission, no exceptions. If you're looping, solve inside the loop.
  • Sitting on a token too long. It expires near 300 seconds. Solve right before the request that needs it, not minutes ahead in a batch.
  • Using the cookie from a different IP or UA. This is the big one for cf_clearance. If you solve through a proxy and then fire requests from your own server's IP, the binding breaks and Cloudflare re-challenges. Keep the IP and UA identical to what earned the cookie.
  • Treating the cookie as single-use, or the token as reusable. Backwards on both counts. The cookie is reusable until it expires; the token never is. Cache the cookie, never cache the token.
  • Solving the wrong thing. Throwing a token at an interstitial, or a cookie at a form. Check what's blocking you first, then pick the task type.

FAQ

What's the difference between cf-turnstile-response and cf_clearance?
cf-turnstile-response is a one-time token from the Turnstile widget on a specific form; it's sitekey-bound and expires in about 300 seconds. cf_clearance is a reusable cookie from the full-page interstitial that gates the whole site; it's bound to the IP and user-agent that earned it and lasts minutes to hours.

Can I reuse a cf-turnstile-response token?
No. It's redeemed once at Cloudflare's siteverify endpoint and is dead after that single use, no matter how much time is left on its ~300-second window.

Why does my cf_clearance cookie stop working?
Almost always an IP or user-agent mismatch. The cookie is bound to the context that earned it; send it from a different proxy or with a different UA string and Cloudflare discards it and re-challenges you.

Start free at peak.fo. 1,000 free solves, no card, pay only for solves that land.

Top comments (0)