Zerowidth CleanerAll measured guides

CLAUDE WATERMARK REMOVER · PRACTICAL TEST

Does JSON.stringify remove invisible characters from a string?

No in our fixtures. JSON.stringify preserves U+200B in the string value; clean the intended value before serialization if that particular character is unwanted.

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

Open the Claude text cleaner · Full measured data

Code-point comparison for Selected marker

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. Three destination checks use separately recorded browser observations; those pages explain the distinction. 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 marker
direct string / keep / invisible true
"A​B"
U+0041 U+200B U+0042
"AB"
Removed 1 invisible character
{"serialized":"{\"text\":\"A​B\"}","roundTrip":"A​B","roundTripEqual":true}
{"serialized":"{\"text\":\"AB\"}","roundTrip":"AB","roundTripEqual":true}
Retained joiner
direct string / keep / invisible true
"A‍B"
U+0041 U+200D U+0042
"A‍B"
No selected invisible characters found
{"serialized":"{\"text\":\"A‍B\"}","roundTrip":"A‍B","roundTripEqual":true}
{"serialized":"{\"text\":\"A‍B\"}","roundTrip":"A‍B","roundTripEqual":true}
Ordinary newline
direct string / keep / invisible true
"A\nB"
U+0041 U+000A U+0042
"A\nB"
No selected invisible characters found
{"serialized":"{\"text\":\"A\\nB\"}","roundTrip":"A\nB","roundTripEqual":true}
{"serialized":"{\"text\":\"A\\nB\"}","roundTrip":"A\nB","roundTripEqual":true}
Literal backslash escape
direct string / keep / invisible true
"A\\u200BB"
U+0041 U+005C U+0075 U+0032 U+0030 U+0030 U+0042 U+0042
"A\\u200BB"
No selected invisible characters found
{"serialized":"{\"text\":\"A\\\\u200BB\"}","roundTrip":"A\\u200BB","roundTripEqual":true}
{"serialized":"{\"text\":\"A\\\\u200BB\"}","roundTrip":"A\\u200BB","roundTripEqual":true}

Serialization preserves the value

The observer stores each raw fixture as the text property of an object, serializes that object and parses it back. The selected-marker fixture returns the same string before cleaning, including U+200B. After cleaning, its round trip contains AB. The retained-joiner reference retains U+200D throughout. The newline appears escaped in the serialized representation but becomes a newline again after parsing. The literal-backslash fixture round-trips as literal backslash notation, not as a decoded marker. Every row checks exact equality of the parsed value with the observer input, avoiding an assumption based on how the JSON looks in a font.

An encoder is not a cleanup policy

JSON.stringify converts a value into JSON syntax; it does not decide which content characters should be deleted. This direction differs from our earlier pages about JSON.parse structural whitespace, duplicate keys and Unicode escapes already present in JSON source. Here the input is a string value and the serializer supplies all structural punctuation. Our saved measurements use one property and a standard serializer without replacers or custom object methods. They do not measure a network transport, HTML script embedding, database storage or an API schema. Producing valid JSON does not make the text free of retained formatting or prove its origin.

Edit the value before building the document

Keep the original value and inspect any specific unwanted character before changing it. If cleanup is appropriate, apply it to that value, compare the exact result and then serialize the containing object. Avoid treating the entire serialized document as ordinary prose, because edits to structural syntax or other fields can change its meaning. Parse the produced JSON and validate the destination schema after serialization. The measured round trip is a useful check for this layer, but it does not establish that a later system will store or render the same string. This page demonstrates a boundary between content editing and JSON encoding.

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

ECMAScript JSON serialization 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.