Feature — collecting

Spam protection you never have to pass.

NumoForms filters junk submissions with three layers enforced by a database trigger rather than by the form: an off-screen honeypot field, a dwell-time floor of 3 seconds by default and configurable per survey, and a rate limit of 30 responses per minute per survey. There is deliberately no reCAPTCHA. A response the checks flag is not discarded — the respondent is told what happened and can confirm it.

The check lives in the database, not the page

Responses in NumoForms insert straight from the browser into the database. That also means any rule written only into the interface is advisory. A script that posts directly to the API never renders your JavaScript, so it never sees the check.

So the three checks run in a database trigger. Every insert passes through it, whether it came from the hosted survey page, an embedded survey in another site, or a script someone wrote at three in the morning. It is the same reasoning behind close dates and response caps, which are also enforced at database level rather than by hiding a button.

Where the checks run matters more than how clever they are. Two of the three signals — the honeypot value and the elapsed time — are sent by the browser, so a bespoke script can leave the hidden field empty and send no timing at all. The rate limit needs nothing from the client, which is why it is the layer that still holds when the other two are stripped.

The three layers

1. Honeypot

A field positioned off screen that a human filling in the survey never sees and never focuses. Automated form-fillers tend to complete every input they find. Anything arriving with that field populated was not filled in by a person reading the page.

2. Dwell time

A floor, in seconds, on how long a response took. The default is 3 and it is set per survey, so a 40-question consultation can demand more than a two-question feedback form. Missing timing is not treated as spam, so older clients and responses resumed through a save-and-continue link still work.

3. Rate limit

Responses per minute per survey, defaulting to 30. This one needs nothing at all from the client, which is the point: it still holds against a bot that strips every piece of metadata the other two layers rely on.

Why there is no reCAPTCHA

This is the decision most likely to come up in procurement, so here is the whole argument.

It makes Google a sub-processor on your consultation

Dropping reCAPTCHA onto a public consultation form means every resident who opens it has data sent to Google before they answer a question. Someone in your organisation then has to record that transfer, justify it, and defend it in a privacy notice for a form that exists to gather opinions about bin collections. NumoForms keeps survey content and responses in Supabase's London region, and the GDPR and data protection page sets out what that means in practice. Adding an advertising company to the processing chain to catch a handful of junk rows is a poor trade for a local authority running public consultations.

It fails disabled respondents

Image and audio challenges are a well-documented cause of failed submissions for disabled people. Our accessibility page argues against exactly that pattern. Shipping a CAPTCHA would contradict a position we publish, and a survey that a screen reader user cannot finish is not a survey with good spam protection. It is a survey with a biased sample.

The three checks NumoForms runs are invisible. Nobody is asked to prove anything, identify a bus, or transcribe distorted audio. There is no challenge to fail.

Rejection is never final

Every heuristic here has an honest false-positive case, and pretending otherwise would be how you lose real data.

A two-question survey genuinely is answered in a couple of seconds. A room of thirty people at a consultation event, all handed the link at once, genuinely does produce thirty submissions in the same minute. Both look exactly like an attack from the database's point of view.

So a flagged response is not silently binned. The respondent is shown what happened, keeps their answers, and can send them again — the second attempt drops the timing signal, because a person has just vouched for it. The honeypot and the rate limit still apply, so a genuine flood is asked to try again in a moment rather than waved through. That turns the filter into friction for a script and a single extra tap for a person. Losing a genuine consultation response is worse than accepting a junk one, and a junk one is obvious later in your results and drop-off analytics.

What this does not do

Stated plainly, because you will find out eventually.

  • No Cloudflare Turnstile. It is the privacy-respecting challenge most often suggested as the reCAPTCHA alternative, and it is not integrated today.
  • No IP-based blocking. Nothing here blocks or rate-limits by address, so a determined attacker distributing submissions across many sources and pacing them below the limit is not stopped by these three layers.
  • Two of the three signals come from the browser. The honeypot value and the elapsed time are supplied by the client, so a script written specifically for your survey can decline to send either. They stop commodity form-fillers, not a targeted attacker; the rate limit is the layer that does not depend on cooperation.
  • No content filtering. The checks look at how a response arrived, not what it says. Offensive free text is a moderation problem; single-step approvals hold responses until someone signs them off.

What these layers are good at is the ordinary case: automated form-fillers, bulk submissions from a single script, and the accidental double-submit.

Questions people ask about survey spam

Does NumoForms use reCAPTCHA?

No, and that is a deliberate decision rather than a gap. Adding reCAPTCHA would make Google a sub-processor on every public consultation, which a data protection officer then has to account for. Its image and audio challenges are also a well-documented cause of failed submissions for disabled respondents. The three checks NumoForms runs are invisible: there is no challenge to fail.

What happens if someone genuinely answers faster than the dwell time?

They are shown what happened and can confirm the submission, which then goes through. A two-question survey really is answerable in under three seconds, so a hard rejection would throw away real responses. Losing a genuine consultation response is worse than accepting a junk one.

Why enforce spam checks in the database rather than in the form?

Because responses insert straight from the browser into the database. Anything checked only in the interface can be skipped by a script that posts directly, so a UI-level check is a suggestion rather than a control. NumoForms runs the honeypot, dwell-time and rate-limit checks in a database trigger, which every insert passes through regardless of where it came from.

What is the default dwell time and rate limit?

The dwell-time floor defaults to 3 seconds and is configurable per survey. The rate limit defaults to 30 responses per minute per survey. The rate limit needs nothing from the client, so it still applies to a bot that strips the timing metadata entirely.

Does NumoForms block spam by IP address?

No. There is no IP-based blocking and no Cloudflare Turnstile integration. The protection is the honeypot, the dwell-time floor and the per-survey rate limit, all enforced in the database.

Filter the junk without a puzzle.

The honeypot, the dwell-time floor and the per-survey rate limit run in a database trigger, so every response passes through them whichever route it came in by. Your respondents are never asked to identify a bus.

  • Three layers: honeypot, dwell time, rate limit
  • Dwell-time floor configurable per survey, 3 seconds by default
  • A flagged respondent can confirm and carry on
Start building