CLAUDE WATERMARK REMOVER · PRACTICAL TEST
Why does decodeURI leave a cleaned percent-encoded slash unchanged?
Our repaired a%2Fb remains a%2Fb under decodeURI but becomes a/b under decodeURIComponent. Both decode the space control. The choice of decoder determines reserved-delimiter handling; cleanup only repairs the actual U+200B interruption.
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. 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.
| Fixture and mode | Input string and code points | Output and cleaner status | Observed before / after |
|---|---|---|---|
| Marked escaped slash direct string / keep / invisible true | "a%2Fb"U+0061 U+0025 U+0032 U+200B U+0046 U+0062 | "a%2Fb"Removed 1 invisible character | {"uri":{"accepted":false,"errorName":"URIError"},"component":{"accepted":false,"errorName":"URIError"}}{"uri":{"accepted":true,"value":"a%2Fb"},"component":{"accepted":true,"value":"a/b"}} |
| Escaped delimiters direct string / keep / invisible true | "a%2Fb%3Fc%3Dd%23e"U+0061 U+0025 U+0032 U+0046 U+0062 U+0025 U+0033 U+0046 U+0063 U+0025 U+0033 U+0044 U+0064 U+0025 U+0032 U+0033 U+0065 | "a%2Fb%3Fc%3Dd%23e"No selected invisible characters found | {"uri":{"accepted":true,"value":"a%2Fb%3Fc%3Dd%23e"},"component":{"accepted":true,"value":"a/b?c=d#e"}}{"uri":{"accepted":true,"value":"a%2Fb%3Fc%3Dd%23e"},"component":{"accepted":true,"value":"a/b?c=d#e"}} |
| Escaped space direct string / keep / invisible true | "a%20b"U+0061 U+0025 U+0032 U+0030 U+0062 | "a%20b"No selected invisible characters found | {"uri":{"accepted":true,"value":"a b"},"component":{"accepted":true,"value":"a b"}}{"uri":{"accepted":true,"value":"a b"},"component":{"accepted":true,"value":"a b"}} |
| Encoded marker direct string / keep / invisible true | "%E2%80%8B"U+0025 U+0045 U+0032 U+0025 U+0038 U+0030 U+0025 U+0038 U+0042 | "%E2%80%8B"No selected invisible characters found | {"uri":{"accepted":true,"value":""},"component":{"accepted":true,"value":""}}{"uri":{"accepted":true,"value":""},"component":{"accepted":true,"value":""}} |
Two successful decoders can produce different text
The first fixture interrupts the percent escape with a literal selected marker, so both decoders initially throw URIError. Cleaning repairs the spelling to a%2Fb. Now both calls succeed, but decodeURI retains the escaped slash while decodeURIComponent returns a literal slash. The multi-delimiter control keeps encoded slash, question mark, equals sign and hash under decodeURI; the component decoder turns each into punctuation. Both decode the ordinary encoded-space control to a space. Both also turn the ASCII spelling of the encoded marker into a real U+200B after the cleaner stage. Accepted status and output text are separate fields because success alone does not identify the resulting representation.
Retention is a decoding rule rather than failed cleanup
The earlier URI encoder guide compares the opposite conversion direction, and the percent-error guide focuses on rejection of malformed escapes. This matrix makes successful reserved-escape retention the central question. It calls the two JavaScript functions directly, without navigation, URL parsing or server routing. The raw percent characters are not themselves in the homepage removal set. The encoded-marker control additionally demonstrates that neither decoder is an invisible-character cleaner: a successful call can introduce the decoded character that was absent from the raw notation. We do not test repeated decoding, lowercase escape preservation, every reserved character, legacy encodings or form-plus behavior. Each observed string is limited to the explicit fixture and runtime.
Decode the representation at the intended argument boundary
Determine whether the source is a whole URI or component data before deciding which operation belongs in the pipeline. Preserve the raw spelling when escaped delimiters carry meaning for a later parser. Avoid assuming that a literal slash and an escaped slash route identically on a real destination; this experiment contacts no such endpoint. If decoded text needs inspection, inspect that stage separately instead of relying solely on the earlier character count. The multi-delimiter and space controls prevent interpreting every retained escape as a decoder failure. The downloads show exact before and after calls, with exceptions and successful values distinguished, providing reproducible evidence for the decoder choice without claiming a universal URL repair policy.
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 decodeURI 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.