Building a form is easy. Keeping the bots out of it is the actual job, and that's what form services really sell. Turnstile does that part for free, with no limit on challenges, and most visitors never see a puzzle.
My recipe for a contact form on a static site: the form posts to a Worker, the Worker checks the Turnstile token on the server, then sends the submission through Resend. Add a honeypot field and almost nothing gets through. It's a few dozen lines, the same for every client, and nobody else holds your visitors' messages.
Use it when
- Any public form: contact, sign-up, sign-in, password reset, comments.
- A static site's contact form: the form posts to a Worker, which checks the Turnstile token, then emails the submission through Resend. About 40 lines, reused for every client, and the submissions never pass through a third party.
- Replacing reCAPTCHA: no image puzzles, and no Google tracking your visitors.
Don't use it when
- Nobody can write the 40 lines: a hosted form backend such as Basin or Forminit takes the form and supports Turnstile, but every submission then sits with a third party, on a small free tier.
Pricing
Free: unlimited challenges, up to 20 widgets per account, 10 hostnames per widget. Enterprise adds unlimited widgets and removes the branding.
Gotchas, with fixes
Gotcha: The widget alone doesn't stop bots: they post straight to your endpoint and never load it.
Fix: Check every token on the server, with your secret, at https://challenges.cloudflare.com/turnstile/v0/siteverify, and reject the request unless it succeeds.
Gotcha: A token can be checked only once and expires after 5 minutes, so a slow form or a retry fails.
Fix: Verify once, at submission; if the form errors, reset the widget for a new token before the user resubmits.
Gotcha: Some bots still get through: Turnstile tells you a browser was there, not that a human meant it.
Fix: Add a hidden honeypot field and drop any submission that fills it.
Provisioning
Official Pulumi package · Official Terraform provider
The widget is a Cloudflare resource (sitekey and secret); the secret goes into the Worker as a secret.
Instead, consider
- Resend Sends the form's email from the Worker.
- Cloudflare Workers Receives the form, checks the token, calls Resend.
Where it fits
- A website, SPA or PWA: Pick 05.
Any form: Turnstile keeps the bots out, a Worker checks it and Resend sends the email.
Sources
- Cloudflare Turnstile: plans
- Cloudflare Turnstile: server-side validation
- Cloudflare: protect your forms from spam and abuse
Last reviewed by Nicolas Dao