Zerowidth CleanerAll measured guides

CLAUDE WATERMARK REMOVER · PRACTICAL TEST

Why does JSON still fail after invisible cleanup?

Our parser accepts JSON after removing a literal U+200B outside a string, but still rejects retained NBSP and NUL. A clean status does not validate JSON grammar.

Tested October 7, 2026 · v24.19.0 · 4 measured runs

Open the Claude text cleaner · Full measured data

Code-point comparison for Selected character before key

Measured inputs and outputs

These are locally constructed test strings, not evidence that Claude inserts these characters. We executed the saved homepage script snapshot with a minimal DOM harness and compared exact strings. The invisible-checkbox state and dash mode appear in each row. The observations below test this page's specific question. File API and event-lifecycle tests include an additional stage described in the analysis. We make no detector-score or statistical-watermark removal claim.

Before and after observations; full code points and strings are in the JSON download.
Fixture and modeInput string and code pointsOutput and cleaner statusObserved before / after
Selected character before key
direct string / keep / invisible true
"{​\"x\":1}"
U+007B U+200B U+0022 U+0078 U+0022 U+003A U+0031 U+007D
"{\"x\":1}"
Removed 1 invisible character
{"valid":false,"errorName":"SyntaxError"}
{"valid":true,"value":{"x":1}}
NBSP before key
direct string / keep / invisible true
"{ \"x\":1}"
U+007B U+00A0 U+0022 U+0078 U+0022 U+003A U+0031 U+007D
"{ \"x\":1}"
No selected invisible characters found
{"valid":false,"errorName":"SyntaxError"}
{"valid":false,"errorName":"SyntaxError"}
NUL before key
direct string / keep / invisible true
"{\u0000\"x\":1}"
U+007B U+0000 U+0022 U+0078 U+0022 U+003A U+0031 U+007D
"{\u0000\"x\":1}"
No selected invisible characters found
{"valid":false,"errorName":"SyntaxError"}
{"valid":false,"errorName":"SyntaxError"}
Allowed tab
direct string / keep / invisible true
"{\t\"x\":1}"
U+007B U+0009 U+0022 U+0078 U+0022 U+003A U+0031 U+007D
"{\t\"x\":1}"
No selected invisible characters found
{"valid":true,"value":{"x":1}}
{"valid":true,"value":{"x":1}}

Whitespace is part of the grammar

Our fixture begins with an opening brace and places one specific character before the quoted key x. The selected U+200B case fails JSON.parse before cleanup and parses afterward. NBSP and NUL remain in their inputs, and both still fail. The tab reference parses at both stages. These are structural positions, outside quoted values. The result is therefore about token separation, not an invisible character inside a key or a Unicode escape decoded into a string. The observer saves success and the error class rather than treating runtime error wording as a stable diagnostic.

Removal and validation answer different questions

RFC 8259 defines a narrow set of whitespace characters around JSON structural tokens. A character that looks blank in an editor is not automatically in that set. The homepage neither parses JSON nor reports the source offset of a syntax failure. Its no-findings message means no selected removal occurred under the settings shown in our record. It does not establish a valid request body. These four authored fixtures were measured with the recorded Node runtime; no CMS importer, database endpoint or Claude response was used to produce the examples.

Repair the rejected token deliberately

Save the complete original response and the parser error before editing a working copy. Determine whether the problem lies outside a string, inside a value or in a byte-decoding stage. For a confirmed unwanted structural character, make a targeted repair and run the same destination parser again. Do not delete spaces globally: spaces inside strings may be meaningful data. An accepted parse only establishes this grammar check; a schema and application rules may still reject the value. Keep those checks separate from the cleaner removal count and from any claim about authorship.

Reproduce this test

Save reproduce.cjs and tested-app.js in the same folder. Run the command below with Node.js. The harness prints its runtime, script SHA-256 and every measured row. Compare those rows with the original record. Using a newer script or runtime creates a new experiment; retain the version information with your rerun.

node reproduce.cjs

Reference and next check

JSON grammar provides the relevant primary definition. The table and fixture analysis are original measurements. For broader inspection, use our Unicode inspector. Read the scope distinction before interpreting cleanup as a watermark result.