Zerowidth CleanerAll measured guides

CLAUDE WATERMARK REMOVER · PRACTICAL TEST

Why does a Unicode regex still reject cleaned decomposed café?

Our literal /^café$/u rejects decomposed cafe plus U+0301 even after U+200B is removed. Normalizing that cleaned value to NFC makes the match succeed. The Unicode flag alone does not make this literal match canonically equivalent spellings.

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

Open the Claude text cleaner · Full measured data

Code-point comparison for Marked decomposed cafe

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 decomposed cafe
direct string / keep / invisible true
"cafe​́"
U+0063 U+0061 U+0066 U+0065 U+200B U+0301
"café"
Removed 1 invisible character
{"literal":false,"afterNFC":false,"nfc":"cafe​́"}
{"literal":false,"afterNFC":true,"nfc":"café"}
Decomposed accent
direct string / keep / invisible true
"café"
U+0063 U+0061 U+0066 U+0065 U+0301
"café"
No selected invisible characters found
{"literal":false,"afterNFC":true,"nfc":"café"}
{"literal":false,"afterNFC":true,"nfc":"café"}
Precomposed accent
direct string / keep / invisible true
"café"
U+0063 U+0061 U+0066 U+00E9
"café"
No selected invisible characters found
{"literal":true,"afterNFC":true,"nfc":"café"}
{"literal":true,"afterNFC":true,"nfc":"café"}
Unaccented control
direct string / keep / invisible true
"cafe"
U+0063 U+0061 U+0066 U+0065
"cafe"
No selected invisible characters found
{"literal":false,"afterNFC":false,"nfc":"cafe"}
{"literal":false,"afterNFC":false,"nfc":"cafe"}

The selected gap and the accent are separate obstacles

The marked fixture ends with e, U+200B and U+0301. Before cleanup, neither the literal regex nor the same regex after NFC accepts it. After the homepage removes U+200B, the ordinary literal test still returns false. The NFC branch now returns true and records café as its normalized string. This paired result shows why a successful deletion count can coexist with an exact-match failure. The remaining combining accent is meaningful text, not another selected character that the homepage forgot to remove. The complete sequences remain available in the downloadable results so the visible word is never the sole basis for comparison.

Three controls locate the remaining difference

The unmarked decomposed spelling also fails the literal regex and succeeds after NFC. The precomposed café reference succeeds through both branches. Plain unaccented cafe fails through both branches, including normalization. These controls prevent two mistaken interpretations: the Unicode flag does not automatically make the decomposed spelling match this precomposed literal, and NFC does not invent a missing accent. We use one fixed anchored expression with the u flag in every row. There is no case-insensitive matching, accent removal, locale collation or search-engine behavior involved. This is an exact regex contract on the recorded strings.

Normalize comparison copies under an explicit contract

If the destination intends canonically equivalent spellings to compare alike, define a normalization policy and apply it consistently to both expected values and incoming comparison copies. Preserve the original when its precise sequence matters. In this experiment the expected literal is already precomposed, so normalizing the accepted candidate to NFC is enough for the measured match. That observation does not authorize changing every stored document or replacing every combining mark. The earlier method guide asks whether normalization deletes selected invisible characters. Here it is an additional stage used after a deliberate deletion to satisfy a separate exact-match requirement.

A matching word is a narrow result

We test four authored words, one Latin accent and one JavaScript runtime. We do not validate a person’s name, compare every canonical sequence, test grapheme cursor positions or measure a database collation. A successful boolean also says nothing about whether the surrounding sentence is correct. Keep destination-specific samples, including a negative unaccented example, when adopting a comparison rule. The cleaner does not run this regex or silently normalize its result. All normalization happens in the independent observer shown in reproduce.cjs. These synthetic strings provide no evidence that Claude emitted the characters or that a statistical watermark has been removed.

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 text processing; Unicode mode and string normalization 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.