# Hidden Character Checker | Find Invisible Characters

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.

Canonical: https://tamperbox.dev/hidden-characters

Docs: https://docs.tamperbox.dev/tools/hidden-characters.md

Updated: 2026-10-26

Reviewed: 2026-10-25

## 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](https://docs.tamperbox.dev/tools/hidden-characters/).

## 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](https://www.unicode.org/reports/tr15/) · [Unicode Standard Annex #9: Unicode Bidirectional Algorithm](https://www.unicode.org/reports/tr9/) · [Unicode Technical Standard #39: Unicode Security Mechanisms](https://www.unicode.org/reports/tr39/) · [Unicode Standard Annex #29: Unicode Text Segmentation](https://www.unicode.org/reports/tr29/) · [CVE-2021-42574: Trojan Source, bidirectional text in source code](https://nvd.nist.gov/vuln/detail/CVE-2021-42574).
