Spam Detection Improvements, Turnstile CAPTCHA, and Manual Reclassification
Spam isn't a problem you solve once. Bots evolve, submission patterns shift, and the signals that worked last month start to drift. This release is a tuning pass on TorchWarden, a new hard gate for forms that need it, and a set of manual controls so you're not dependent on automated scoring alone.
Smarter spam detection
TorchWarden now detects submissions from known script clients. If a request arrives from curl, Python Requests, wget, or Go's HTTP client, it adds 25 points to the spam score. That's not enough to flag it alone, but combined with disposable email or keyword signals, scripted submissions now reliably cross the threshold.
Two accuracy fixes went in alongside the new signal. The link count threshold is raised from 2 to 3 unique URLs. Two links is common in legitimate submissions: a personal site and a social profile, or a citation and a source. The old threshold produced false positives in those cases. URL values are also now excluded from keyword matching, so a website field containing a spammy-sounding domain no longer fires the keyword signal on its own.
The spam panel in submission detail got a UI pass as well. Signal labels now read as plain English ("Honeypot triggered", "Duplicate submission") instead of the raw identifiers. The score display was also corrected: scores above 100 are valid, and the panel now shows the actual value with a "Spam threshold: 60 pts" reference instead of capping at 100.
Cloudflare Turnstile CAPTCHA
For forms where you want a hard gate rather than passive scoring, you can now enable Cloudflare Turnstile per form in Form Settings → Spam Protection. Submissions without a valid CAPTCHA token are rejected at the edge before anything reaches the database.
Turnstile is optional and per-form, so you can apply it where the risk justifies the friction without adding it to every form you run.
Manual reclassification
TorchWarden's scoring is accurate, but no automated system is right every time. You can now mark any submission as spam or not spam directly from the submissions table, the detail drawer, or the submission detail page. The override is stored alongside the original score so the signal is available for future rule review.
This gives you a correction path when the model is wrong, without having to adjust global thresholds or wait for a model update.
Per-form rate limit controls
The rate limiter now accepts per-form overrides. You can set a custom IP-per-minute cap and a form-per-hour cap for any form from Form Settings → Rate Limits. The defaults remain the same; overrides apply only to the form you configure.
Alongside the per-form thresholds, you can now add an IP blocklist and an IP allowlist per form. Blocked IPs are rejected before rate limit accounting runs. Allowlisted IPs bypass the per-IP checks entirely, which is useful when you have a known integration or internal tool that submits at high volume.
Spam filtering and bulk delete in the dashboard
The submissions table now has a type filter: All, Clean, or Spam. Filtering to Spam lets you review flagged submissions without scrolling through the full list.
When you select rows in the table, a trash icon appears in the toolbar. Clicking it opens the bulk delete confirmation. The shortcut was always there, buried in the actions menu. It's visible now.
We’d love to hear from you
Have feedback on this update, or an idea for a feature you’d like to see? We read every message and genuinely take them into account as we build.
hello@formtorch.com