CWR

The invisible character reference

Every block the scanner looks for, why it exists in Unicode at all, and the circumstances under which finding one actually means something.

Last reviewed

Text can carry characters that render as nothing, or as something other than what they are. Most of the time this is harmless residue from a PDF or a word processor. Occasionally it is deliberate, and in a few specific cases it is an attack.

Paste anything into the scanner to see which of these are present. It runs locally; the text does not leave your browser.

The blocks

Unicode tag characters

U+E0000 – U+E007Fhigh concern

Deprecated code points in the U+E0000 block that mirror ASCII. They render as nothing at all, which makes them the usual vehicle for smuggling instructions into text that a person will paste into an AI system.

Bidirectional controls

U+200E, U+200F, U+202A – U+202E, U+2066 – U+2069high concern

Characters that reorder how text is displayed. In source code this is the Trojan Source attack: what a reviewer reads and what the compiler reads differ.

Often legitimate: Genuinely needed when mixing Hebrew or Arabic with Latin text.

Control characters

U+0000 – U+001F, U+007F – U+009F (excluding tab, LF, CR)high concern

C0 and C1 control codes other than tab and newline. Almost never intentional in prose, and a common source of corrupted imports.

Zero-width characters

U+200B, U+200C, U+200D, U+2060, U+FEFF, U+180Emedium concern

Characters with no width. A run of them encodes bits, so they can act as a fingerprint identifying who a document was sent to. They also break string comparison and deduplication.

Often legitimate: Zero-width joiners and non-joiners are required in Arabic, Persian and Indic scripts, and in multi-part emoji.

Variation selectors

U+FE00 – U+FE0F, U+E0100 – U+E01EFmedium concern

Modifiers that select an alternate glyph. Because 256 of them exist, an arbitrary byte string can be encoded in a sequence of them and hidden after any visible character.

Often legitimate: U+FE0F is what makes an emoji render in colour rather than as monochrome text.

Mixed-script look-alikes

Cyrillic and Greek blocksmedium concern

Cyrillic or Greek letters inside otherwise-Latin words. Visually identical, different code points. This defeats exact-match search and is the basis of domain spoofing.

Often legitimate: Flagged only inside mixed-script words, so genuine Russian or Greek text is not reported.

Non-standard spaces

U+00A0, U+2000 – U+200A, U+202F, U+205F, U+3000low concern

Non-breaking, narrow and thin spaces. Mostly a typography artefact rather than a signal, but they break splitting on \s, CSV parsing and database keys.

Often legitimate: Standard in French typography and in typeset numbers.

Soft hyphens

U+00ADlow concern

Invisible unless a word wraps at that point. Frequently left behind by copying from a PDF or a print layout.

The two that are genuinely attacks

Prompt injection via tag characters

Unicode tag characters mirror the ASCII range and render as absolutely nothing in every normal context. That makes them an ideal carrier for text meant for a machine but not for a person. Instructions hidden this way inside a document, an email or a web page are invisible to the human who pastes it and fully legible to a language model that receives it.

This is why the scanner decodes them rather than merely counting them. If a payload is present you should be able to read what it says.

Trojan Source

Bidirectional override characters reorder how text is displayed without changing its underlying sequence. In source code the consequence is that a reviewer and a compiler can read the same file differently — a line that appears to be a comment executes, or a conditional that reads as one thing evaluates as another. Most compilers and code hosts now warn about this; not all editors do.

The mundane reasons this matters more often

Attacks are the interesting case, not the common one. The everyday cost of invisible characters is that two strings which look identical are not equal:

  • A CSV import silently produces duplicate records
  • A lookup key never matches and a join returns nothing
  • Search finds no results for a term that is plainly on the page
  • A diff shows a line as changed when nothing visible about it changed, and a review stalls
  • Splitting on whitespace fails because a non-breaking space is not matched by \s in some regex flavours

Copying out of a PDF, a Word document, a rendered web page or a chat interface is enough to pick these up. No malice required.

What this has to do with AI watermarks

Very little, which is the point worth making since it is the reason most people arrive here.

Claude’s text watermark is a statistical bias in word selection. It is not built out of zero-width characters, tag characters or homoglyphs, and stripping every character on this page leaves it exactly as it was. Tools marketed as watermark removers are performing this cleanup and describing it as something it is not.

Clean text because invisible characters break your data. That reason is real and this scanner serves it. The other reason does not work, and the mechanism page explains precisely why.