Inspiration

The day a look-alike of your name goes live, no alert fires and nothing breaks. DMARC explicitly does not cover look-alike ("cousin") domains (RFC 7489), a mail-ready look-alike intercepts quietly, and if you find out at all, it's from a confused customer's email — not from a tool. The FBI's IC3 counted USD 2.77 billion in business email compromise losses in 2024, and misspelled domains are one of its named tells. Meanwhile a seven-month academic study found that nearly all popular domains are actively typosquatted while few owners protect themselves. The gap we wanted to close: a small company has no brand-protection budget and no way to even see this exposure. So we built the screen that shows it — and, in the same motion, fixes it.

What it does

typo.watch takes one input — your domain — and answers three questions with registry-grade evidence, in about ten seconds:

  1. Strangers hold N — look-alike permutations of your name (replacement, omission, transposition, homoglyph, TLD swap, keyword/combosquat) that other people already own, ranked by attacker economics: mail-ready beats parked, live-in-search beats invisible, fresh beats decade-old. Every "taken" is a real RDAP answer; every row's evidence panel opens the raw registry JSON, the SerpApi search verdict (including the honest negative, "checked against Google — does not appear"), a score breakdown that sums, and a ready-to-send notice draft addressed to the registrar's abuse contact.
  2. Forward to you M — look-alikes that already redirect home are shown in green as reassurance, with their 301 chain one click away (Google's own defensive gogle.com is the proof case).
  3. Free and dangerous K — permutations nobody owns yet, with live name.com prices. Tick five, click Defend, and they are registered and pointed at your real site through the name.com API — sandbox-labelled in the demo, and the same flow registered typo.watch itself in production on day one.

It keeps watching: each scan is snapshotted, and the next one opens with a diff — "Since 14 Aug 2026: 2 new registrations, 0 now forward to you, 0 newly free." A permalink makes any scan shareable with the boss who approves the $64.95. And one honest limit is printed on the page itself: subdomain look-alikes, free-hosting pages, non-Latin homographs beyond our table, and social handles are not covered.

How we built it

FastAPI + HTMX server-rendered two-phase flow (counts paint before evidence; no SPA), SQLite for snapshots and response caching, Tailwind compiled to one CSS file, self-hosted IBM Plex Mono — the whole result page is a dark "registry ledger" designed so the evidence hierarchy is the visual hierarchy.

brand -> permutation engine (dnstwist-class fuzzers: replacement, omission,
         transposition, homoglyph, TLD swap, keyword/combosquat)  ~150 candidates
   -> name.com Core v1  domains:checkAvailability   (batched 50, live prices)
   -> RDAP via IANA bootstrap                        (authoritative taken/free; 404 = free)
   -> HTTP/DNS probe                                 (redirect chains, MX, parked detection)
   -> SerpApi                                        (live-in-search, rank-ordered budget, 10/scan)
   -> rules score attacker economics -> Claude writes ONE line per top card from given facts
                                        (a deterministic guard strips anything beyond them)
result -> three bands -> Defend: name.com domains (register) + URL forwarding (point home)
        + notice draft (registrar abuse contact) -> snapshot -> watch diff + permalink

The trust rule that shaped everything: a model never decides taken/free/yours. Rules decide; RDAP and name.com answer; the model writes one explanatory line from facts it is handed, and a deterministic guard removes any claim (search, rank, band) it was not given. Every judgment call — class weights, the "established, likely unrelated" demotion, ccTLD non-authoritative handling — is documented on the public methodology page.

AI use declared: Claude (Anthropic) writes the one-line card reasons and polishes notice drafts from given facts, under a deterministic guard; it makes no taken/free/yours decisions. The app was built with AI pair-assistance; all code was written during the submission period (clean-sheet repo).

Challenges we ran into

  • The sandbox is its own world. name.com's test environment has a separate username, token, credit — and its prices differ from production's, which our Defend flow learned live ("Purchase price does not match") and now handles by re-quoting each domain against the sandbox immediately before registering it.
  • Replay masking real failures. Our demo fallback (curated snapshots with a visible label) once hid a broken production model call for two rounds, because the snapshots carried real prose. Since then every review round must live-scan a never-seeded brand on production.
  • Honesty is an engineering problem. The model kept narrating things it wasn't told — search results it never saw, its own ranking. The fix was layered: a tri-state search fact ("appears" / "does not appear" / "not checked"), a sharpened prompt, and a deterministic guard that strips unsupported clauses. The negative search answer got its own visible chip, because "we looked and found nothing" is a different claim from silence.
  • Cold-start truth. A test passed for days only because a developer's .env and local DB supplied hidden state; our fresh-clone rule now runs the suite from a copy with neither, so a judge cloning this repo gets the same green we see.

Accomplishments that we're proud of

  • Every claim on screen traces to a raw response one click away — RDAP JSON, name.com availability, SerpApi results, the score arithmetic that sums, the 301 chain on the green band.
  • typo.watch is its own case study: the domain was found, priced, and registered through the same name.com Core v1 API the product uses, on day one. The address bar is the receipt.
  • 175 automated tests, six adversarial review rounds with fresh-context examiners and demo-rehearsal gates, and a UI that survived a 119-row, 9000px worst case at nine viewport widths.
  • The honest states are designed, not apologetic: "not searched (10 per scan)", "checked — does not appear", "not authoritative (no RDAP server for this TLD)", the sandbox label at the point of action, and a not-covered line that names what we cannot see.

What we learned

That defensive tooling lives or dies on trust, and trust is built from boring things: authoritative sources, visible raw data, arithmetic that adds up, and a model kept on a short, factual leash. Also: registry APIs reward reading the docs — batch limits, rate limits (20 req/s, 3000/h), sandbox quirks — and a demo path is a feature you build, test, and rehearse like any other.

What's next

Watch mode as a subscription (the diff is already the product's heartbeat), ccTLD coverage as registries adopt RDAP, registrar-agnostic Defend, and the honest expansion of the not-covered line: subdomain look-alikes and social handles need different detection paths, and we would rather ship them right than claim them early.

Built With

Share this project:

Updates

Submission history