Inspiration

Imposter scams were nearly 1 in 3 fraud reports to the FTC in 2025, with $3.5 billion in reported losses. They all work the same way: the message gives you the phone number or link to use, and you use it. The standard advice is "look up the company yourself and call the number you find." Almost nobody does that when a text says their account is locked. And now that scammers use AI, the spelling mistakes that used to give them away are gone.

Asking a chatbot "is this a scam?" doesn't fix it either. You get a confident answer and nothing you can check. I wanted a tool that does the looking up for you and shows its work.

What it does

You paste a text or email, or drop in a screenshot. Callback works out who the message claims to be, then finds that organization's real domain and phone number from sources the sender can't edit: a hand-checked list of 27 commonly impersonated US organizations, and the organization's own contact pages. It compares those against the links, phone numbers and emails in your message, and gives one of four verdicts: doesn't match (with the real number to call instead), matches, can't verify, or no organization claimed. Every verdict comes with numbered pieces of evidence.

If you already clicked or paid, it gives you a checklist based on how you paid, plus a summary you can paste into a report to the FTC.

How I built it

The key decision: the AI never decides the verdict. Gemini only reads messy text and screenshots into structured fields, and writes the plain-English explanation. Seven fixed rules decide the verdict. Every sentence in the explanation has to cite a numbered piece of evidence like [E1], or it gets dropped. Anything the AI "extracts" has to appear in the original message, or it gets thrown out.

It's built with Next.js, TypeScript and Tailwind, with Gemini (gemini-3.5-flash-lite) for reading and explaining. Links in a message are never opened. The only requests Callback makes are safe HEAD requests, and they refuse private and cloud-metadata addresses. I wrote unit tests with Vitest and end-to-end tests with Playwright. If there's no Gemini key or the quota runs out, it falls back to a keyless mode where the rules still run.

I used AI coding assistants to write most of the code from a spec I wrote, then checked what they produced against real runs.

Challenges

  • "Official" data isn't always trustworthy. Wikidata had a lookalike domain, only 45 days old, listed as Citigroup's official site. Trusting it would have flagged real Citi alerts and legitimized a fake. That's why I built the hand-checked list and added a domain-age check.
  • Big companies hide their phone numbers. Some sites bury them or block automated checks. Instead of guessing, Callback says "can't verify."
  • Stopping the AI from making things up. The citation rule was my answer. In my test run, 74 of 80 explanation sentences kept their citations and 5 uncited ones were dropped.

What I learned

I tested Callback against plain Gemini on 35 messages I wrote myself (20 scams, 15 legitimate). Gemini alone flagged all 20 scams, but it also called a real payment receipt a scam and showed no evidence. Callback caught 15 of the 20 with zero false alarms, and said "can't verify" on 10 of the 35 instead of guessing. It catches fewer, and I think that's the right trade-off when someone is deciding which number to call. But these are messages I made up, so it's a demonstration, not a real-world accuracy rate.

I also learned that saying "I don't know" is a feature. Most of my work went into making the tool honest about what it can't confirm.

What's next

More countries' banks and post offices, a phone share-sheet so you can send a suspicious text straight to Callback, and signed public phone registries that organizations can publish themselves.

Built With

Share this project:

Updates

Submission history