Zerowidth CleanerAll measured guides

CLAUDE WATERMARK REMOVER · PRACTICAL TEST

Why is the second token unchanged after replace?

String.replace with a string search replaces the first occurrence in our controls. replaceAll replaces both. Removing U+200B can make an earlier token become the first match, changing which occurrence replace edits.

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

Open the Claude text cleaner · Full measured data

Code-point comparison for Marked first token

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
Marked first token
direct string / keep / invisible true
"A​B AB"
U+0041 U+200B U+0042 U+0020 U+0041 U+0042
"AB AB"
Removed 1 invisible character
{"first":"A​B X","all":"A​B X","source":"A​B AB"}
{"first":"X AB","all":"X X","source":"AB AB"}
Two tokens
direct string / keep / invisible true
"AB AB"
U+0041 U+0042 U+0020 U+0041 U+0042
"AB AB"
No selected invisible characters found
{"first":"X AB","all":"X X","source":"AB AB"}
{"first":"X AB","all":"X X","source":"AB AB"}
One token
direct string / keep / invisible true
"AB"
U+0041 U+0042
"AB"
No selected invisible characters found
{"first":"X","all":"X","source":"AB"}
{"first":"X","all":"X","source":"AB"}
No token
direct string / keep / invisible true
"AX"
U+0041 U+0058
"AX"
No selected invisible characters found
{"first":"AX","all":"AX","source":"AX"}
{"first":"AX","all":"AX","source":"AX"}

An earlier repaired token changes the target

The marked input contains A, U+200B and B, then a space and plain AB. Before cleanup, the first matching AB is the second visible token, so the string-search replace edits that token. After cleanup, AB appears at the beginning as well. The same replace call now edits the first token and leaves the second one intact. This is not merely an increased count of available matches. It is a change to the identity of the occurrence chosen by an operation that stops after its first match. The exact source and resulting strings make that selection observable.

The plain duplicate control explains the API

AB AB becomes X AB with replace and X X with replaceAll. The one-token control becomes X through both operations, while AX remains unchanged. A single-occurrence example would therefore fail to reveal the distinction. We pass the literal search string AB and replacement string X in every row, avoiding regular-expression flags and dollar replacement templates. Those other contracts already have separate guides. Here the only intended difference between the two observer calls is whether all literal occurrences are selected. Neither observer mutates its input string, which we also retain in the record.

Choose the occurrence policy before bulk edits

If every literal occurrence should change, use an operation that expresses that intent and test a repeated-token input. If only one occurrence should change, establish how it is selected and review that choice after any preprocessing. Our first fixture shows that removing a marker can shift the first recognized occurrence to an earlier location without any visible word reordering. A workflow that reviewed the old target should not assume it still identifies the new target. Preserve a working copy and compare complete output strings when the replacement has meaning beyond cosmetic formatting.

The observed transformation is deliberately small

We do not apply these replacements to a real document, template engine, database query or user account. The cleaner removes its selected code point; the observer independently performs literal string replacements on both versions. X is a synthetic replacement label, with no formatting or interpretation attached. These tests do not establish the right replacement policy for a particular corpus or guarantee that a repeated token is unwanted. They demonstrate an operation boundary that can matter after cleanup. The result is not a measurement of watermark removal, rewriting quality, plagiarism, authorship or downstream detector behavior.

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 String.replace 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.