Skip to content
Form and Project Settings

Honeypot and basic spam protection

Add honeypot spam protection to Qubeforms with an off-screen form field and optional submission timing. Configure trap names, inspect spam flags, and test your form.

1. Add the external form stylesheet

Save the CSS below as a separate file in your website. HTML examples load it from /static/assets/css/form-helper.css; React and Vue import ./form-helper.css beside the component. Adjust the path to match your site and confirm the file loads before publishing. The generic .form-helper class moves the text input off-screen without the hidden attribute or display: none. Keep tabindex="-1", autocomplete="off", and aria-hidden="true". New forms use fax_number; existing forms keep their saved name. Match Settings → Delivery & spam → Honeypot field in HTML, JSON, and drafts. To rename an existing trap, update both the setting and the website together. Never use a name that also collects a real visitor answer.

.form-helper {
    position: absolute;
    left: -9999px;
    width: 1px;
    height: 1px;
    overflow: hidden;
    pointer-events: none;
}

2. Connect the configured trap

Every plan includes baseline spam scoring and request limits. In Settings → Delivery & spam, read the Honeypot field name; new forms default to fax_number. Include an empty input with that exact name in your website form. It must not be a real question, a required field, or an email autofill target. This example keeps it hidden from visitors, keyboard navigation, and assistive technology. Keep it as a text input; avoid type="hidden", the hidden attribute, or display: none for the trap.

<link rel="stylesheet" href="/static/assets/css/form-helper.css">
<input class="form-helper" name="fax_number" type="text" tabindex="-1" autocomplete="off" aria-hidden="true">

3. Coordinate a custom honeypot name

A custom name must start with a letter or underscore and use only letters, numbers, underscores, dots, or hyphens, up to 191 characters. Prefer underscores for consistency across HTML and JSON. Choose a plausible unused field such as fax_number, website, or nickname; avoid honeypot or spam in the input name or ID. Update both the saved setting and the website, including any draft requests. Do not reuse a real field name: the configured honeypot is removed from stored field data, and filling it can classify the submission as spam. The trap is one signal, not a guarantee of blocking every bot.

4. Optionally include form-start timing

_cf_started_at lets scoring consider how quickly a visitor completed the form. Use Unix seconds recorded when the form becomes available, not milliseconds or the time of the submit click. Add the hidden input inside the form and run the script after it. Without JavaScript the empty value provides no timing signal. For a reusable AJAX form, set a new timestamp after a confirmed success when starting the next attempt; do not reset it on every step or failed retry.

<input id="contact-started-at" name="_cf_started_at" type="hidden" value="">
<script>
document.querySelector('#contact-started-at').value = String(Math.floor(Date.now() / 1000));
</script>

5. Understand scoring and quarantine

Baseline scoring considers a filled honeypot, very fast completion when timing is supplied, excessive links, known spam phrases, and elevated request velocity. A stored spam record can return successful receipt while going to Spam without normal inbox delivery. Draft saves reject a filled honeypot with 422. Inspect Spam signals and Policy used on the submission instead of assuming every success response means Inbox.

6. Add advanced controls when needed

Pro and Business add configurable sensitivity, rejection policy, CAPTCHA, timing, link thresholds, velocity, phrases, and email-domain rules. Enabling CAPTCHA also requires the matching widget and a fresh response token in your website requests. The provider’s public site key is available under Configured CAPTCHA site keys when configured; its secret stays on the service. See Advanced spam controls for the full setup.

7. Verify without disrupting production

Use a test form to compare a normal submission with a deliberately completed honeypot. Check the stored status or rejection message and inspect signals where a record exists. If legitimate visitors hit the trap, inspect autofill, reused names, and frontend mapping before changing spam policy. Keep allowed origins restricted to the sites you intend to use.

Keep private credentials private

Public form keys can appear in browser code. Read keys, management credentials, and webhook signing secrets must stay on the server.