CLAUDE WATERMARK REMOVER · PRACTICAL TEST
Why can slice(0, 1) create a broken emoji after cleaning?
Our marker-before-emoji input initially slices to U+200B. After cleaning, slice(0, 1) returns a lone high surrogate; UTF-8 encoding replaces it. The cleaner retains the complete emoji and the later slice breaks it.
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 |
|---|---|---|---|
| Marker before emoji direct string / keep / invisible true | "😀X"U+200B U+1F600 U+0058 | "😀X"Removed 1 invisible character | {"firstUnit":"","wellFormed":true,"firstCodePoint":"","encodedHex":"e2808b"}{"firstUnit":"\ud83d","wellFormed":false,"firstCodePoint":"😀","encodedHex":"efbfbd"} |
| Emoji before letter direct string / keep / invisible true | "😀X"U+1F600 U+0058 | "😀X"No selected invisible characters found | {"firstUnit":"\ud83d","wellFormed":false,"firstCodePoint":"😀","encodedHex":"efbfbd"}{"firstUnit":"\ud83d","wellFormed":false,"firstCodePoint":"😀","encodedHex":"efbfbd"} |
| Plain ASCII direct string / keep / invisible true | "ABX"U+0041 U+0042 U+0058 | "ABX"No selected invisible characters found | {"firstUnit":"A","wellFormed":true,"firstCodePoint":"A","encodedHex":"41"}{"firstUnit":"A","wellFormed":true,"firstCodePoint":"A","encodedHex":"41"} |
| Combining accent direct string / keep / invisible true | "éX"U+0065 U+0301 U+0058 | "éX"No selected invisible characters found | {"firstUnit":"e","wellFormed":true,"firstCodePoint":"e","encodedHex":"65"}{"firstUnit":"e","wellFormed":true,"firstCodePoint":"e","encodedHex":"65"} |
The edit changes which unit the later slice selects
Our first input contains a marker, a complete smile pair and X. Selecting the first UTF-16 unit before cleanup returns the marker, a well-formed string. The cleaned output begins with the retained complete smile. Applying the same one-unit slice then returns only its high surrogate, fails isWellFormed and encodes as efbfbd. The ordinary smile reference already has that sliced result without cleanup. Plain ASCII returns A with byte 41. The combining-accent reference returns e, which is well formed but omits its accent. We also record the first code point to make the unit-versus-code-point distinction directly visible.
The cleaner does not manufacture the lone surrogate
The saved homepage returns the complete emoji in the edited string; the observer’s subsequent slice introduces the malformed unit. Our previous TextEncoder article supplies unmatched surrogates in the original input and studies their export. This matrix identifies an earlier operation that can create one from initially valid text. The byte observer uses Buffer UTF-8 encoding on the sliced value, not a file export button. We do not measure display columns, browser selection ranges or a grapheme truncation library. The combining mark control is especially useful: a well-formed slice can still cut a user-perceived character, so scalar validity is only one check.
Define the truncation unit before shortening text
Preserve the complete cleaned output and select a truncation method based on the destination’s intended width unit. Code points avoid this particular surrogate split but do not by themselves preserve every combining or emoji sequence. If visual characters must remain intact, test an appropriate grapheme-aware policy separately. Do not delete a replacement character from the encoded slice and call the original emoji restored. Our authored examples establish one-unit slicing behavior and its subsequent encoding, without implementing a universal shortening function or validating an actual field quota. The saved code points and outputs help locate the loss at the destination operation instead of blaming the cleanup counter.
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 string operations 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.