Detect spam form submissions in Google Sheets
=HUNCH(text, question) returns the probability, 0 to 1, that a form submission is spam, a fake signup, or a low-quality lead rather than a genuine inquiry. Point it at your form export and every row gets a number to sort on, instead of a name and a message you have to read one by one.
A blocklist only catches what it has already seen
A list of banned words or domains stops the spam pitch you have already read once and rewrites itself into a new one the next week: a new domain, a different opening line, the same offer to guarantee page-one rankings. Reading the submission for what it is asking, rather than for a word it contains, does not need to be rewritten every time the wording changes.
Combine the fields, then ask
A form export usually carries name, email, and message in separate columns. Combine them into one cell before judging, so the model sees the whole submission at once.
=A2&" | "&B2&" | "&C2=HUNCH(D2:D500, "Does this form submission look like spam, a fake signup, or a low-quality lead rather than a genuine business inquiry?")In Excel: =HUNCH.ASK(D2:D500, "Does this form submission look like spam, a fake signup, or a low-quality lead rather than a genuine business inquiry?")
Column D is the combined text from the formula above; the probability formula points at that column, not at the three original ones separately. Full syntax is on the HUNCH reference.
Real outputs
Nine submissions to a contact form on a B2B software site, name, email, and message combined into one line each.
| Row | A | B |
|---|---|---|
| 1 | Submission | Spam probability |
| 2 | Name: John Smith | Email: john.smith@acme.co | Message: Hi, we are looking for a tool to score inbound leads for our 40-person sales team. Can we set up a demo? | 0.17 |
| 3 | Name: asdkfj asdf | Email: test123@mailinator.com | Message: asdfasdf | 0.96 |
| 4 | Name: SEO Expert | Email: backlinks@rank-boost-service.ru | Message: I noticed your website could rank higher. We offer guaranteed page 1 rankings, contact us for a free audit. | 0.96 |
| 5 | Name: Maria Chen | Email: maria@northwindlogistics.com | Message: Following up from the webinar last week, would like pricing for the team plan. | 0.13 |
| 6 | Name: 123456 | Email: xj8k2n@tempmail.com | Message: | 0.93 |
| 7 | Name: Best Loans 4U | Email: loans@quickcash-approve.info | Message: Get approved for a business loan today no credit check click here | 0.96 |
| 8 | Name: Dave Okafor | Email: dave.okafor@gmail.com | Message: Curious if this integrates with Airtable before I buy. | 0.16 |
| 9 | Name: Test Test | Email: test@test.com | Message: test | 0.94 |
| 10 | Name: Priya Patel | Email: priya@lumenhealth.io | Message: We filled this out by mistake, please disregard, sorry. | 0.90 |
The row worth reading twice is Priya Patel's: a plausible name, a real-looking company domain, and a message that says the form was filled out by mistake, still scores 0.9. That is not the model mistaking a real person for a bot. The question asks whether the submission is spam, a fake signup, or a low-quality lead rather than a genuine business inquiry, and an accidental, disregard-this submission genuinely is not a business inquiry, even though nobody did anything wrong. If you only want to catch malicious and automated spam, not accidental submissions, narrow the question to say so; as written, it also catches this kind of row on purpose.
The middle of the range
Six submissions picked to sit away from the obvious extremes.
| Row | A | B |
|---|---|---|
| 1 | Submission | Spam probability |
| 2 | Name: Growth Partners Agency | Email: hello@growthpartners.io | Message: We help SaaS companies with SEO and link building, would love to chat about a partnership. | 0.70 |
| 3 | Name: R | Email: r@r.com | Message: pricing? | 0.51 |
| 4 | Name: Sasha Kim | Email: sasha.kim@outlook.com | Message: hi | 0.80 |
| 5 | Name: Free Gift Winner | Email: claim-prize@bonus-reward.top | Message: You have been selected, claim your free gift card now | 0.97 |
| 6 | Name: Tom Becker | Email: tom@beckerconsulting.com | Message: Not looking to buy right now, just researching options for next year, can I get on your mailing list? | 0.27 |
| 7 | Name: info | Email: info@info.com | Message: interested | 0.86 |
"R" asking only "pricing?" lands at 0.51, close enough to the middle that the model is telling you it genuinely cannot decide: a terse name and a one-word question look exactly like a low-effort probe and exactly like a real buyer typing fast on a phone. Compare the two rows with an ordinary-looking name and domain: "hi" with nothing else scores 0.8, while a full sentence explaining a genuine not-yet-ready interest scores 0.27. A plausible name is not enough on its own in either direction; the message still has to say something.
Set a threshold
In these fifteen rows, genuine inquiries top out at 0.27 and obvious spam starts at 0.93, with the debatable rows, the agency partnership pitch, the bare "hi", the accidental submission, the generic info@ address, spread from 0.51 to 0.9. That gap between roughly 0.3 and 0.9 is wider than a single cutoff can cleanly split, which is exactly why it is a review band and not a hard line.
=SORT(FILTER(D2:D500, E2:E500>=0.3, E2:E500<0.9), 2, FALSE)Auto-archive above the top of that range, forward anything below the bottom of it to sales without a second look, and read the middle band yourself for a week before you trust either edge.
Read the middle band before you touch the top and bottom. Move the threshold based on what you find there, not on the number itself.
Limits
- It does not check the email domain against a blocklist or verify deliverability. Combine a REGEXMATCH check against known disposable domains with the probability column for a stronger signal.
- It does not stop a submission at the point of entry. It scores what is already in the sheet; pair it with an Apps Script trigger on form submit if you want a live score on new rows.
- It will not catch everything. No filter does. Use it alongside a honeypot field or reCAPTCHA at the form itself, not instead of one.
- It does not check whether the same message was submitted from ten different addresses in a minute. That pattern lives in your timestamps, not the message text; a COUNTIFS on the message column plus a time window catches it separately.
Copy the template to try this on your own form export. The lead scoring guide covers the same probability pattern for qualifying a lead once it clears this filter, and REGEXMATCH vs asking a question goes deeper on why a keyword match misses cases like the ones above.
Questions
Can this replace reCAPTCHA on my form?
Does it check whether the email domain is disposable?
Will a genuine but very short inquiry get flagged as spam?
Can it score submissions as they arrive instead of in a batch?
What is worse, marking a real lead as spam or letting spam through?
Run it on your own column
Copy the template (or use the Excel add-in), paste your key, point the formula at your data. Every formula here has its Excel spelling underneath. 100 rows free to start, then $29 for 5,000 rows. Credits never expire and there is no subscription.
Reference: HUNCH