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.
Open the Claude text cleaner · Full measured data
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.
| Fixture and mode | Input string and code points | Output and cleaner status | Observed before / after |
|---|---|---|---|
| Selected marker direct string / keep / invisible true | "AB"U+0041 U+200B U+0042 | "AB"Removed 1 invisible character | {"serialized":"{\"text\":\"AB\"}","roundTrip":"AB","roundTripEqual":true}{"serialized":"{\"text\":\"AB\"}","roundTrip":"AB","roundTripEqual":true} |
| Retained joiner direct string / keep / invisible true | "AB"U+0041 U+200D U+0042 | "AB"No selected invisible characters found | {"serialized":"{\"text\":\"AB\"}","roundTrip":"AB","roundTripEqual":true}{"serialized":"{\"text\":\"AB\"}","roundTrip":"AB","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.cjsReference 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.