Skip to main content
Menu
On this page

Spam and bot protection

The honeypot, timing checks, rate limits, and the optional Turnstile human check Fillo applies today.

Fillo combines renderer signals and server limits to reject simple automated submissions without putting a visible challenge on every form.

What Fillo applies

The default React and DOM renderers include an off-screen honeypot and report elapsed fill time. The public response endpoint treats a filled honeypot or a submission under 400 milliseconds as automated and returns a plausible success without storing the response.

Public write routes also apply per-IP, per-form, and per-workspace rate limits. Schema validation, file binding, response limits, and submission trust add separate boundaries around what a request can store or deliver.

These layers come from the renderer and the server. There's no per-form dashboard toggle for them.

In a headless form

FilloProvider and the framework-neutral controller use the same engine, but a fully custom surface has to go through the controller's submission path instead of posting arbitrary JSON directly. Raw API clients don't produce the built-in renderer's honeypot and timing signals, though the endpoint still validates and rate-limits them.

tsx
<FilloProvider form={form} client={client}>
  <YourAccessibleLayout />
</FilloProvider>

Require a human check

For forms that need more than heuristics, turn on Require a human check (Turnstile) in the form's Respondents settings — or set settings.trust.challenge: "turnstile" in a code-defined schema. The SDK renders a Cloudflare Turnstile check before the form can submit, and Fillo verifies the token on the server: a submission without a valid token is rejected, no matter what the client rendered. Fillo hosts the keys, so there's nothing to configure, and a form with the check off loads no third-party script.

The human check is independent of submission trust — a form can require both.

What's not included

Fillo doesn't expose reCAPTCHA, proof-of-work, or an allowlist. And the passive heuristics above aren't proof that a respondent is human — only the Turnstile check makes that claim.

For a signed-in product flow, pass a server-verified respondent and enable submission trust when unverified traffic should wait for review. For a public high-risk flow, put abuse controls in the host application or a server-side layer in front of the form as well.

Responding to abuse

  1. Check whether the traffic uses the hosted form, default SDK, headless SDK, or raw endpoint.
  2. Review source, timing, repeated values, and respondent context in accepted responses.
  3. Add a response limit only when its identity model fits the form.
  4. Require host-app sign-in for an access-controlled workflow.
  5. Delete unwanted accepted responses and rotate any exposed management credential.

Updated

Was this page helpful?