What is a homoglyph attack?
A homoglyph is a character that looks the same as, or nearly the same as, a different character. A homoglyph attack exploits that overlap by substituting one or more letters in a string with their lookalikes from another script — most often swapping a Latin letter for its Cyrillic or Greek twin. Cyrillic а (U+0430) and Latin a (U+0061) render as the same glyph in almost every font, but they are different code points: to a human eye the text is identical, to a computer comparing bytes it is a completely different string.
That gap is what makes homoglyphs dangerous. Anywhere a system relies on an exact string match — comparing a domain name, checking a username against a blocklist, matching an email address, flagging plagiarized text — a single substituted character defeats the check while leaving the text looking untouched to the person reading it. This is a distinct problem from the invisible characters this site normally deals with: those have no glyph at all and can be safely deleted; a homoglyph is a real, visible letter, and deleting or replacing it automatically risks destroying genuine text in another script.
The 2005 PayPal exploit that started it
The attack has a precise starting date. Security researcher Eric Johanson of The Shmoo Group notified browser vendors on January 19, 2005, then publicly disclosed at ShmooCon on February 6, 2005 (covered the same week by security researcher Bruce Schneier) that Firefox 1.0, Safari 1.2.5, and Opera 7.54 rendered the domain xn--pypal-4ve.com — registered with a Cyrillic а standing in for the Latin a in "paypal" — identically to the real paypal.com in the address bar. This was the first practical demonstration that internationalized domain names (IDNs), which let browsers display non-Latin scripts natively instead of raw Punycode, could be weaponized for phishing. ICANN issued a public statement within days, and Mozilla shipped a fix that restricted which top-level domains were allowed to render as Unicode at all — everything else fell back to visible Punycode (the xn-- prefix), which at least exposes the trick to anyone who looks. The underlying bug report is still public on Mozilla's Bugzilla, filed as bug 279099.
The 2017 all-Cyrillic apple.com attack
Mozilla's 2005 fix checked for mixed scripts within one label — Latin letters next to Cyrillic letters in the same word — but it didn't stop a label written entirely in one foreign script. In April 2017, developer Xudong Zheng showed exactly that gap in a post titled "Phishing with Unicode Domains": he registered a domain where every single letter of "apple.com" was replaced by its Cyrillic counterpart. Because the label was single-script — all Cyrillic, no mixing — it passed the 2005-era check and rendered pixel-for-pixel as apple.com in Chrome, Firefox, and Opera. Zheng reported it privately in January 2017; Chrome shipped a fix in version 58 (March 2017) and Firefox followed, both adding a check against Unicode Technical Standard 39's confusable-character tables on top of the mixed-script rule, not just within a single label.
How browsers detect homoglyphs today
Modern homoglyph defense in Chrome and Firefox both trace back to one standard: Unicode Technical Standard 39, "Unicode Security Mechanisms". It defines two checks browsers now run on every domain label before deciding whether to display it in Unicode or fall back to Punycode:
Mixed-script check
A label combining scripts that don't normally appear together — Latin letters mixed with Cyrillic or Greek in the same word — is rejected outright and shown as Punycode. This is what the 2005 fix introduced.
Skeleton / confusable check
Even a single-script label is mapped to a canonical "skeleton" — each character reduced to its representative confusable form — and compared against known domains. A skeleton match to a real domain forces Punycode display. This closed the 2017 all-Cyrillic gap.
The full mapping browsers use lives in Unicode's confusables.txt data file, part of UTS 39, which associates thousands of characters across scripts with the ASCII or common-script character they visually resemble. It's the same reference table security tools, registrars, and plagiarism checkers draw on when they flag look-alike substitutions.
Homoglyphs beyond domains: code, documents, and pasted text
Domains are the best-documented case, but the same substitution works anywhere text is compared for equality. A Cyrillic character in a variable name compiles as a different identifier than its Latin twin, producing a bug that looks correct in every code review. A homoglyph in a submitted document defeats naive plagiarism matching. Copy-pasting from a non-English source can introduce one by accident with no attack intended at all. A few of the common pairs:
| Looks like | Genuine (Latin) | Homoglyph | Script |
|---|---|---|---|
| a | U+0061 | U+0430 | Cyrillic а |
| e | U+0065 | U+0435 | Cyrillic е |
| o | U+006F | U+043E | Cyrillic о |
| p | U+0070 | U+0440 | Cyrillic р |
| O (capital) | U+004F | U+039F | Greek Ο (Omicron) |
This is also what Turnitin's integrity Flags are built to catch in submitted work — the same "replaced characters" check that looks for a Cyrillic а inside otherwise-English text, covered in more detail on the hidden character checker page. For code, JSON, and CSV specifically, see sanitizing copied text for code, JSON, and CSV — homoglyphs sit alongside BiDi override characters as one of the visible-but-deceptive tricks that plain text search won't catch.
Detection, not deletion
Homoglyphs need a fundamentally different fix than the hidden characters this site otherwise covers. A zero-width space has no legitimate reading in most contexts, so removing it is safe by default. A homoglyph is a real letter that might be entirely legitimate — Cyrillic, Greek, and Latin text all coexist on the same page constantly — so the correct response is to surface it for a human to judge, never to silently swap it. That's why CleanPastedText, which strips invisible characters in your browser, does not touch homoglyphs: the safest tools here are inspection tools — a Unicode-aware code editor, a codepoint viewer, or your browser's own address bar, which since 2005 has been quietly doing exactly this check every time you click a link.