← field notes

How lookalike domains hide in plain sight: the punycode trick behind homograph phishing

A domain name that looks exactly right can still be wrong. Not “wrong with a typo you’d catch if you squinted.” Wrong at the byte level, while every pixel on screen matches the real thing. That gap between what a browser renders and what a domain actually resolves to is the whole trick behind punycode lookalike domains, and it’s been sitting in the DNS spec since 2003.

What punycode actually is

DNS was built for ASCII. Every hostname that ever gets queried ultimately has to fit into that narrow character set, no accents, no Cyrillic, no Han characters. But the web is global, and plenty of businesses need domains in their own script. The fix, standardized in RFC 3492, is punycode: an ASCII-Compatible Encoding that takes a string of Unicode characters and turns it into a string of ASCII characters prefixed with xn--. So a domain registered as “münchen.de” actually lives in DNS as xn--mnchen-3ya.de. The Unicode version is what a person types or reads; the punycode version is what actually gets resolved.

Browsers exist to hide that translation from the user. When a page loads, the browser decodes the punycode label and decides whether to display the readable Unicode string or the raw xn-- string in the address bar. That decision, made silently thousands of times a day, is the entire attack surface. If the browser shows the decoded Unicode and the decoded Unicode happens to look identical to a brand the visitor trusts, the trick works. If it shows the raw punycode string, the visitor sees an ugly jumble of letters and numbers and, ideally, gets suspicious.

The homoglyph trick

The abuse depends on homoglyphs: characters from different scripts that render as visually identical, or nearly identical, glyphs. Cyrillic “а” (U+0430) looks the same as Latin “a” (U+0061) in most fonts. Cyrillic “е,” Cyrillic “р,” and Cyrillic “с” all have Latin doubles too. Greek omicron looks like a Latin “o.” Mix a handful of these into a brand name, register the resulting string, and DNS will encode it as an unremarkable xn-- domain that resolves fine and can hold a valid TLS certificate.

The Unicode Consortium tracks this formally. Unicode Technical Standard 39 maintains a “confusables” table mapping characters across scripts that are visually ambiguous, the same reference browser vendors, registrars, and brand-protection tools pull from when they build their own spoof-detection logic. It’s not a secret list; it’s public infrastructure for exactly this problem, because the ambiguity is a property of how human eyes parse glyphs, not something anyone can patch out of Unicode.

The detail that matters most here is single-script versus mixed-script. A domain that mixes Latin and Cyrillic characters in the same label is an obvious tell, and most browsers will refuse to render it as Unicode, falling back to the raw punycode string instead. A domain built entirely from one foreign script, where every character including the ones that happen to look like Latin letters is genuinely Cyrillic, is much harder to catch that way, because a fully Cyrillic domain is exactly what a legitimate Russian-language business would register. That’s not a hypothetical: a well-documented 2017 proof of concept built an all-Cyrillic domain that rendered as a pixel-perfect “apple.com” in browsers of the day, because the mixed-script heuristic simply didn’t apply to a domain with no script mixing at all.

Why the address bar is the battleground

Everything downstream of the browser trusts the address bar. Password managers autofill based on the domain shown. Users glance at a green padlock or a certificate name and read it as a trust signal, even though a TLS certificate only ever proves that whoever requested it controls the domain, not that the domain belongs to who it claims to be. Domain-validated certificates from automated issuers are cheap and fast to get precisely because they were designed to democratize encryption, not to vet identity, and a lookalike domain qualifies for one just as easily as a legitimate site does.

That’s why browser vendors treat the Unicode-vs-punycode display decision as a security control in its own right, not a cosmetic one. Chrome and Firefox each run their own spoof-checking logic on top of the IDN standard: checking for mixed scripts within a label, checking against lists of scripts considered “highly restricted” when combined with Latin, and checking individual characters against confusable tables before deciding whether a decoded label is safe to show. None of these algorithms are static. They get revised after researchers publish new bypasses, which is a pattern that repeats every time a heuristic closes one gap and someone finds the next one.

How defenders catch these domains before they load

The most useful early-warning signal doesn’t come from the browser at all. It comes from Certificate Transparency. Every publicly trusted certificate authority is required to log every certificate it issues to public, append-only CT logs, searchable through tools like crt.sh. Because a punycode phishing domain generally needs a valid TLS certificate to avoid tripping a “not secure” warning, and because automated issuers turn certificates around in minutes, that issuance event becomes a real-time tripwire. Security teams and researchers run continuous queries against CT logs for xn-- domains and for strings that are edit-distance-close to a protected brand name, often catching infrastructure before a phishing campaign has even started sending traffic to it.

Registrars and registries add another layer. Some top-level domain registries, including Verisign for .com, apply their own IDN restriction rules at registration time, rejecting labels that mix scripts in ways their policy disallows. Brand-protection services run their own scanners across newly registered domains, WHOIS and passive DNS changes, and screenshot comparisons against known logos and layouts, feeding takedown requests and UDRP complaints once a match is confirmed.

Email security is the third layer, and arguably the most consequential one, because a lookalike domain that never gets clicked is harmless. Gateways decode the punycode in every URL in inbound mail, compare it against confusable tables and a list of protected brand strings, and flag or rewrite links before a user ever sees them rendered as trustworthy text.

The cat and mouse never really ends

Every one of these defenses is a heuristic, and every heuristic has an edge case. Mixed-script detection missed single-script Cyrillic domains until researchers demonstrated it. Confusables tables get extended as new scripts and new fonts introduce new ambiguous pairs. CT log monitoring only works because certificate issuance is mandatory and public, which is itself a relatively recent hardening of the CA ecosystem, not something that was always true. None of this makes the current defenses useless. It means they shift the cost and timing of an attack rather than eliminating it outright, forcing anyone building this kind of infrastructure to work faster, narrower, and more disposably than they otherwise would, which is its own kind of friction.

Punycode itself isn’t the vulnerability. It’s the mechanism that lets a business in Munich, Moscow, or Shanghai register a domain that reads naturally to its own customers, and that’s a legitimate and necessary piece of internet infrastructure. The abuse is a side effect of two systems, human vision and character encoding, that were never designed to agree with each other perfectly. Watching where they disagree is basically a full time job for a lot of people in this industry.

This is the kind of machinery The Hidden Internet spends its time taking apart, the systems platforms build to trust things and the systems other people build to make those trust signals lie. If that’s the layer of the internet you find yourself curious about, there’s more of it waiting on the home page.

Get new guides and videos first — join the Telegram channel.

watch
The Hidden Internet on YouTube

Every field note starts as a short documentary. Watch the systems in this piece explained on screen.

subscribe →
read on
More field notes

The rest of the series on how the modern internet detects, tracks, and sorts the traffic that reaches it.

browse the archive →