About the Invisible Character Detector
An invisible character is a Unicode codepoint that renders with no visible width and is still present in the text. It occupies a position in the string, it is copied and saved along with everything else, and any software that searches, compares or parses that text sees it. The reader does not. That gap between what is displayed and what is stored is the entire problem, and it is why the fix starts with looking rather than deleting.
Which invisible characters exist, and what does each one break?
Twelve codepoints account for almost every case found in ordinary text. The table names each one, gives its Unicode codepoint, states what it is for, and states the specific failure it causes when it is somewhere it was not intended.
| Character | Codepoint | What it is for | What it breaks |
|---|---|---|---|
| Zero-width space | U+200B | Marks a permitted line-break point inside a word | Search, find and replace, and regular expressions stop matching a word that looks correct |
| Zero-width non-joiner | U+200C | Prevents two characters joining in cursive scripts | Removing it changes how Arabic and Persian words render |
| Zero-width joiner | U+200D | Binds codepoints into one composed glyph | Removing it splits a composed emoji into its parts and breaks joined scripts |
| Byte order mark | U+FEFF | Signals encoding at the start of a file | A CSV or JSON parser reads it as part of the first field and fails |
| No-break space | U+00A0 | Keeps two words on the same line | Text refuses to wrap where it should, and a search for a normal space misses it |
| Narrow no-break space | U+202F | A thinner non-breaking space, used before punctuation in French | Same as above, and it is even harder to spot |
| Soft hyphen | U+00AD | Marks where a word may hyphenate if it must break | Appears as a stray hyphen when the text is re-flowed or converted |
| Word joiner | U+2060 | Prevents a line break without adding space | Invisible interference in string comparison |
| Left-to-right mark | U+200E | Sets text direction | Reordered or mis-aligned text when mixed with right-to-left scripts |
| Right-to-left override | U+202E | Forces the display order of following characters to reverse | Can disguise what a filename or string actually says |
| Hangul filler | U+3164 | A placeholder in Korean text | Used to fake an empty username or message on platforms that reject blanks |
| Braille pattern blank | U+2800 | An empty Braille cell | Renders as a blank that survives whitespace trimming |
Three of those twelve are load-bearing in normal text rather than accidents: the joiner, the non-joiner and the no-break space all do a job somebody intended. That is why a detector is more useful than a blanket remover.
Where do invisible characters come from?
Four routes account for nearly all of them, and knowing which one applies usually decides whether the character should stay.
- Copying out of a chat window or a web page. The rendered page contains characters the layout needed, and they travel with the selection.
- A word processor or CMS inserting them to control spacing and line breaking, which is what no-break spaces and soft hyphens are for.
- Text that has passed through an encoding step, which is where a byte order mark at the start of a file comes from.
- Deliberate insertion, which has both ordinary uses and adversarial ones. The next two sections cover each.
Why would anyone add an invisible character on purpose?
Because a character with no width does things an ordinary space cannot. The four uses below are entirely legitimate and are the reason these codepoints exist at all.
- Sending an apparently empty message or comment on a platform that rejects a blank submission.
- Controlling where a long word or URL breaks across a line, without inserting a visible space.
- Padding a name or username where the platform trims ordinary spaces from the ends.
- Composing emoji, where a zero-width joiner binds several codepoints into a single glyph.
We run the tool at the other end of this, which is worth saying plainly: the blank space generator on this site produces these characters deliberately. That is one of the ways they end up in text somebody else later pastes and cannot account for, and it is the reason this page explains them rather than treating every one as dirt.
Can invisible characters be used to hide something?
Yes, and it is worth understanding the mechanism rather than the folklore. Because a sequence of zero-width characters carries information while displaying nothing, a run of them can encode data inside ordinary-looking text.
Three uses of that are documented. Text can be watermarked before it is shared, so that a leaked copy identifies the recipient. Copied text can be tagged to show where it came from. And instructions can be concealed inside input that a language model will read but a person reviewing the same text will not see, which is the class of problem security researchers call ASCII smuggling.
The defence is the same in every case and it is the reason this page exists: inspect text before you trust it, particularly text you are about to paste into source code or feed to a model. This page shows you what is there. It publishes no encoder and no example payload, because a working one would be a tool for doing the thing rather than for spotting it.
Does ChatGPT hide a watermark in its output?
No hidden watermark has been established in the text output of current models. What is verifiably present is the ordinary character set in the table above, arriving through the routes already named.
The question is asked often enough that several tools now sell themselves on removing one. Removing something whose existence has not been shown is not a capability, and the honest version of the answer is the short one.
Do invisible characters affect AI detectors?
The available sources disagree, and the disagreement is worth stating rather than resolving by assertion.
One side comes from a heavily discussed forum thread on the subject, which reports that zero-width characters are exactly what plagiarism bots and detector scripts key on, and treats stripping them as a necessary step. The other side comes from a tool vendor's own page ranking on the same query, which states that detectors score statistical properties of the writing — sentence-length variance, vocabulary distribution, rhythm — and that character-level edits do not move any of them.
The weight of the evidence is uneven: one is a forum consensus with no published method, the other is a vendor describing its own product. Neither publishes a test. What can be said without picking a side is the practical part: adding or removing these characters is not a detection strategy in either direction, and the good reasons to remove them — broken search, failed parsing, text that will not wrap — have nothing to do with detectors at all.
How do you get rid of them?
Decide first, then strip — because removing the zero-width joiner breaks composed emoji and joined scripts. That constraint is the reason this page shows and does not delete.
Three routes, depending on what the text is. Our space remover strips invisible Unicode along with the whitespace artifacts that usually arrive with it, which covers prose. A code editor can be configured to highlight these characters so they can be deleted in place, which is the right approach for source files. And in code, matching the codepoints directly — U+200B, U+200C, U+200D and U+FEFF — catches the common set in any language with regular expressions.
What does this tool not do?
It does not remove anything. That is deliberate, and the reason is in the section above. The space remover does the removing.
It does not change AI-detection outcomes, in either direction.
It does not read images. Text inside a screenshot has to be copied out as text first.
There is no app to install, on Android or anywhere else. This is a web page that runs in the browser you already have.
It cannot tell you who inserted a character or when. It reports what is in the text, not its history.