BuildBaseBuildBase

Spam protection

Stop bots and spam on public forms with a captcha, content rules, a review queue and daily limits, without writing code.

Every public form is protected in layers. Two are always on, and the rest are switches in the console. None of them need code: turn a captcha on, and the hosted page and the embed render it and BuildBase verifies it.

LayerOn by defaultWhat it stops
Hidden bot trapYesScripts that fill in every field they find
Duplicate guardYesDouble clicks, retry loops, the same message pasted repeatedly
Rate limitsYesFloods from one address, and a flood against one organization
CaptchaPer formBots and headless scripts
Content rulesPer formPeople, and AI agents in a real browser, who pass the captcha
Held for reviewPer formLets you see a suspicious submission before anything runs
Daily capPer formA form taking more than you planned for

Before you start

Choose a captcha provider once in the BuildBase console under Forms > Spam protection. Then open a form's Protect button (the shield in the forms table) to turn the captcha and the rules on for that form.

Choose a captcha provider

The provider applies to every form that has Require a captcha turned on.

OptionCost to youSetup
Managed by BuildBase (default)FreeNone
Built-in checkFreeNone
Your Cloudflare Turnstile keysFree, unlimited checksA site key and secret key from Cloudflare
Your hCaptcha keysFree plan available; paid plans add passive modeA site key and secret key from hCaptcha
Your Google reCAPTCHA keysFree up to 10,000 checks a month per Google Cloud organization, then billed by GoogleA v2 Checkbox site key and secret key

Managed by BuildBase uses Cloudflare Turnstile run on BuildBase's own account. Most visitors see a small "Success" check and never a puzzle. On a self-hosted install without Turnstile keys, Managed uses the built-in check.

Built-in check runs a short proof-of-work calculation in the visitor's browser, typically under a second. It loads no third-party script and sets no cookie, so it suits sites with strict privacy requirements. It makes every submission cost a bot CPU time, but it does not tell a person from a headless browser on its own: pair it with content rules.

Your own keys route verification through your own provider account, so its analytics and settings are yours.

Add your own keys

  1. Create a widget at the provider:
    • Cloudflare Turnstile: Cloudflare dashboard > Turnstile > Add widget, Managed mode.
    • hCaptcha: dashboard.hcaptcha.com > Sites > New site. The secret key is under your account settings.
    • Google reCAPTCHA: google.com/recaptcha/admin > Create, type v2 "I'm not a robot" Checkbox. v3 and Invisible keys do not render.
  2. Add the hostname the console shows in the dialog to the widget's allowed domains. That is where the hosted page and the embed run.
  3. Paste the site key and secret key into Forms > Spam protection and choose Check keys and save.

For Turnstile, Cloudflare confirms the secret before it is saved, so a mistyped key is reported in the dialog. hCaptcha and Google only confirm a secret against a real visitor's token, so after saving keys for either, open the hosted form and submit it once.

Note

The secret key is write-only. It is encrypted at rest and never sent back to the console or any browser. The dialog shows that a key is saved and its last four characters. To rotate it, paste the new one and save. Switching to Managed or Built-in deletes the stored keys.

If a stored key later becomes unreadable, or a provider rejects it, forms fall back to Managed rather than accepting submissions without a check.

Turn protection on for a form

The Protect dialog holds every per-form setting. The shield icon is filled when any of them is on.

SettingDefaultEffect
Require a captchaOffSubmissions must carry a verified token from your provider
Most links allowedNo limitCounts links across all answers. Fields of type link are not counted
Blocked words and phrasesNoneWhole words or phrases, any capitalization, up to 200 entries
When a submission breaks a ruleHoldHold for review or Reject it
Block throwaway email addressesOffMailinator, Guerrilla Mail, 10 Minute Mail and similar
Also block these domainsNoneYour own list, matched with subdomains
Most submissions per dayNo limitCounted over a rolling 24 hours

Warning

Leave Require a captcha off for a form that your own backend or your own markup posts to, unless that code sends a token. See Custom forms.

The rules are never sent to the public form page, so a spammer cannot read which words or limits to avoid.

Held for review

With Hold for review, a submission that breaks a link or word rule is saved but fires nothing: no form.submitted webhook, no workflow, no email. The visitor sees the normal success message.

On the form's page in the console, held submissions show a Held for review badge. Hover it for the reasons, for example 3 links (limit 1) or Contains blocked word "casino". Then:

  • Approve releases it. form.submitted and the record-created event fire as if it had just arrived, so workflows run normally.
  • Delete discards it. Nothing it would have triggered runs.

Email domain rules never hold: the visitor is asked for a different address, since a submission from a throwaway address cannot be followed up.

Test before going live

Each provider publishes test keys that run the real widget and the real verification, and always pass. Save them in Forms > Spam protection to try the whole flow on a draft form, then replace them with your own keys.

ProviderTest site keyTest secret key
Turnstile1x00000000000000000000AA1x0000000000000000000000000000000AA
hCaptcha10000000-ffff-ffff-ffff-0000000000010x0000000000000000000000000000000000000000
Google reCAPTCHA6LeIxAcTAAAAAJcZVRqyHh71UMIEGNQ_MXjiZKhI6LeIxAcTAAAAAGG-vFI1TnRWxMZNFuojJ4WifJWe

Test widgets show a "for testing only" line, so never leave them on a live form: with test keys, every visitor passes.

After saving your real keys:

  1. Open the form's hosted page from the console and complete the captcha.
  2. Submit it. The submission should appear on the form's page.
  3. If the visitor sees "Could not verify the captcha", the provider refused your secret key or hostname. Check both in the provider's dashboard.
SituationStatusMessage
Captcha missing or failed400Captcha verification failed. Please try again.
Captcha provider unreachable503Could not verify the captcha. Please try again.
Blocked or throwaway email domain400Please use a different email address.
Content rule, set to Reject it400Your submission could not be accepted.
Content rule, set to Hold for review200The normal success message
Any rate limit, daily cap or plan limit429Too many submissions. Please try again later.
Hidden bot trap filled, or a duplicate200The normal success message; nothing is stored

The hosted page shows each message in a toast and resets the captcha so the visitor can try again. The quiet answers are deliberate: telling a bot which check caught it tells it what to change.

Self-hosting

Nothing is required: Managed uses the built-in check until the platform has Turnstile keys. To run Managed on your own Cloudflare account, set both:

VariablePurpose
FORMS_TURNSTILE_SITE_KEYPublic site key handed to the hosted page
FORMS_TURNSTILE_SECRET_KEYVerifies tokens on submit. Keep it secret
FORMS_CHALLENGE_SECRETOptional. Signs the built-in check; derived from JWT_PASS when empty

Next Steps