Invisible text & homoglyph detector
Find zero-width characters, hidden Unicode tag text, bidi overrides and lookalike letters in a prompt or document, decode them, and clean them in one click.
What it does
Paste a prompt, a document, a web page's text or code. The detector shows what the text really contains: every invisible character is drawn as a chip with its code point, such as U+200B ZWSP, and every letter that only looks Latin is marked with its script and the letter it imitates. Hidden text written in Unicode tag characters is decoded and shown. Clean the text removes what was found and replaces each lookalike with the Latin letter.
The text stays in your browser. It is never sent anywhere, and never put in the address or a share link: a share link holds only which kinds of character are looked for.
Why it matters
A model reads every character, including the ones a person cannot see. That is how an instruction is hidden in a prompt, a document or a web page a model is asked to read:
- Tag characters (U+E0000 to U+E007F) mirror ASCII, and no font draws them. A sentence written in them is invisible on screen and readable by a model.
- Zero-width characters split a word so a filter misses it, or carry bits between visible letters.
- Bidirectional controls change the order text is displayed in without changing the order it is read in. In code, this is the "Trojan Source" technique.
- Lookalike letters — a Cyrillic
аinpаypal, a full-widthp, a mathematical bold𝐢— make a word read one way to a person and another to a program.
What it looks for
- Zero-width and invisible characters: zero-width space, joiner and non-joiner, word joiner, the byte-order mark, the soft hyphen, the invisible mathematical operators, the Mongolian vowel separator, Hangul fillers, and a few other characters Unicode defines to draw nothing.
- Tag characters, U+E0000 to U+E007F, with the text they spell.
- Bidirectional controls: the embeddings, overrides and isolates (U+202A to U+202E, U+2066 to U+2069) and the left-to-right, right-to-left and Arabic letter marks.
- Variation selectors (U+FE00 to U+FE0F and U+E0100 to U+E01EF).
- Unusual spaces: the no-break space, the fixed-width spaces from U+2000 to U+200A, the ideographic space, and the line and paragraph separators.
- Control characters, other than tab, line feed and carriage return.
- Lookalike letters, from Unicode's confusables table (below).
Every character is named by its Unicode name. The short forms, such as ZWSP or RLO, are Unicode's own abbreviations where one exists.
Ordinary uses are reported, not flagged. A zero-width joiner between two emoji (the way a family or a technologist emoji is built), a variation selector after an emoji, the tag characters of the three subdivision flags Unicode recommends (England, Scotland and Wales), a joiner in Persian or Hindi spelling, and a byte-order mark at the very start are counted as ordinary uses. Cleaning keeps them unless you ask otherwise.
A flag that is not a flag is text. Any other run of tag characters after 🏴 — anything but England's, Scotland's or Wales's code — is decoded, shown and reported as suspicious: a made-up "flag" is the simplest way to hide an instruction behind something that looks harmless.
Nothing drawn as nothing goes unreported. Besides the characters above — the Braille pattern blank, the Mongolian free variation selectors and the shorthand format controls among them — any character Unicode marks Default_Ignorable_Code_Point, which a renderer may draw as nothing, is reported too. One this tool has no name for is reported as a default-ignorable character.
When a lookalike counts
Russian is written in Cyrillic, and a Cyrillic а in a Russian word is a letter, not a trick. So a lookalike is reported:
- in a word that also holds Latin letters or digits, such as
pаypal: ordinary text does not mix scripts inside one word; - anywhere, when it is a full-width or mathematical letter or digit, or a letterlike symbol: no language writes its words with those;
- anywhere, when you switch on Lookalikes in words with no Latin letter too.
Accented Latin letters, such as ı in Turkish, are Latin already and are only reported when that switch is on.
The lookalike table
The table is a documented subset of Unicode's confusables data (UTS #39, confusables.txt), version 16.0.0: the 1,485 characters outside ASCII that Unicode says can be mistaken for ASCII letters or digits, out of 6,355 mappings in the file. Lookalikes of punctuation, of letters in other scripts, and of sequences with combining marks are not in it. Full-width and mathematical letters and digits that the table maps to something other than ASCII, such as U, are read by their compatibility form (Unicode normalization NFKC) instead, when that form is ASCII.
unicode.org could not be reached when this tool was built, so the mappings were taken from the table the Rust unicode-security crate (0.1.2) generates from Unicode's 16.0.0 confusables.txt, not from Unicode's file directly. They were checked against Unicode's official 13.0.0 file (as shipped in the PyPI package confusables 1.2.0): all 6,311 of its mappings are identical. The 44 added since 13.0.0 have not been checked against Unicode's own copy.
What it does not know
- Other hidden encodings. A message spelled in the pattern of zero-width characters, or in whitespace, is found character by character, but not decoded: only tag characters have one defined meaning.
- Lookalikes outside the table, and a word spelled entirely in another script that happens to read like an English word, unless you switch on every script.
- Whether a character is malicious. It reports what is there. A no-break space in
10 kgis usually harmless, and it is still reported as an unusual space.
FAQ
Will cleaning break my text? It removes the characters found and replaces lookalikes with Latin letters. In a text that legitimately mixes scripts, look at the cleaned text before you use it. Ordinary uses are kept by default.
Will other tools read invisible characters the same way? Yes: the detection lives in one shared module, and tools that check prompts use it rather than a copy.
Sources
- The character names and ranges are Unicode's: UnicodeData.txt and the abbreviations in NameAliases.txt.
- Tag characters are Unicode's U+E0000 block; their ASCII mapping is by code point.
- The lookalike table is Unicode's confusables data, version 16.0.0, as described above.
Where the numbers come from
This tool works only on what you enter. It uses no external data and runs entirely in your browser.
