Invisible Character Detector

Find and remove invisible Unicode characters — zero-width spaces, bidi overrides, soft hyphens, BOMs — including the ones behind Trojan Source attacks.

Paste or type some text to scan it for invisible characters.

What are hidden characters?

Some Unicode characters take up no visible space yet sit right inside your text: zero-width spaces (U+200B), the zero-width joiner and non-joiner, the byte order mark (BOM), soft hyphens, and bidirectional controls that can silently reorder how text is displayed. They get pasted in when you copy from a website, PDF, chat app or word processor, and they can break search, string comparison, form validation, code and URLs. This tool scans your text, flags every invisible character with its position, name and code point, and gives you a cleaned copy with them stripped out. The table’s last column, “Around it”, shows the visible text either side of each find with the hidden character tagged in its place, so a row can be found in your own text by eye. “Where they are” draws your own text with each hidden character shown as a tag in its place — ZWSP, RLO, BOM or its code point — and “Replace with a space instead of deleting” keeps the word break when a zero-width space stood for a space, as it does in text copied out of a PDF. Under the count, one line names each family found — Zero-width, Direction (bidi), Tag characters, Variation selectors, Other formatting — with how many of each, and a checkbox per family under Remove from the cleaned text keeps one in the cleaned copy, such as the joiners of an emoji, while the table still lists it. Tag characters are named one by one, and the page spells out the hidden text a run of them carries. No-break spaces, line and paragraph separators and control codes (other than tab, line feed and return) are listed separately: they look like ordinary spacing, or draw nothing, but a spreadsheet or a search treats them as different characters, and they stay in the cleaned text unless you tick Mend these too.

Why it matters

A single zero-width space can make two identical-looking strings compare as different, break a password field, or corrupt a CSV export. Bidirectional override characters are the basis of Trojan Source attacks, where source code looks harmless but compiles to something else. Because everything runs locally in your browser, you can safely inspect sensitive or untrusted text without uploading it anywhere.

Frequently asked questions

What counts as a hidden character?

Any character in the Unicode Format (Cf) category: zero-width space, joiner and non-joiner, the BOM, soft hyphen, and the left-to-right and right-to-left embedding, override and isolate controls, plus the bidi marks. Outside that category it also flags a variation selector that selects nothing — with no character before it, or stacked after another one, which is how data is smuggled inside an emoji — while one that changes the character before it, as in ❤️, is left alone; and the Hangul fillers U+3164 and U+FFA0, which draw nothing. Ordinary spaces, tabs and line breaks are left untouched; no-break spaces, line and paragraph separators and other control codes are listed apart from the rest, and changed only if you tick Mend these too.

Does cleaning change my visible text?

Not the characters: only invisible ones are removed (or, with Replace with a space instead of deleting ticked, one between two words becomes a space), and the joiners that hold an emoji together (👩‍💻, the rainbow flag, a subdivision flag) are kept so it stays whole. But removing a zero-width joiner or non-joiner can change how Persian, Arabic or Indic letters connect, and removing bidirectional controls changes the order mixed-direction text is shown in — which is exactly why you would remove a smuggled one.

Can I see where the hidden characters are in my text?

Yes. Where they are draws your own text with each hidden character replaced by a tag in its place — ZWSP, RLO, BOM, VS16, or its code point — and its name and code point in the tag’s tooltip. The tags are only for checking; copy the cleaned text below, not this.

Does it catch no-break spaces and control codes, or let me keep some hidden characters?

It lists them, and leaves the choice to you. No-break spaces, line and paragraph separators, NEL and control codes other than tab, line feed and return are named by position in a list of their own, and text holding only these is not called clean. They stay in the cleaned text unless you tick Mend these too, which turns no-break spaces into ordinary spaces and separators into line breaks and removes the control codes. Under the count, one line names each family found — Zero-width, Direction (bidi), Tag characters, Variation selectors, Other formatting — with how many of each, and Remove from the cleaned text has a checkbox per family, all ticked, so you can keep one, such as the joiners of an emoji, while the table still lists it. Tag characters are named one by one, and the page reads out what a run of them spells.

Does the table show the text around each hidden character?

Yes. The table’s last column, “Around it”, shows a few visible characters either side of each find, with the character itself tagged in its place (ZWSP, RLO and so on), so the row can be matched to your own text by eye. Other hidden characters in that window are left out, and a line break is shown as one space so every row stays on one line.