We generated 96 answers from three Claude model tiers, wrote each one straight to disk, and counted every code point. Zero zero-width or bidirectional-format characters appeared in any of them. The most repeated explanation of Claude's watermark (that it hides invisible characters in your text) finds no support in the bytes.
Published 2026-08-12Updated 2026-08-12Research/proposal
What this does and does not settle
Settles: Claude output in this corpus contains no hidden Unicode. A cleaner that strips zero-width characters had nothing to strip.
Does not settle: whether Anthropic's confirmed statistical text watermark is present. No public detector exists for it, so this study cannot see it and neither can any tool claiming to remove it.
Does not settle: that no Claude surface anywhere ever emits such characters. This is one harness, one date, 96 outputs.
Why a count of zero is a finding rather than a failure
A null result is only meaningful if the same path could have carried a positive one. The control arm sends known invisible characters through the identical capture path.
The fourth control character (U+00A0) never appeared: asked for a non-breaking space, the model wrote an ordinary one. That is a small result in its own right, and it points the same way as the corpus.
Every character class we counted
Twenty classes of invisible or non-obvious character, chosen because they are the ones every "AI watermark remover" on the web actually operates on. Nineteen returned zero.
Counts across all 96 outputs (19,364 words, 127,307 code points), 2026-08-12.
Character class
Occurrences
U+200B zero width space
0
U+200C zero width non-joiner
0
U+200D zero width joiner
0
U+2060 word joiner
0
U+FEFF byte-order mark
0
U+00AD soft hyphen
0
U+034F combining grapheme joiner
0
U+180E Mongolian vowel separator
0
U+061C Arabic letter mark
0
U+200E / U+200F directional marks
0
U+202A–202E bidi embedding and override
0
U+2066–2069 bidi isolates
0
U+FE00–FE0F variation selectors
0
U+E0100–E01EF variation selector supplement
0
U+E0000–E007F tag characters
0
U+00A0 no-break space
0
U+202F narrow no-break space
0
U+2000–200A Unicode spaces
0
U+1680 Ogham space mark
0
U+3000 ideographic space
30
The single non-zero row is the interesting one, and it is not a watermark. All 30 ideographic spaces occur inside the Japanese-language outputs, where U+3000 is ordinary typography, the character a Japanese writer uses to indent a line. A naive scanner that flagged "invisible characters found" on that basis would be reporting correct Japanese as evidence of a hidden mark.
Em dashes per 1,000 words, by Claude model
Em dashes (U+2014) per 1,000 words
A second measurement from the same corpus, because the em dash is the other thing people point at when they claim to spot AI text. The rate varies by more than 2× between model tiers of the same provider. That is a problem for anyone treating em-dash density as a detector. It also means a corpus-level em-dash rate says more about which model wrote the text than about whether a model did.
Source:
Original measurement, AI Watermark Lab
Sample:
96 outputs, 19,364 words, 68 em dashes total
Method:
Code-point count of U+2014 across the same corpus, normalised per 1,000 whitespace-delimited words
Date:
2026-08-12
Limitations:
One harness, one date, 8 prompts. Prompt mix strongly affects prose style, so these rates describe this corpus rather than Claude in general.
How it ran
Three model identifiers, claude-opus-5, claude-sonnet-5, and claude-haiku-4-5-20251001 each answered the same eight prompts, four independent times, for 32 outputs per model. The prompts span a short factual answer, long prose, source code, a list, Spanish, Japanese, a markdown table, and dialogue, because a marker might plausibly attach to some output shapes and not others.
The capture path is the part that matters. Each answer was written straight to a file by the generating process, with no clipboard, no terminal rendering, and no editor in between, since every one of those can quietly strip or add characters. Sampling settings are not controllable through this harness and are not published by the provider, so defaults were used; that is a limitation rather than a control.
The eight prompts, verbatim
In two sentences, explain why the sky appears blue.
Write a 600-word essay on the history of the printing press and its effect on literacy in Europe.
Write a Python function that merges two sorted lists into one sorted list. Include a docstring and three doctests.
List 10 practical tips for reducing household energy use. One line each, no intro.
Explica en español, en unas 200 palabras, qué es la fotosíntesis y por qué importa.
日本語で俳句を三つ作ってください。それぞれに季語を必ず入れてください。
Produce a markdown table comparing four programming languages across five attributes.
Write a 300-word dialogue between a librarian and a student about how to find primary sources.
Where this study stops
One provider, three model identifiers, one harness, one date. Nothing here is longitudinal, and a provider can change behaviour between releases.
96 outputs rules out a per-output or per-paragraph marker. It does not rule out a rare probabilistic marker appearing in well under 1% of outputs. Ruling that out would need a corpus one to two orders of magnitude larger.
Generation ran through a command-line agent harness. If a marker were applied as a presentation-layer step in a different product surface, this capture path would not see it. A sampling-layer mark would be unaffected by the harness.
The corpus was generated for this study, so the prompt distribution is ours rather than the world's.
None of this measures the statistical watermark Anthropic has confirmed. That remains unmeasurable outside Anthropic.
Run it on your own text
The same character classes, scanned in your browser. Paste Claude output, or anything else, and you get a per-character count rather than a verdict. Nothing is uploaded.
If it comes back clean, that matches our corpus. If it does not, the interesting question is where the text has been since it was generated: editors, CMSs, and web pages all leave these characters behind routinely.
Invisible character checker
This local tool finds and cleans common invisible characters before publishing, editing, or review.
Analysis runs in your browser.
Characters checked
0 found
Zero-width space U+200B
0
Zero-width non-joiner U+200C
0
Zero-width joiner U+200D
0
Word joiner U+2060
0
Byte-order mark U+FEFF
0
Soft hyphen U+00AD
0
Non-breaking space U+00A0
0
Narrow non-breaking space U+202F
0
Data, code, and how to check us
The scanner is a dependency-free Node script. Point it at your own corpus: outputs from any model, saved as plain text. The numbers are directly comparable to ours.
aggregate.json (totals overall and per model, per character class).
per-file.csv (one row per output, 96 rows, every class counted).
manifest.json lists the models, prompts, design, control result, and the stated limitations.
scan.mjs is the analysis script. node scan.mjs [corpusDir] [outDir]
Reuse is welcome with attribution and a link back. If a re-run disagrees with ours, that is a correction and it gets published. See the corrections policy.
What follows from this
If you are using a tool that strips zero-width characters and calling that "removing the Claude watermark," this is the measurement that shows the two are unrelated. The stripping is real and occasionally useful, because invisible characters do break linters, search, and diffs. On this corpus, though, there was nothing to strip, and Anthropic has never described its mark that way.
The honest position on Claude's actual watermark is unchanged by this study: Anthropic says it exists, has not described the mechanism, and has published no detector.