Skip to content

How spam protection works

Every form has four layers of spam protection, all on by default and invisible to real visitors. There is no CAPTCHA. This page explains each layer, what a visitor sees when it stops a submission, and the settings you can change.

LayerWhat it catchesWhat the visitor seesStored?
HoneypotA hidden field, labelled “Leave this empty”, that people never see but bots fill in. Its name is different for each form.The normal success message.Yes, as spam
Timing checkSubmissions sent less than 3 seconds after the form was shown.Please wait a moment before submitting.No
Duplicate checkThe same submission arriving twice within 60 seconds, such as a double tap.The first copy’s own result once it is saved; Your first attempt is still being processed. Please wait a few seconds, then try again. while it is not.Only the first
Rate limitsToo many submissions from one IP address, or to one form. See below.Too many submissions. Please try again later.No

The honeypot answers with a success message on purpose, so a bot learns nothing. The submission is kept as a spam entry: it sends no email, fires no webhook and starts no workflow, and it is hidden in Form Entries unless Include Spam is ticked. If a real person filled the honeypot, usually through a password manager, tick the entry and choose Mark as Not Spam from Bulk actions. At most 50 honeypot entries are kept per form each hour, so a bot attack cannot fill the database.

The duplicate check never says “Thanks” for a copy unless the first one was really saved.

LimitDefaultCan you change it?
One IP address, one form5 submissions an hourYes, per form
One IP address, all forms together20 submissions an hourNo
All visitors, one form30 submissions a minuteWith a filter, see below

The form-wide limit shows This form is receiving too many submissions. Please try again later. Every attempt counts toward the limits, including ones then refused for a missing required field.

These go in settings.spam_protection:

"spam_protection": {
"honeypot": true,
"timing_check": true,
"min_submission_time": 3,
"rate_limit": {"max": 5, "window": 3600}
}
OptionWhat it doesDefault
honeypotAdd the hidden honeypot field.true
timing_checkRefuse submissions sent too soon after the form was shown.true
min_submission_timeThe minimum, in seconds.3
rate_limit.maxSubmissions allowed from one IP address to this form in the window, from 1 to 100.5
rate_limit.windowThe window in seconds, from 60 (a minute) to 86400 (a day).3600

Raise rate_limit.max for forms many people submit from one network, such as an event sign-up used on a school or office connection.

  • Behind a proxy or CDN, every visitor can appear to come from the proxy’s address and share one rate limit. List your proxy addresses with the pforms_trusted_proxies filter so the visitor’s own address, from X-Forwarded-For, is used instead.
  • pforms_global_rate_limit changes the 30-a-minute form-wide limit; it receives the limit and the form ID.
  • pforms_spam_detected fires when the honeypot or timing check stops a submission, and pforms_rate_limit_exceeded when a per-form limit is hit.
  • The connector’s formengine_test_submit does not run these checks.
  • Testing too fast. Submitting within 3 seconds of loading the page, as browser autofill and test scripts do, shows Please wait a moment before submitting. Wait a few seconds.
  • “Nothing arrived but the form said thank you.” The honeypot stopped it. Tick Include Spam in Form Entries to find it. A password manager or autofill that fills every field, including hidden ones, can trigger the honeypot.
  • Spam still gets through. Mark it with Mark as Spam on the entry; it is hidden from the list and counts. There is no learning filter.