How spam filtering works
The checks every submission goes through, what happens to bots and spam, and what you can turn on for extra protection.
Spam protection is built in on every plan and needs no setup. Every submission goes through the same checks, in this order.
| Check | Catches | What happens |
|---|---|---|
| Blocked IPs and countries | Addresses and countries you blocked | Dropped without notice |
| Allowed websites | Submissions from sites you didn't allow | Rejected with 403 |
| Rate limits | Floods from one client or at one form | Rejected with 429 |
| Honeypot | Bots that fill in the hidden _gotcha field | Dropped without notice |
| Fill time | Bots that submit in under 2 seconds | Dropped without notice |
| Cloudflare Turnstile | Bots that can't solve the challenge | Rejected with 403 |
| Links and link markup | Link spam | Stored in the spam folder |
| Duplicates | The same submission sent again within 24 hours | Stored in the spam folder |
Blocked IPs, blocked countries, allowed websites and Turnstile are optional and set per form. Everything else is always on.
Dropped without notice
Submissions caught by the honeypot, the fill-time check or your block lists are never stored and never counted. They still get a normal success response, so bots can't learn what gave them away. The JSON response has no submissionId in that case.
- Honeypot: the hidden
_gotchainput. People never see it, so they leave it empty. See Special fields. - Fill time: the
_elapsedfield, in milliseconds. The styled embed sends it for you. Forms without it skip this check.
Rate limits
| Limit | Retry after |
|---|---|
| 30 submissions a minute from one IP address, across all forms | 60 seconds |
| 5 submissions a minute from one IP address to one form | 60 seconds |
| 200 submissions an hour to one form, from everyone | 5 minutes |
Requests over a limit get 429 with a Retry-After header. People filling in a form by hand never come close to these limits.
The spam folder
Some submissions look like spam but could be real. Those are stored in the form's Spam folder instead of being dropped:
- Links: more than 5 links in total across all answers. Both
https://addresses andwww.addresses count. - Link markup: forum-style link code like
[url=...]or[link=...], or an HTML link like<a href="...">. - Duplicates: exactly the same answers as a submission the form received in the last 24 hours, ignoring capitals and surrounding spaces. Only submissions with an email address, or an answer of at least 20 characters, are compared, so identical short answers like a 5-star rating are never flagged.
Spam never sends notifications or auto-replies, never reaches your integrations and doesn't count toward your monthly limit. Open the Spam filter in the inbox to review it, and choose Not spam to move a submission back. See Inbox.
Add more protection
If spam still gets through, turn on more checks for the form in Settings, Spam protection:
Allowed websites
Accept submissions only from your own domains.
Cloudflare Turnstile
Add an invisible challenge that stops automated submissions.
Block IPs and countries
Drop submissions from specific addresses or countries.
Rotate the key
Give the form a new endpoint when the old one is being abused.
Tips
- Keep the
_gotchahoneypot in every form you write yourself, and send_elapsedwhen you submit with JavaScript. - Use the styled embed from the form builder. It includes both checks.
- Turn on Turnstile for forms that attract a lot of spam, like public signup forms.