Zerowidth CleanerAll measured guides

CLAUDE WATERMARK REMOVER · PRACTICAL TEST

Does JSON.stringify remove a script closing sequence from cleaned text?

No in our string test. Cleanup turns an interrupted closing tag into </script>, and JSON.stringify preserves it inside the JSON string. Replacing literal less-than signs with JSON Unicode escapes retains the parsed value. Browser execution is not tested.

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

Open the Claude text cleaner · Full measured data

Code-point comparison for Interrupted closing tag

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. Destination observations run independently on the exact input and cleaned strings in the recorded Node runtime. 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
Interrupted closing tag
direct string / keep / invisible true
"</scr​ipt>"
U+003C U+002F U+0073 U+0063 U+0072 U+200B U+0069 U+0070 U+0074 U+003E
"</script>"
Removed 1 invisible character
{"json":"{\"text\":\"</scr​ipt>\"}","containsScriptEndPrefix":false,"escapedJson":"{\"text\":\"\\u003C/scr​ipt>\"}","roundtrip":true,"method":"String boundary check, not browser execution"}
{"json":"{\"text\":\"</script>\"}","containsScriptEndPrefix":true,"escapedJson":"{\"text\":\"\\u003C/script>\"}","roundtrip":true,"method":"String boundary check, not browser execution"}
Closing tag
direct string / keep / invisible true
"</script>"
U+003C U+002F U+0073 U+0063 U+0072 U+0069 U+0070 U+0074 U+003E
"</script>"
No selected invisible characters found
{"json":"{\"text\":\"</script>\"}","containsScriptEndPrefix":true,"escapedJson":"{\"text\":\"\\u003C/script>\"}","roundtrip":true,"method":"String boundary check, not browser execution"}
{"json":"{\"text\":\"</script>\"}","containsScriptEndPrefix":true,"escapedJson":"{\"text\":\"\\u003C/script>\"}","roundtrip":true,"method":"String boundary check, not browser execution"}
Less-than text
direct string / keep / invisible true
"a < b"
U+0061 U+0020 U+003C U+0020 U+0062
"a < b"
No selected invisible characters found
{"json":"{\"text\":\"a < b\"}","containsScriptEndPrefix":false,"escapedJson":"{\"text\":\"a \\u003C b\"}","roundtrip":true,"method":"String boundary check, not browser execution"}
{"json":"{\"text\":\"a < b\"}","containsScriptEndPrefix":false,"escapedJson":"{\"text\":\"a \\u003C b\"}","roundtrip":true,"method":"String boundary check, not browser execution"}
Plain control
direct string / keep / invisible true
"AB"
U+0041 U+0042
"AB"
No selected invisible characters found
{"json":"{\"text\":\"AB\"}","containsScriptEndPrefix":false,"escapedJson":"{\"text\":\"AB\"}","roundtrip":true,"method":"String boundary check, not browser execution"}
{"json":"{\"text\":\"AB\"}","containsScriptEndPrefix":false,"escapedJson":"{\"text\":\"AB\"}","roundtrip":true,"method":"String boundary check, not browser execution"}

A valid JSON string can retain HTML-sensitive spelling

Our first fixture deliberately interrupts the letters of a script closing sequence with U+200B. The saved homepage script removes that code point, leaving the contiguous closing sequence. We then serialize an object whose text property contains the exact string. The serialized JSON retains the literal less-than sign and slash. A case-insensitive prefix check changes from false before cleaning to true afterwards. The unmarked closing-tag control produces the same flag without cleanup, while the ordinary comparison text and AB control do not match that prefix. All these results are string observations in Node. We do not create an executable HTML document or infer that any script ran.

A JSON escape can change source spelling without changing the value

The observer creates a second JSON representation by replacing each literal less-than sign in the serialized result with the six-character Unicode escape for U+003C. Parsing that JSON reconstructs the original supplied string in every row. The comparison-text control demonstrates the same round trip for an ordinary less-than sign that is unrelated to a closing tag. This is a representation change at the JSON boundary, separate from the cleaner deleting U+200B. The HTML standard is the primary reference for script-content restrictions; the local test does not implement its tokenizer or audit a framework. It also does not establish handling of every HTML embedding context, attribute value, URL, comment, or executable expression.

Choose serialization for the actual output context

When cleaned data moves into a webpage, identify whether it is being served as a JSON response, inserted as text, or embedded in HTML source. Those routes have different contracts. Retain the JSON result and inspect the final generated markup when using a template or framework; a successful JSON parse alone answers only the JSON question. Use the receiving system’s documented handling for that context and test the completed boundary. Our paired representations isolate why character cleanup cannot stand in for that work. The downloadable script contains the exact prefix check and escaping operation, allowing readers to reproduce the observations without publishing a test payload or claiming a watermark-removal success.

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

HTML script-content restrictions 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.