"Check the address bar" is the one piece of security advice everybody has heard. It assumes the name there can be read correctly, which held while domain names could only contain English letters, digits, and a hyphen. Since 2003 they can use almost any writing system, so a Berlin bookshop can be
Chromium (the engine behind Chrome, Edge, and other browsers), which this post examines most closely, applies a display check. If a name looks built to deceive, the address bar shows its encoded Punycode form, such as xn--80ak6aa92e.com, instead. Mail clients make their own choice about how to draw a sender's address, and registries decide separately which characters a name may contain.
This research investigates whether it is still possible to register a domain that looks like a well-known one and have Chromium-based browsers render it close to the real thing. The screenshot below shows Chrome 154 displaying
In April 2017, Xudong Zheng registered .com is Cyrillic, and Chrome, Firefox, and Opera all drew it as something almost indistinguishable from all look like Latin ones. If a label does not pass this check, it is shown in its raw xn-- Punycode encoding instead.
Chromium has shown that name as Punycode ever since. With the 2017 fix long settled, this research takes a fresh look at how Chrome handles internationalized domain names (IDNs) and finds two edge cases that still let a convincing lookalike through. The first is in the whole-script confusable check. Cyrillic , a letter used in Kazakh, Mongolian, and Tatar, is not on Chromium's lookalike list, so
When Chromium is about to show xn--80a6aa68c8d.com) and the U-label (Unicode Technical Standard #39 (UTS #39), which specifies which scripts may be mixed, which characters count as confusable, and how to reduce a string to a comparison "skeleton". Chromium runs the first part of the check through International Components for Unicode (ICU), configured with a narrowed set of allowed characters, and then applies rules of its own.
The decision has two stages, and a name has to pass both to show as Unicode. Stage 1 checks each xn-- label on its own through SafeToDisplayAsUnicode(), with the top-level domain (TLD) as context. Stage 2 checks the whole hostname against a list of popular domains.
Stage 1 runs seven checks on each label in a fixed order, and the first one that fails sends the name to Punycode. Only a hostname whose labels all pass reaches stage 2. The walkthrough below takes each check in turn with
The whole-script confusable (WSC) rule is all-or-nothing, so a single Cyrillic character that is not on the lookalike list keeps the whole label out of it. This post calls that character a "breaker". A useful WSC breaker has to satisfy three conditions at once.
It sits in Chromium's allowed Unicode set, so it clears check #1.
It is missing from the Cyrillic lookalike list, so check #6 does not fire.
It still looks enough like a Latin letter that a reader can mistake it for the letter it replaces.
Under ICU 78 and the 29-character list, 64 lowercase Cyrillic characters meet conditions 1 and 2. The table lists the breakers this research identified. The first three meet conditions 1 and 2 today. The last two met condition 1 only before Chrome 148.
Unicode 17.0 moved and from Recommended to Uncommon_Use, and ICU's recommended set follows that table. Chrome 148, released in May 2026, moved to ICU 78.2, which carries Unicode 17, so both characters now fail check #1. Chrome 147 and earlier accept all five.
This is the mechanism behind the name in the introduction. Every character in
Two more conditions decide whether a breaker is useful. The whole label has to be written in Cyrillic, and the name also has to pass stage 2, covered in the next section. The first condition rules out many words. , , , , , , and have no Cyrillic substitute in Chromium's allowed set, and Chrome 148 also removed the substitutes for and . Every letter in
Stage 2 runs only when every label passes stage 1, and it looks at the whole hostname rather than one label. Chromium reduces the hostname to one or more comparison strings, called skeletons, and compares them against a bundled list of popular domains. A match for a different site sends the entire hostname back to Punycode, even though every label passed stage 1. The skeletons are built in four steps.
Strip diacritics. The label is decomposed into base characters and combining marks (Unicode Normalization Form D), the marks are removed, and the result is recomposed.
Generate variants for ambiguous characters. could be an or an , so Chromium generates a variant for each reading.
Map confusables to ASCII. Chromium's own additions to the Unicode list convert lookalikes such as to , to , and to .
ICU skeleton computation. A final pass applies the UTS #39 confusable mappings to each variant and produces the comparison strings. Skeletons are built for comparison, not for reading. UTS #39 maps to rn because the two look alike, so .corn endings still match.
Each resulting skeleton is looked up against Chromium's bundled domain list of 8,462 names, 836 of them in a higher-priority top bucket. At build time, that list is turned into a skeleton table, which is what the runtime check searches. If a generated skeleton matches an entry for a different site, Punycode is displayed for the entire hostname.
Whether stage 2 catches a lookalike depends on what happens to the substitute character when the skeleton is built. Some substitutes reduce to a plain Latin letter, so the name matches its target. Others keep a combining mark, so it does not. That difference separates
Accents are the simple case. The in
A hook or a stroke, on the other hand, behaves differently. is stored as a single character rather than a base character plus a separate mark, so diacritic stripping has nothing to remove. The confusable mapping that runs afterward rewrites it as followed by a combining mark , and because stripping has already happened, the mark stays in the skeleton.
This settles the second breaker condition. Most names are not on the bundled list, so any breaker passes stage 2 for them.
Latin lookalikes get through the same way. Chromium keeps no whole-script list for Latin, because one would also flag ordinary names such as
A Cyrillic lookalike label has to replace every letter, while a Latin one can change just one.
Unicode display is not the last check. When a page loads, a separate lookalike check (LookalikeUrlNavigationThrottle in Chromium) can block the page or warn about it even when the address bar shows Unicode. It can show an interstitial, a full-page warning that asks whether the visitor meant the real site, or a "Safety Tip" bubble next to the address bar that does not block the page.
This check builds the same skeletons as the display check and compares them against two lists.
Sites the visitor uses regularly. Chromium scores the frequency of visits to each domain, and any domain visited at medium frequency or above counts. An exact skeleton match against one of these sites shows the interstitial.
The bundled list of 8,462 domains. An exact match against one of the 836 top-bucket domains shows an interstitial; against any other domain on the list, a Safety Tip.
When no skeleton produced an exact match, Chromium looks for a near match. That is, a skeleton that differs from a known domain's skeleton by one edit (one character added, removed, or replaced), or by one swap of two neighboring characters. Chromium skips this step for targets shorter than five characters before the TLD. As a result, lookalikes of
The visitor's history therefore decides the result. A new visitor has no visited sites to compare with, only the bundled list, and a match there would already have produced Punycode. So even
Names like аррӏө.com can be registered in .com, so the next question is how many already have been. The .com zone file, obtained through ICANN's Centralized Zone Data Service in October 2026, held 167,226,216 delegated names, 733,509 of them in xn-- form. For each IDN, its non-ASCII characters were replaced with the ASCII characters they resemble, and the result was kept as a pair when that ASCII name was also delegated in .com. That left 161,894 pairs, covering 133,953 distinct ASCII names. Each pair is a potential imitation, not a confirmed typosquat. It only shows that one registered name looks like another.
Of those pairs, 102,592 were exact matches. For each ASCII name, up to 500 lookalike spellings were generated, keeping only spellings that passed Chromium's stage 1 checks. A pair is an exact match when the IDN is one of those spellings and Chromium displays it in Unicode. All but 42 were Latin. Of the rest, 20 were Greek, such as rn, or it was a generated spelling that Chromium displays as Punycode (1,224 of them). Chromium displays 12,780 of these 59,302 as Punycode and the other 46,522 in Unicode.
A lookalike name is not necessarily malicious. Some are defensive registrations, multilingual sites, or unrelated businesses.
Email has the same problem, but there, the mail client decides how to show the sender's domain, not the browser. Chromium's checks only run on the hostname in the address bar. If a webmail service decodes the A-label before sending the page, the browser receives plain Unicode text and checks nothing.
The table shows how each client displayed the sender domains tested. The Chromium column comes from Chromium's display checks run offline, and the Gmail and Outlook Web columns come from captures of test mailboxes.
In testing, Gmail and Outlook Web took opposite approaches. Of 20 internationalized senders, Gmail showed all 20 in Unicode and Outlook Web showed all 20 as A-labels. Two ASCII senders served as controls. Gmail kept the From line in Unicode and showed the Punycode form only in the separate mailed-by: field, which is not the address a reader checks. Outlook Web printed A-labels even for ordinary names such as [email protected] and [email protected]. Neither client checked for lookalikes. Gmail decoded everything, and Outlook Web decoded nothing.
Each test message carried the sender domain as an A-label in its From header, because mail headers traditionally use ASCII. The messages were imported through each provider's API into a researcher-owned mailbox. Both mail clients were kept at their default settings. The recorded result is the address the opened message showed. Spam filtering, sender reputation, and link scanning are separate systems and were not measured.
Chromium's IDN checks are among the strictest in any browser, and they still trade some security for usability. Gmail and Outlook Web make different trade-offs again, and browser updates close gaps one character at a time, as Chrome 148 did for and . The right defense depends on what an organization controls and how often it deals with IDNs, but the following steps apply to most.
Register the lookalike spellings of protected domains that survive a skeleton comparison, such as those built with , , or . Accented spellings of names on Chrome's list are already caught.
Register the hooked and stroked spellings of any brand with four characters or fewer directly, because Chrome gives those names no near-match protection.
Monitor new xn-- registrations within two edits of each protected domain.
Use the mail gateway's existing controls. Gmail shows every IDN sender in Unicode, and SPF, DKIM, and DMARC all pass for a lookalike the attacker owns. Turn on the gateway's lookalike or impersonation protection for the organization's own domains, add a rule that tags inbound mail from xn-- sender domains, and keep external-sender banners on.
Use phishing-resistant MFA (FIDO2/passkeys). A passkey registered on xn--80a6aa68c8d.com, whatever the address bar shows.
Treat xn-- names as a signal in DNS and proxy logs. Most organizations rarely resolve IDN domains or receive mail from them, so log, banner, or block them outside an allowlist. This works on the encoded name, which no display choice can hide.
Domain protection
Detect adversary infrastructure while it is being staged.
Have I Been Squatted helps security teams detect lookalike domains, certificate and DNS changes, and staging infrastructure, investigate the evidence, and coordinate takedowns.