The cf-turnstile-response Token, Explained

The cf-turnstile-response field holds the token Cloudflare Turnstile issues when a browser passes. What it is, how it's submitted, why it expires, and how to get one without a browser.

You open the page source, find a hidden input called cf-turnstile-response, and it's empty. Submit the form without filling it and the server bounces you. That one field is the whole handshake between Cloudflare Turnstile and the site behind it, and once you understand what goes in it, solving Turnstile stops feeling like magic.

cf-turnstile-response is the token Cloudflare Turnstile hands your browser after it decides you're allowed through. The widget runs its checks, and when it's satisfied it drops a long string into that hidden field. The server then sends that string to Cloudflare's siteverify endpoint to confirm it's real before trusting the request. No valid token, no entry.

Where the token comes from

When a page loads Turnstile, it renders a widget tied to a sitekey (the public identifier for that site's Turnstile config). The widget scores the browser in the background. If it passes, Turnstile writes the token into an input named cf-turnstile-response, usually inside the form you're about to submit, and optionally fires a JavaScript callback with the same value.

So the token has three properties that matter for automation:

  • It's tied to the sitekey it was issued for. A token from one sitekey won't validate against another.
  • It's single-use. The server redeems it once at siteverify; replay the same token and Cloudflare rejects it.
  • It's short-lived. Turnstile tokens expire around 300 seconds after issue. Grab one and sit on it, and it goes stale.

If you're not sure where the sitekey on your target comes from, that's a two-minute job covered in how to find a Turnstile sitekey.

How the token gets submitted

In the normal browser flow, the widget fills the field and you just submit the form. The token rides along as a POST parameter:

POST /login HTTP/1.1
Content-Type: application/x-www-form-urlencoded

email=you@example.com&password=...&cf-turnstile-response=0.abc123LongOpaqueString...

On the server, the site takes that value and verifies it:

# server side, on the site you're submitting to
POST https://challenges.cloudflare.com/turnstile/v0/siteverify
  secret=<the site's secret key>
  response=0.abc123LongOpaqueString...
# -> {"success": true, ...}

You never see the secret key; that's the site's. Your job as the client is only to produce a valid response value and send it with the form.

Getting the token without running a browser

You have two ways to produce that token. Drive a real browser, let the widget solve, and scrape the field. Or ask a solving API to return the token directly. The second skips keeping a headless browser alive for every request.

import requests

token = requests.post(
    "https://api.peak.fo/solve",
    headers={"X-API-Key": "pk_your_api_key"},
    json={
        "task_type": "turnstiletask",
        "url": "https://target.com/login",
        "sitekey": "0x4AAAAAAAxxxxxxxx",
        "proxy": "http://user:pass@ip:port",
    },
    timeout=30,
).json()["data"]["token"]

# now submit it before it expires (~300s)
requests.post("https://target.com/login", data={
    "email": "you@example.com",
    "password": "...",
    "cf-turnstile-response": token,
})

On a typical target that comes back in about one to one and a half seconds, and Peak only charges when the solve lands, so a miss costs nothing. The token you get is a normal cf-turnstile-response value; the server can't tell it apart from one a browser produced, because it isn't different.

Why a token gets rejected

Almost every "my token doesn't work" case is one of four things:

  • It expired. You solved, then waited too long to submit. Solve immediately before the request that needs it.
  • You reused it. Tokens are single-use. Every submission needs a fresh one.
  • Wrong sitekey. You solved against a sitekey that isn't the one on the page you're posting to.
  • Mismatched context. Some deployments tie the token to an action or the page's IP. Solve through the same proxy you'll submit from, and pass the action if the widget sets one.

FAQ

What is cf-turnstile-response?

It's the hidden form field that holds the token Cloudflare Turnstile issues when a browser passes the challenge. The site sends that token to Cloudflare's siteverify endpoint to confirm the visitor cleared Turnstile before accepting the request.

How long is a Turnstile token valid?

Around 300 seconds. It's also single-use, so you need a fresh token for each submission and you should submit it right after you get it.

Can I reuse a cf-turnstile-response token?

No. The server redeems it once at siteverify. Solve again for the next request. See the Turnstile solving guide for the full flow, or pricing to start.

Need Turnstile tokens on demand? Grab a key free at peak.fo.

Read more