turnstile · siteverify · secret key

invalid-input-secret: siteverify rejected your secret key

Cloudflare's description is "Secret key is invalid or expired". In practice the key is usually correct and something happened to it between the dashboard and the request.

This is about your server, not the visitor

Unlike most Turnstile errors, this one has nothing to do with the browser, the widget or the person filling in the form. The token may be perfect. invalid-input-secret means the secret parameter your server sent to siteverify was not a secret Cloudflare recognises.

That makes it one of the easier codes to diagnose, because there are only a handful of ways a correct key becomes an incorrect one in transit.

The five things that actually cause it

CauseHow to confirm it
You sent the sitekeyThe sitekey is public and begins 0x4. The secret is a different value entirely. Copying the wrong one out of the dashboard is the single commonest cause, because both live on the same screen.
Whitespace in the environment variableA trailing newline from an echo into a .env file, or a space picked up from a copy-paste, is sent verbatim. Print the length of the value your process actually holds and compare it with the dashboard.
The secret belongs to a different widgetEvery widget has its own sitekey and secret pair. A secret from another widget is a valid secret and still the wrong one, which is why the error says invalid rather than unknown.
A testing key paired with a live responseCloudflare's testing keys work only with each other. A testing secret validating a real token, or a live secret validating a testing token, fails here.
The widget was rotated or deletedRegenerating a secret in the dashboard invalidates the previous one immediately. If this started without a deploy, check whether someone rotated it.

Check the key your process is holding

Read the value your running process has, not the value in the file you think it read. Configuration is loaded by more layers than people expect, and any of them can trim, quote or override.

bash
# length and a fingerprint — never print the key itself into a log
printf '%s' "$TURNSTILE_SECRET_KEY" | wc -c
printf '%s' "$TURNSTILE_SECRET_KEY" | sha256sum | cut -c1-12

# then confirm against siteverify directly
curl -X POST https://challenges.cloudflare.com/turnstile/v0/siteverify \
  -d secret="$TURNSTILE_SECRET_KEY" \
  -d response="dummy"

# invalid-input-response -> the secret is FINE, the token was the dummy
# invalid-input-secret   -> the secret is the problem

That second call is the useful one. Sending a deliberately bogus token isolates the secret: if the secret is good you get invalid-input-response, because Cloudflare got far enough to judge the token. Getting invalid-input-secret back proves the key never passed.

The full siteverify table

For context, the seven codes this endpoint returns:

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-secret is the neighbouring case and means something different: the parameter was not sent at all. If you see that one, the secret is not reaching your request builder — an unset variable rather than a wrong value.

Common questions

The sitekey is public, goes in your page's markup, and begins 0x4. The secret key is private, never leaves your server, and is what siteverify authenticates you with. They are issued together per widget and are not interchangeable — sending the sitekey as the secret is the commonest cause of this error.

They do not expire on a timer, but they are invalidated the moment you rotate them in the dashboard, and deleting a widget invalidates its pair immediately. Cloudflare's wording says "invalid or expired" because both arrive as the same code.

Almost always a different value in the two environments — a secret from another widget, a testing key that was never swapped for a live one, or a deployment variable that was never set and is falling back to an empty string. Fingerprint the key in both places and compare.

No, and the attempt produces this error. The testing sitekeys and secrets are documented to work only with each other, so a testing secret cannot validate a token from a real widget. They exist to make automated tests deterministic, not to bypass validation.

No. Log its length and a hash prefix instead — that is enough to tell a trailing newline from a wrong key without putting the credential in a log file, a crash report or an error tracker.

Rarely. A genuine outage on their side returns internal-error, not this. invalid-input-secret is a verdict about the value you sent, so it points at configuration on your side essentially every time.

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-responsesiteverify returns invalid-input-response when a token is invalid, malformed or expired. The causes worth checking, in the order they occur.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