Hunch

Detect spam form submissions in Google Sheets

Updated · Edoardo Panichi, maker of Hunch

=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.

RowAB
1SubmissionSpam probability
2Name: 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
3Name: asdkfj asdf | Email: test123@mailinator.com | Message: asdfasdf0.96
4Name: 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
5Name: Maria Chen | Email: maria@northwindlogistics.com | Message: Following up from the webinar last week, would like pricing for the team plan.0.13
6Name: 123456 | Email: xj8k2n@tempmail.com | Message:0.93
7Name: Best Loans 4U | Email: loans@quickcash-approve.info | Message: Get approved for a business loan today no credit check click here0.96
8Name: Dave Okafor | Email: dave.okafor@gmail.com | Message: Curious if this integrates with Airtable before I buy.0.16
9Name: Test Test | Email: test@test.com | Message: test0.94
10Name: 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.

RowAB
1SubmissionSpam probability
2Name: 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
3Name: R | Email: r@r.com | Message: pricing?0.51
4Name: Sasha Kim | Email: sasha.kim@outlook.com | Message: hi0.80
5Name: Free Gift Winner | Email: claim-prize@bonus-reward.top | Message: You have been selected, claim your free gift card now0.97
6Name: 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
7Name: info | Email: info@info.com | Message: interested0.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

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?
No. It scores text after the fact; it does not stop a bot from submitting in the first place. Use both: reCAPTCHA at the form, this column to triage what still gets through.
Does it check whether the email domain is disposable?
Not directly. Combine a REGEXMATCH check against a list of known disposable domains with the probability column for a stronger combined signal.
Will a genuine but very short inquiry get flagged as spam?
A short genuine message usually reads lower than an obvious spam pitch, but it also gives the model less to work with. Read anything in your middle band yourself before archiving it.
Can it score submissions as they arrive instead of in a batch?
Not by itself. Sync new rows to the sheet with a Zapier connection or an Apps Script trigger on form submit, then point the formula at the combined text column as rows land.
What is worse, marking a real lead as spam or letting spam through?
Missing a real lead usually costs more than a rep spending ten extra seconds on a spam row, so lean the threshold toward under-flagging until you have read a week of your own middle band and know how the two costs compare for your form.

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

More guides