HomeBlog › The Invisible Characters Hiding in AI Text

The Invisible Characters Hiding in AI Text

Editorial Team · published 11 August 2026

Quick answer

AI output frequently carries zero-width space, zero-width joiner and non-joiner, soft hyphens, word joiners, non-breaking spaces and byte order marks. They render as nothing, survive copy and paste, and break git diffs, database keys, CSV parsing and search. None of them is a watermark.

What are invisible characters?

Unicode code points that occupy space in the byte stream but render as nothing, or as something indistinguishable from an ordinary space. They survive copy and paste, they are not visible in any normal editor, and most of them have legitimate typographic uses that AI output does not need.

The full list

CharacterCode pointRenders asWhat it breaks
Zero width spaceU+200BnothingString equality, search, database keys
Zero width non-joinerU+200CnothingGit diffs on visually identical lines
Zero width joinerU+200DnothingSame, and stripping it carelessly corrupts emoji
Soft hyphenU+00ADnothing until a line wrapsSurvives proofreading, then appears in print
Word joinerU+2060nothingWord boundary logic in search indexes
Non-breaking spaceU+00A0a spaceCSV parsing, trim(), shell arguments
Byte order markU+FEFFnothingBreaks JSON parsing when it lands at the start of a file
Left-to-right markU+200EnothingUnexpected reordering in mixed-script text

Alongside those, AI text carries visible characters that behave like artefacts: em dash U+2014, en dash U+2013, curly quotes U+201C U+201D U+2018 U+2019, and the ellipsis U+2026. They are not invisible, but they break code strings and shell commands the same way, and the em dash carries a stylistic signal all of its own.

What each one actually costs you

Git. Two lines that look identical but differ by one zero width character are different bytes. You get a diff nobody can explain, a merge conflict with no visible cause, and a blame history that points at the wrong commit.

Databases. A trailing U+200B on a key makes lookups fail silently. The value is there, the query returns nothing, and the two strings look the same in every log you check.

Data pipelines. A non-breaking space passes visual inspection and then breaks the CSV column split, or survives a trim() that was supposed to clean it.

Search. A word joiner inside a term prevents the tokeniser seeing the word, so the document never matches.

Publishing. Soft hyphens are invisible until the line wraps at a different width, which is usually after the piece is published.

How to find them yourself

Do not take any tool’s word for it, including this one. In a browser console:

[...text].filter(c => /[​-‏­⁠ ]/.test(c))
  .map(c => 'U+' + c.codePointAt(0).toString(16).toUpperCase().padStart(4,'0'))

That returns the code points present in a string. On the command line, cat -A or hexdump -C shows the bytes directly. In VS Code, the unicode-highlight setting flags them in the gutter.

If a tool tells you it found something and this returns an empty array, the tool is wrong.

Why these are not the Claude watermark

Because Anthropic’s mark is statistical. It biases which tokens the model picks, using a secret key, and there is no character carrying it. A watermark made of the code points above would show up under hexdump and be removed by one regular expression, which is why nobody would build one that way.

Tools that describe these characters as “the watermark” are describing a real thing and mislabelling it. Delete them because they break your build, not because you think it changes what a detector sees. The full explanation.

Who this is not for

If nothing in your pipeline touches bytes, this probably does not matter to you. Prose that only ever gets read by humans is unaffected by a zero width space, and cleaning it changes nothing you can perceive.

The people who need this are developers, data engineers, anyone maintaining a CMS, and anyone who has spent an hour on a diff that made no sense.

Keep reading