Appearance
Spam protection
BootForm has four independent layers of spam protection. All four live in the same place - open your form in the dashboard, go to the Settings tab, and look for the Spam protection section. You can turn on any combination of them; they don't conflict with each other.
| Layer | On by default? | Good for |
|---|---|---|
| Honeypot | Yes | Simple bots that fill in every field they find |
| Cloudflare Turnstile CAPTCHA | No | More sophisticated bots and scripted abuse |
| IP blocklist | No | One specific abusive sender you've identified |
| Country restriction | No | Traffic you only expect from certain countries |
If you've never touched any of these settings, honeypot is already protecting your form - there's nothing you need to do. The rest of this page walks through each one, what it actually looks like when it catches something, and how to turn it on.
Honeypot
A honeypot is an invisible trap. BootForm adds a form field that a real person never sees and never fills in - but a bot that blindly fills in every field it finds on a page will fill it in too, because it can't tell the difference. Any submission that arrives with that field filled in gets treated as spam.
It's on by default and needs no setup - if you're using the HTML snippet BootForm gives you (from your form's Overview tab), the trap field is already in there. It looks like this:
html
<input type="text" name="_honeypot" style="position:absolute;left:-9999px" tabindex="-1" autocomplete="off">If your form's HTML isn't the one BootForm generated for you, add that input yourself anywhere inside your <form> - name it exactly _honeypot, and keep it positioned off-screen (not display:none/visibility:hidden - some bots specifically skip fields hidden that way while still filling in everything else, which would defeat the point) rather than removing it, so a bot still finds and fills it in.
What happens when it catches something: the sender sees a completely normal "thanks, your submission was received" response - BootForm never tells a bot that it got caught, so it doesn't learn to try something else next time. On your side, the submission shows up under the Spam tab (not All submissions), and it doesn't count against your monthly submission quota.
Turning it off: most people never need to. The one real reason to disable honeypot is if something legitimate - a browser extension, a testing tool, a script that fills in every input on a page - is triggering it by accident on a form you control. To turn it off: Settings → Spam protection → Honeypot, flip the switch.
Cloudflare Turnstile CAPTCHA
Honeypot catches bots that aren't paying attention. CAPTCHA catches the more careful ones, at the cost of a small, usually-invisible check on the visitor's side. BootForm uses Cloudflare Turnstile - a free CAPTCHA service. You'll need your own free Cloudflare account, since BootForm doesn't run a shared one for every customer; you create your own widget and give BootForm its keys.
Step 1: create a Turnstile widget on Cloudflare
- Go to the Cloudflare dashboard and log in (or sign up - no credit card needed).
- In the left sidebar, click Turnstile.
- Click Add widget.
- Give it a name - this is just for your own reference inside Cloudflare, e.g. your form's name.
- Under Domain, enter the domain(s) where your form actually lives (e.g.
mysite.com) - notbootform.com. This has to match the site your visitors will be on when they submit the form. - Leave Widget Mode set to Managed (the default) - Cloudflare decides on its own whether to show a visible challenge, based on how suspicious the visitor looks.
- Click Create.
- Cloudflare shows you a Site Key and a Secret Key. Copy both somewhere safe now - the Secret Key is only ever shown this once.
Step 2: give BootForm the keys
In the BootForm dashboard: open your form → Settings → Spam protection → Cloudflare Turnstile CAPTCHA → Add (+). Paste in the Site Key and Secret Key from step 1, then Save.
If you're using BootForm's own HTML snippet (Settings tab), you're done - the snippet automatically includes everything Turnstile needs as soon as a CAPTCHA is configured, no further edits required.
Step 3 (only if you hand-wrote your own form HTML)
If your form's HTML isn't the one BootForm generated for you, add these two things yourself:
html
<script src="https://challenges.cloudflare.com/turnstile/v0/api.js" async defer></script>
<form action="https://f.bootform.com/{form_id}" method="POST">
<input name="email" type="email" required />
<textarea name="message"></textarea>
<div class="cf-turnstile" data-sitekey="YOUR_SITE_KEY"></div>
<button type="submit">Send</button>
</form>Cloudflare's script finds that <div>, renders the widget in its place, and - once the visitor passes the check - adds a hidden field to the form for you automatically. You don't need to read or handle that value yourself; just make sure the <div> is somewhere inside the <form> before it's submitted.
Only one CAPTCHA provider can be active per form at a time (Turnstile is the only one BootForm supports today). Editing or removing it later works the same way: Settings → Spam protection → Cloudflare Turnstile CAPTCHA → Edit or Remove.
IP blocklist
If you've noticed one specific IP address sending you junk - checked your submissions, seen the pattern, and want it hard-blocked - you can add it here. This is an exact match: blocking 203.0.113.5 does not block 203.0.113.6 or any other address in the same range. There's no support yet for blocking a whole range (a /24, for example) - just individual addresses.
Settings → Spam protection → IP blocklist → Add, type the address, and Save. A submission from a blocked address never reaches your form at all - not stored anywhere, not counted against quota, rejected instantly.
Country restriction
Restrict submissions to (or away from) specific countries, based on where the sender's IP address appears to be located. Two modes:
- Block these countries - accept from everywhere else.
- Allow only these countries - reject everyone else.
Settings → Spam protection → Country restriction → Add, pick the mode, add one or more countries from the dropdown (it lists every country by name - you don't need to know ISO codes), and Save.
Two things worth knowing:
- If BootForm can't figure out where a submission is coming from (the lookup times out, or fails for any reason), that submission is never rejected by this rule, in either mode. A restriction you can't reliably enforce is worse than one that occasionally lets an unresolved visitor through - this is a deliberate choice, not a bug.
- Country lookup works by matching the sender's IP address against a third-party IP-to-country database. Those databases are updated regularly but are never 100% accurate or complete - IP ranges get reassigned between countries, VPNs and proxies can put a visitor's apparent location somewhere they aren't, and mobile carriers in particular can report a country other than the one the visitor is actually in. Treat this as a strong filter, not a guarantee - it won't perfectly catch or exclude every submission from a given country.
The "Spam detected" reminder
Once a form has caught its first piece of spam and doesn't yet have a CAPTCHA configured, the dashboard shows a one-time reminder suggesting you turn on Turnstile (or honeypot, if you somehow have it off). Two ways to dismiss it if you're not ready:
- Remind me later - hides it until tomorrow, on this browser.
- Never remind me again - hides it for this form for good, everywhere you log in.
Neither of these changes any of the actual protections above - they're purely about whether you see the nudge.
Response reference
The rest of this page is plain-language. If you're the one writing the code that submits to your form (or debugging why a submission didn't arrive), this section has the exact status codes and response bodies each layer produces.
Everything below is a POST https://f.bootform.com/{form_id} response. code is stable and safe to match on in your own code; error is a human-readable string meant for logs, not guaranteed to stay word-for-word identical between versions.
| Layer | Status | code | Submission stored? | Counts against quota? |
|---|---|---|---|---|
| Honeypot | 200 (looks identical to success) | (none - see below) | Yes, filed as spam | No |
| Cloudflare Turnstile | 422 | CAPTCHA_FAILED | No | No |
| IP blocklist | 403 | IP_BLOCKED | No | No |
| Country restriction | 403 | COUNTRY_BLOCKED | No | No |
Honeypot is the one deliberate exception: the response is a plain {"ok": true} (or a normal redirect for a classic browser POST), identical to a real successful submission - this is the whole point, so a bot never learns it tripped something. There's no error code because, from the sender's point of view, nothing went wrong.
Cloudflare Turnstile:
json
{ "ok": false, "error": "CAPTCHA verification failed.", "code": "CAPTCHA_FAILED" }IP blocklist:
json
{ "ok": false, "error": "This IP address is blocked for this form.", "code": "IP_BLOCKED" }Country restriction:
json
{ "ok": false, "error": "Submissions from this country are not accepted for this form.", "code": "COUNTRY_BLOCKED" }A classic (non-AJAX) browser form POST gets the same rejection as a redirect back to the form's page with ?bootform_error=CODE appended, instead of a JSON body - there's no script running on that request to read one. Send Accept: application/json or _format=json to always get JSON back regardless of how the form was submitted (see Responses and redirects).
Ordering, if more than one layer is configured: IP blocklist and country restriction are checked first (cheapest, no external calls), then honeypot, then CAPTCHA. A submission that would fail more than one check only ever reports the first one it hit.