Skip to content

Anti-spam

OctaForms fights spam with two main tools: a honeypot with a quarantine, and rate limiting. The security token helps too, but it is deliberately not the main barrier. The guiding principle throughout is that a real person’s submission should never be silently thrown away.

A honeypot is a hidden field that real visitors never fill in, but many bots fill automatically. You add one by marking any field with "honeypot": true in the config. See Field types.

If you render your own markup, a honeypot only works when it is hidden the right way:

  • Hide it with CSS, for example position: absolute; left: -9999px. Never use type="hidden", which bots recognise.
  • Add tabindex="-1" and autocomplete="off" so keyboards and autofill skip it.
  • Give it a name that browsers will never autofill. Names like company, website, phone, email or name are risky, because a browser can fill them for a real person. The config validator warns about risky names.

The bundled helper and the shortcode render honeypots correctly for you.

When a honeypot is filled, OctaForms does not drop the submission. It stores it in a spam quarantine and returns a response that looks exactly like success, so the bot learns nothing.

This matters because the honeypot’s most common false positive is browser autofill filling the field for a real person. Those real submissions land in the quarantine too, where you can review and recover them.

Find it under Submissions → Spam quarantine. Recovering a submission also sends its emails and webhooks, as if it had come through normally. A sudden spike in the quarantine usually means you are catching real people, so check the honeypot’s name.

The quarantine clears itself after 30 days.

OctaForms limits requests with two separate counters, because “too many requests” and “too many successful submissions” are different problems:

  • Request floods earn a temporary ban. Someone hammering the endpoint gets a 429 ban that lifts after a while.
  • Too many successful submissions from one network get a gentler response: a 429 that says “try again shortly”, with a Retry-After header, and never a ban. This is what protects a busy office behind one shared IP during a campaign. Real people filling in the form are asked to wait, not blocked.

Your integration should read Retry-After and wait, rather than retrying immediately. See the error table in Your own JavaScript.

Every submission carries a token fetched from the API. It does three things: it deduplicates double submits, it acts as a time-trap against instant bot submissions, and it requires JavaScript to obtain.

It is worth being clear that the token is not the primary anti-bot defence. A determined bot can run JavaScript. The honeypot and rate limiting do the heavy lifting; the token raises the cost of the easy attacks.

A form can waive the token with settings.requireToken: false, which you would only do if a security plugin blocks the token endpoint. Honeypot and rate limiting stay active regardless. See the token contract.