Cloudflare Turnstile

Challenge service

Also known as: Turnstile, siteverify

A token verifier rather than a gatekeeper. Its API always answers 200, so the verdict lives in a JSON body and never in the status code.

Turnstile is different in kind from everything else in this glossary. It does not sit in the request path and refuse traffic. It issues a token to a client, and your server exchanges that token for a verdict by calling the siteverify API. The enforcement decision is yours.

The single most important operational fact is that siteverify always returns HTTP 200. Success and failure are both 200 responses; the difference is the success boolean and the error-codes array in the JSON body. Any integration that checks response.ok and proceeds is accepting every failed and forged token it is handed.

Cloudflare is blunt about this: it warns that it is critical to enforce Turnstile tokens with the siteverify API, and that not verifying the token will leave major vulnerabilities in your implementation. Skipping verification also produces zeroes in Turnstile analytics, which is the usual way people discover they never wired it up.

Tokens are single use and valid for five minutes. Both constraints produce the same error code, which is a frequent source of confusion in support threads.

How to identify it

Status codes

200 siteverify success

Allowed. Documented by the vendor.

The token was valid. The body carries success true along with the hostname and timestamp of the challenge.

What triggers it

How to confirm it

What to do about it

POST https://challenges.cloudflare.com/turnstile/v0/siteverify

HTTP/2 200
content-type: application/json

{"success": true, "challenge_ts": "2026-08-28T12:00:00.000Z",
 "hostname": "example.com", "error-codes": []}

200 siteverify failure

Blocked. Documented by the vendor.

The token was rejected. Still an HTTP 200; the body carries success false and an error-codes array naming the reason.

What triggers it

How to confirm it

What to do about it

HTTP/2 200
content-type: application/json

{"success": false, "error-codes": ["timeout-or-duplicate"]}

If you run a site behind it

If your traffic is being caught by it

Documentation

See also