turnstile · siteverify · server-side validation

invalid-input-response: the token siteverify would not accept

Cloudflare documents this one in five words — "Token is invalid, malformed, or expired" — and those five words cover several very different mistakes. This is how to tell which of them you made.

What siteverify is actually saying

invalid-input-response comes from POST https://challenges.cloudflare.com/turnstile/v0/siteverify, the server-side call that decides whether a token is real. It means the value you put in the response parameter was not something Cloudflare would honour.

It is not a statement about the visitor. The widget may have been solved perfectly and the token still rejected here, because everything between the widget and this call is your code.

If the token was accepted once and rejected on a second attempt, that is timeout-or-duplicate, not this. Each token validates exactly once, which is why the two codes are separate.

The causes, in the order worth checking

CauseHow to confirm it
The token expiredTokens are valid for 300 seconds. If you queue submissions, or a user leaves a form open, the token dies before validation. Log the gap between the widget's callback and your siteverify call.
You sent the sitekey instead of the tokenThe sitekey is public and begins 0x4; a token is far longer and begins 0. If your response value starts 0x4, that is the bug.
The field never arrivedAn empty string is invalid input. Log the raw value your handler received before validating — a mis-named form field produces the same code as a forged token.
The token came from a different widgetTwo widgets on one page issue two tokens against two sitekeys, and each is valid only for the secret paired with its own.
It was mangled in transitDouble URL-encoding, a truncating database column, or trimming to a fixed length all produce a value that is no longer the token. Compare lengths before and after.
The token is genuinely not realCloudflare's own wording notes this frequently means a fabricated token was submitted. If everything above checks out, that is what remains.

Confirm it in one request

Before changing code, call siteverify by hand with the token your handler received. Two parameters, and it tells you plainly whether the token or your plumbing is at fault.

bash
curl -X POST https://challenges.cloudflare.com/turnstile/v0/siteverify \
  -d secret="$TURNSTILE_SECRET_KEY" \
  -d response="$TOKEN_FROM_YOUR_FORM"

# invalid-input-response  -> the token is the problem
# invalid-input-secret    -> your secret is the problem
# timeout-or-duplicate    -> the token was already spent

A success: true here, with a failure in your application, means the token is fine and the fault is downstream. A failure here with the same token your handler logged means the token never was valid.

The full siteverify table

Seven codes, and knowing which neighbours yours narrows the search considerably.

CodeCloudflare's description
missing-input-secretSecret parameter not provided
invalid-input-secretSecret key is invalid or expired
missing-input-responseResponse parameter was not provided
invalid-input-responseToken is invalid, malformed, or expired
bad-requestRequest is malformed
timeout-or-duplicateToken has already been validated
internal-errorInternal error occurred

missing-input-response and invalid-input-response are worth distinguishing carefully: the first means the parameter was absent, the second that it was present and wrong. If you are seeing the first, the bug is in how you read the form, not in the token.

reCAPTCHA returns this string too

Google's reCAPTCHA verification endpoint uses the same code names, so a search for this error returns results for both products. If your integration is reCAPTCHA the shape of the problem is identical — expired, missing or mangled token — but the endpoint and key formats differ, so check which one you are calling before applying a fix written for the other.

Common questions

300 seconds from issue. After that siteverify returns invalid-input-response. That window is why a token should be requested at the moment of submission rather than at page load: a form left open for six minutes fails validation even though nothing about it was wrong.

invalid-input-response means the token was never acceptable — expired, malformed, empty or fabricated. timeout-or-duplicate means it was acceptable and has already been spent, because each token validates exactly once. Retrying a failed submission with the same token moves you from the first error to the second.

No. Cloudflare states each token can only be validated once and that a replayed token is rejected with timeout-or-duplicate. For retry safety use the optional idempotency key — a UUID you generate — rather than re-sending the token.

Usually a key mismatch. Testing sitekeys must be paired with testing secret keys; mixing a test key with a live secret produces a validation failure that looks like a bad token. Check the pair deployed to production belongs to the same widget.

Not necessarily, and usually not. Every ordinary cause above produces the same code — expiry, a mis-named field, a truncated column. Cloudflare's note that it often indicates a fabricated token is worth taking seriously only once the mundane explanations are eliminated.

The string is. Google's verification endpoint uses the same code names, which is why searches mix the two products. The diagnosis is similar, but the endpoint, key formats and token shape differ, so make sure the advice you follow is written for the product you are using.

Related

Sources

More in Turnstile errors

Turnstile error 300030Error 300030 means a Turnstile widget mounted and then stopped responding. The real causes, the codes it gets confused with, and the fixes.Turnstile timeout-or-duplicate errorsiteverify returns timeout-or-duplicate when a Turnstile token is verified twice or is older than 300 seconds. The causes, and how to fix each one.Turnstile callback not firingWhy the Turnstile success callback never runs: implicit rendering, callbacks not on window, hidden containers and SPA remounts.Cloudflare Turnstile error 600010Turnstile error 600010 is a generic challenge failure in the 600* family. What Cloudflare documents, the reproduced causes, and how to fix it.cf-turnstile-response invalidThree different failures wear this name. Sort out which one you have — the token never arrived, siteverify refused it, or your keys do not match.Turnstile stuck on "Verifying you are human"Why Turnstile hangs on "Verifying you are human": how to read the error code, plus fixes for CSP, clock skew, blocked domains and headless CI.invalid-input-secretsiteverify returns invalid-input-secret when your secret key is rejected. Why the key is usually right, and the five things that actually cause it.Token rejected"Token rejected" is not a Cloudflare error — it is what an app prints when siteverify refused its token. What to do, as a visitor or as a developer.Field is requiredA Laravel validation message meaning the Turnstile token never reached your server. Why the field is empty, how to tell which cause it is, and the fix for each.

Automating a gate you own or are authorised to test?

// SolveGate clears Cloudflare Turnstile and WAF challenges through one REST call · first 1,000 solves free