Find Invisible Characters
Text looks right but fails validation? Find invisible characters, misleading letters and differences in how systems count its length.
Find zero width, look-alike, direction and control characters in text, compare its length in characters, UTF-16 units and UTF-8 bytes, and clean it locally. Jump to: Break it.
Example A username that looks like "admin" and fails to log in. Replace it in the box on the left.
1 hidden or misleading character found: ZERO WIDTH SPACE, U+200B.
Takes no space on screen but is a real character: it breaks equality, search, validation and length checks.
Your text stays in your browser. It is inspected here and never uploaded, even when you open a file.
Nothing is sent or stored. No server request is made for any input.
What was found
Check U+200B ZERO WIDTH SPACE
Takes no space on screen but is a real character: it breaks equality, search, validation and length checks. At line 1, column 3.
Your text with hidden characters shown
ad⟦U+200B⟧min
Each ⟦U+XXXX⟧ tag stands for one character you could not see.
Clean text
Result: 5 characters, 5 bytes.
Length, by every count
| Characters | 6 | Unicode code points. What Python len() and most database CHAR limits count |
|---|---|---|
| UTF-16 units | 6 | JavaScript, Java and C# string length. An emoji counts as 2 |
| UTF-8 bytes | 8 | Bytes on the wire and in a VARCHAR(n) byte limit, a file name or an HTTP header |
| Visible characters | 6 | What a person counts: an accent or a whole emoji family counts once |
| Lines | 1 | 0 CRLF, 0 LF, 0 CR |
Unicode forms
| NFCcomposed | 6 characters, same as the input | The form most systems store and expect |
|---|---|---|
| NFDdecomposed | 6 characters, same as the input | Letters split from their accents. macOS file names use it |
| NFKCcompatibility composed | 6 characters, same as the input | Also turns fullwidth letters, ligatures and superscripts into plain ones |
| NFKDcompatibility decomposed | 6 characters, same as the input | The same, with accents split off |
How it works
Your text is read one Unicode code point at a time in your browser. Each code point is checked against the characters that cannot be seen or are easily mistaken: zero width characters, direction marks and overrides, blank fillers that are not whitespace, tag characters, control characters, look-alike spaces, and letters from another script sitting inside a Latin word. The result lists every kind found with its code point, its name and where it is by line and column, then counts the length four ways (characters, UTF-16 units, UTF-8 bytes and visible characters) and shows the text in each Unicode normalization form. The clean-up step only removes or replaces what you tick, keeps the joiners that emoji need, and tells you what it changed.
The full method, every rule and worked examples are on docs.tamperbox.dev.
Limits and interpretation
A finding is a character that is in the text, not proof of an attack or a bug: a zero width non-joiner is correct in Persian, and a joiner is correct inside an emoji sequence, so those are reported as notes or left alone. Look-alike letters are only found inside a word that also contains Latin letters, or in a word made only of a small set of well-known look-alikes; a full confusables check is not run. Text from files is read as UTF-8. Characters already replaced by U+FFFD were lost before they reached this page and cannot be repaired here. The line count treats CRLF, LF and CR each as one line break. Input is limited to 200,000 characters. Nothing is stored.
Frequently asked questions
Why does my text fail a check when it looks identical?
Two strings that look the same can differ in characters you cannot see: a zero width space inside a word, a no-break space instead of a space, a Cyrillic letter in place of a Latin one, or an accent stored as a separate character. Each makes equality, search and validation behave differently.
Why are there three different lengths?
Systems count different things. Python counts code points, JavaScript and Java count UTF-16 units, so an emoji counts as 2, and databases and HTTP headers often limit bytes, where an emoji is 4. A person counts visible characters, where a family emoji built from seven code points counts as 1.
Should I always remove zero width and direction characters?
Not always. They are correct in some scripts and in emoji, and direction controls are needed for some right-to-left text. Remove them where the value is an identifier, a file name, a URL, an email address or source code, and keep them in prose in the languages that need them.
References
Unicode Standard Annex #15: Unicode Normalization Forms · Unicode Standard Annex #9: Unicode Bidirectional Algorithm · Unicode Technical Standard #39: Unicode Security Mechanisms · Unicode Standard Annex #29: Unicode Text Segmentation · CVE-2021-42574: Trojan Source, bidirectional text in source code.
Are you an AI agent? You are in the right place.
This page and every tool are available as plain text with their methods and limits, and the same checks run over MCP.