Skip to main content
AI Detection

Hidden Characters in AI Text: What Claude, ChatGPT and Gemini Actually Embed

Zero-width spaces, narrow no-break spaces and look-alike letters turn up in copied AI text every day. Here is where they come from, which ones are a watermark, and how to check any text yourself.

August 19, 2026 8 min readBy Tim GeithnerReviewed 8/19/2026
Hidden Characters in AI Text: What Claude, ChatGPT and Gemini Actually Embed

Turn on "show invisible characters" in your editor, paste in a few paragraphs you copied out of a chat window, and there is a decent chance something lights up that you did not type. A dot between two words where a space should be. A marker sitting flush against a comma. A letter that looks exactly like the one next to it but sorts differently.

The internet has a name for this: the AI watermark. Search for "remove Claude watermark" or "ChatGPT invisible characters" and you will find forum threads, browser extensions and a small industry of tools promising to strip it out.

The reality is more interesting than the conspiracy, and considerably more useful to know. Some of what you are seeing is real, some of it is ordinary typography being misread, and the one system that genuinely is a text watermark works in a way that no character-stripping tool can touch.

Two different things get called an AI watermark#

Almost every confused conversation about this topic comes from collapsing two separate mechanisms into one phrase.

Character-level markers are extra code points sitting in the string. Zero-width characters, unusual spaces, direction controls, letters swapped for look-alikes from another alphabet. They are objectively present — you can count them, and you can delete them without changing a single word of the actual writing.

Token-level watermarks add nothing at all. A system like SynthID-Text nudges which word the model samples at each step, so that across a long enough passage the choices form a statistical pattern a verifier can recognise. There is no marker character to find, because the marker is the text.

What is actually in there#

Here is the full catalogue of what shows up in pasted model output, roughly in order of how often you will meet it.

Non-breaking and narrow spaces. U+00A0 (non-breaking space) and U+202F (narrow no-break space) are by far the most common. They look like a space, they are not the space key, and that difference is why a Ctrl+F search returns nothing, a spreadsheet lookup fails, or a generated slug comes out with a character your CMS refuses.

The zero-width family. U+200B (zero-width space), U+200C and U+200D (non-joiner and joiner), U+2060 (word joiner), U+FEFF (byte-order mark), U+00AD (soft hyphen). No width, no glyph, fully preserved through copy-paste. Two of them have legitimate jobs — the joiner holds emoji sequences together, and the non-joiner is real spelling in Persian and several Indic scripts — which is exactly why blunt stripping tools break emoji and Farsi.

Direction controls. U+200E and U+200F (the left-to-right and right-to-left marks), plus the embedding and override range U+202A–U+202E. Invisible, and capable of making a string display in a different order from the one it is stored in. That property has a long history in filename spoofing.

Tag characters. The block U+E0000–U+E007F mirrors ASCII in code points that render as nothing. A run of them can encode a complete readable message inside a sentence that looks entirely ordinary. This is the one category worth treating as genuinely adversarial rather than accidental.

Look-alike letters. A Cyrillic а inside an otherwise Latin word, or a Greek ο standing in for o. Identical to a reader, different to every machine — which is how one word in a paragraph can silently fail search, spellcheck and copy-paste with no visible cause.

Typography. Em dashes, curly quotes, the single-character ellipsis. These are not and not a watermark. They are the punctuation set chat models reach for, and the first thing an attentive human reader notices. We wrote about that pattern separately in the words and phrases that give away AI writing.

Where they come from#

The unglamorous answer: mostly from the path between the model and your clipboard, not from the model deciding to mark you.

Chat interfaces render responses as rich text. Markdown gets converted to HTML, HTML gets styled, and along the way non-breaking spaces are inserted to stop awkward line breaks — before a unit, after a number, around punctuation. When you select and copy, the clipboard carries a text rendering of that HTML, spacing characters included.

Models also produce typographic punctuation because their training data is full of it. Published prose uses em dashes and curly quotes; a model trained on published prose writes em dashes and curly quotes. Nothing is being signalled.

That leaves a smaller residue of genuinely odd cases — zero-width characters mid-sentence, tag-character runs, look-alike letters — which usually arrive from a document, a plugin, a scraped source or a previous tool in the chain rather than from the model at all.

Model by model#

Sticking strictly to what each vendor has published, because the rest is guesswork dressed up as fact.

Claude (Anthropic). As of August 2026, no covert text watermark has been announced. What gets called "the Claude watermark" in forum threads is the typography and spacing set above: em dashes, curly quotes, non-breaking and narrow no-break spaces, plus markdown residue from the chat surface. Real characters, worth cleaning, not an identifying mark.

ChatGPT (OpenAI). OpenAI has publicly discussed text-watermarking research; nothing of the kind has been announced as shipped. Separately and reproducibly, users find narrow no-break spaces and other non-ASCII spacing in copied output. Those two facts get merged into "ChatGPT watermarks its text," which does not follow. Treat the spacing as a formatting artefact unless the vendor says otherwise.

Gemini (Google DeepMind). This is the one that genuinely is a watermark. SynthID-Text is documented, an implementation is public, and it works at the token level — the signal is in which words were sampled, spread across the whole passage. Google's own analysis notes that heavy editing and paraphrasing weaken detection. Stripping characters does nothing to it, because there is nothing added to strip.

Why it matters even if you do not care about detection#

Most people arrive at this topic worried about an AI detector. The practical reasons to clean pasted text are far more boring, and far more likely to actually cost you something.

  • Search stops working. A narrow no-break space is not the space key, so Ctrl+F, a database LIKE, a spreadsheet lookup and a deduplication pass all miss the row you are looking at.
  • Imports and slugs break. Zero-width characters travel into CSV columns, JSON strings, YAML keys, URL slugs and commit messages. They are behind a surprising share of "but it looks identical" bugs.
  • Parsers notice. Applicant-tracking systems, plagiarism checkers and editorial tooling normalise text before comparing it. Unusual characters do not help you pass anything, and to a human reviewer they read as tampering.
  • Invisible text can carry instructions. A tag-character run encodes readable ASCII that nobody sees. Pasting unchecked text into an agent, a ticket or a prompt is how a instruction gets a second life.

How to check any text yourself#

You do not need to take anyone's word for what is in a document — including ours. Three ways, all under a minute.

Paste it into a scanner. Our hidden character cleaner lists every flagged code point with its count and shows you where each one sits. It runs entirely in the browser tab, so nothing is uploaded.

Search for the ranges in your editor. VS Code, Sublime and most editors accept a regex search:

[\u200B-\u200F\u202A-\u202E\u2060\uFEFF\u00AD\u00A0\u202F\u2007-\u200A]

That covers the zero-width family, the direction controls, the byte-order mark, the soft hyphen and the common non-breaking and typographic spaces.

Compare lengths in a console. Paste the text into a variable and normalise it:

const clean = text.replace(/[\u200B-\u200F\u202A-\u202E\u2060\uFEFF\u00AD\u00A0\u202F\u2007-\u200A]/g, "");
console.log(text.length - clean.length, "flagged characters");

Any number above zero means something is riding along that you did not type.

What cleaning does not do#

It does not change an AI detector's verdict. GPTZero, Originality, Turnitin, Copyleaks and their peers score how predictable your word choices are (perplexity) and how much your sentence rhythm varies (burstiness). Neither number has anything to read in a zero-width character. If a tool tells you that removing zero-width spaces will drop a detector score, ask it which measured property is supposed to change — there isn't one.

Moving those scores means changing the writing — varying sentence length deliberately, cutting the high-probability filler, using words a model would rank lower. We covered the manual version of that in how to humanize AI text, and the automated version is what the text humanizer does. Neither can promise a specific verdict, because detectors are retrained constantly and routinely disagree with each other.

Should you add invisible characters to beat a detector?#

You will find advice suggesting the opposite trick: sprinkle zero-width spaces or swap in Cyrillic look-alikes to confuse a detector. It is a bad idea, for three separate reasons.

It targets nothing a detector is known to measure, so the upside is speculative at best. It is trivially visible to anyone who runs a scan like the one above, and unlike a stylistic edit it cannot be explained away as ordinary writing. And it actively breaks the text for search, accessibility and screen readers.

Our own text humanizer keeps that option switched off by default for exactly this reason. The durable version of this work is making the prose read like a person wrote it, not decorating it with characters nobody can see.

The short version#

  • Two unrelated things are called an AI watermark. Character-level markers you can delete; token-level watermarks you cannot.
  • Most of what you find in pasted text is spacing and typography from the chat interface, not an identifying mark.
  • SynthID-Text is a real token-level watermark on Gemini output. No cleaner touches it.
  • Cleaning characters fixes search, imports, parsers and pasted-in instructions. It does not move a detector score.
  • Cleaning characters does not touch your own disclosure duties. Art. 50(4) of the EU AI Act and the AI-content labels on TikTok, Instagram and YouTube attach to the person publishing, not to the file. Use the label where it applies.
  • Check before you assume. It takes a minute, and the answer for your text is the only one that matters.

Review method, sources and limits

Reviewed by
Tim Geithner · Founder and technical reviewer
Last reviewed
August 19, 2026

We compare current primary documentation with the implemented browser data flow and, where stated in the article, repeatable hands-on observations. A detector score is not proof of authorship or provenance. No controlled benchmark is claimed unless the article names its sample, tested version, date and method; third-party products and policies can change.

Primary references

SynthGuard.net — privacy-first tools

Humanize AI media locally and choose a clearly disclosed text mode.

Images, video and detector scans stay on your device. Light-mode text is local; deeper text modes use the protected inference route. No detector outcome is guaranteed.

All third-party names, logos and trademarks (e.g. Hive, Optic, Sensity, Sightengine, Illuminarty, GPTZero, Instagram, TikTok, OnlyFans, Fanvue, SynthID, C2PA) are the property of their respective owners. SynthGuard is an independent service and is not affiliated with, endorsed by, sponsored by, or partnered with any of these companies or platforms. Detector and platform names are used solely for descriptive comparison under § 6 UWG / Art. 4 Directive 2006/114/EC.

Frequently asked questions

Glossary terms in this article

Keep reading