Skip to content

Testing

Test Cloudflare Turnstile in CI With Testing Sitekeys

Test your own Turnstile forms in CI with Cloudflare's testing sitekeys and secret keys: always pass, always fail, forced challenges, and spent tokens.

3 min readPublished Updated

If Turnstile protects forms on your own site, your end-to-end tests have to get past it too. You do not need a solving service for that. Cloudflare publishes testing sitekeys and secret keys that make the widget and the server-side check behave predictably, so tests can cover success and failure without depending on a real challenge. This guide lists them and shows how to wire them into a test setup.

These keys are Cloudflare’s, documented on its testing page. They are the right tool whenever you own the site.

The testing sitekeys (client side)

Put one of these in the widget’s data-sitekey, or in sitekey for turnstile.render():

Sitekey Behavior Visibility
1x00000000000000000000AA Always passes Visible
2x00000000000000000000AB Always fails Visible
1x00000000000000000000BB Always passes Invisible
2x00000000000000000000BB Always fails Invisible
3x00000000000000000000FF Forces an interactive challenge Visible

With a passing sitekey, the widget produces a dummy token straight away and fills the cf-turnstile-response field, so your test can submit the form as a person would.

The testing secret keys (server side)

Configure one of these as your server’s Turnstile secret, the value it sends to siteverify:

Secret key siteverify answers
1x0000000000000000000000000000000AA Always passes
2x0000000000000000000000000000000AA Always fails
3x0000000000000000000000000000000AA Fails as a token that was already spent

Pair a sitekey and a secret key to make the combination you want to test: a passing widget with a failing secret, for example, checks that your server really refuses a bad token instead of trusting the browser.

The Cloudflare Turnstile test sitekeys page renders each sitekey live, and runs siteverify with each secret key, so you can see what your tests will meet before you write them.

Wire them in by environment

Keep the real keys out of test environments entirely. Read both values from configuration, and set the testing ones in CI:

Terminal window
# CI and local development
TURNSTILE_SITEKEY=1x00000000000000000000AA
TURNSTILE_SECRET=1x0000000000000000000000000000000AA

Render the sitekey from that setting:

<div class="cf-turnstile" data-sitekey="{{ TURNSTILE_SITEKEY }}"></div>

And verify with the secret from the same place:

import os, requests
def verify(token: str, remote_ip: str | None = None) -> bool:
reply = requests.post(
"https://challenges.cloudflare.com/turnstile/v0/siteverify",
data={"secret": os.environ["TURNSTILE_SECRET"], "response": token, "remoteip": remote_ip},
timeout=10,
).json()
return reply.get("success") is True

A production deploy that still carries a testing key accepts everyone, so add a startup check that refuses any key starting with 1x, 2x or 3x when the environment is production.

Test cases worth having

  1. Happy path: sitekey 1x…AA, secret 1x…AA. The form submits and your server accepts it.
  2. Rejected token: sitekey 1x…AA, secret 2x…AA. Your server refuses the submission and shows the visitor a useful message.
  3. Spent token: secret 3x…AA. Your server treats timeout-or-duplicate as a failure and asks for a new challenge instead of retrying the same token. See Cloudflare Turnstile token expiry for why tokens are single-use.
  4. Blocked visitor: sitekey 2x…AB. Your form stays disabled and says why.
  5. Interactive challenge: sitekey 3x…FF. Your layout still works when the widget asks for a click.
  6. Invisible widget: sitekeys 1x…BB and 2x…BB, if you use invisible mode. See Cloudflare Turnstile widget modes.

When a solving API is the right tool instead

Testing keys only work on sites whose configuration you control. When you automate a page you do not run, such as a partner’s portal you have permission to use or a public page whose terms allow it, the widget uses its real sitekey, and a token must be solved. That is what the Cloudflare Turnstile solver is for: a task with the page URL and sitekey returns a real token, charged only when it is solved.

Keep the two apart. Use Cloudflare’s keys for your own CI, and use a solving API only against sites you are allowed to automate under the Acceptable Use Policy.

Questions

Do I need a CAPTCHA solver to test my own Cloudflare Turnstile forms?

No. Cloudflare's testing sitekeys and secret keys make the widget and the server check pass or fail on demand, so end-to-end tests of your own site need no solver.

Can the testing keys be used in production?

No. They accept every visitor, or reject every visitor, so they must only ever be configured in development, CI and staging.

What does the 3x secret key test?

It makes siteverify answer as if the token had already been used, so you can check how your server handles the timeout-or-duplicate case.

Read next

This guide is part of the Cloudflare Turnstile solver hub. Every task is charged only when a token is ready.

Get an API key