Zerowidth CleanerAll measured guides

CLAUDE WATERMARK REMOVER · PRACTICAL TEST

Why does #abcd fail to match an ID that looks like abcd?

In our browser, an ID containing U+200B does not match #abcd until cleaning removes it. CSS.escape lets a selector match the original exact ID without deleting the marker.

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

Open the Claude text cleaner · Full measured data

Code-point comparison for Selected marker

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. Three destination checks use separately recorded browser observations; those pages explain the distinction. 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
Selected marker
direct string / keep / invisible true
"ab​cd"
U+0061 U+0062 U+200B U+0063 U+0064
"abcd"
Removed 1 invisible character
{"escaped":"ab​cd","escapedOwnSelectorMatches":true,"plainSelectorMatches":false}
{"escaped":"abcd","escapedOwnSelectorMatches":true,"plainSelectorMatches":true}
Retained joiner
direct string / keep / invisible true
"ab‍cd"
U+0061 U+0062 U+200D U+0063 U+0064
"ab‍cd"
No selected invisible characters found
{"escaped":"ab‍cd","escapedOwnSelectorMatches":true,"plainSelectorMatches":false}
{"escaped":"ab‍cd","escapedOwnSelectorMatches":true,"plainSelectorMatches":false}
Ordinary identifier
direct string / keep / invisible true
"abcd"
U+0061 U+0062 U+0063 U+0064
"abcd"
No selected invisible characters found
{"escaped":"abcd","escapedOwnSelectorMatches":true,"plainSelectorMatches":true}
{"escaped":"abcd","escapedOwnSelectorMatches":true,"plainSelectorMatches":true}
Leading digit
direct string / keep / invisible true
"1abcd"
U+0031 U+0061 U+0062 U+0063 U+0064
"1abcd"
No selected invisible characters found
{"escaped":"\\31 abcd","escapedOwnSelectorMatches":true,"plainSelectorMatches":false}
{"escaped":"\\31 abcd","escapedOwnSelectorMatches":true,"plainSelectorMatches":false}

Two selectors ask different matching questions

The observer creates a detached div and assigns each fixture to its id property. It tests the fixed selector #abcd, then a selector formed from a hash and CSS.escape of the exact ID. The selected-marker ID fails the fixed selector before cleaning and matches it after becoming abcd. Its escaped exact selector matches at both stages. The retained joiner still prevents the fixed match. The plain reference matches, while the leading-digit reference requires the escaped spelling for its own exact selector. We record the selector escape string and both booleans to separate spelling differences from selector syntax.

Escaping preserves the identifier

CSS.escape serializes a string for selector use; it does not remove a code point or assert that an identifier is desirable. That explains why an escaped selector can match the marked ID without cleaning it. Our previous JavaScript identifier guide concerned language token syntax, while this test concerns a DOM property and CSS matching. The elements are detached, so no published page IDs or styles are changed. The browser version is saved with the measurements. We do not test a full stylesheet, a query across many elements, duplicate IDs or CSS injection defenses. Exact matching alone does not establish that the chosen element is the intended target.

Keep producer and selector in agreement

Inspect the actual id property and the code that created it before changing either side. If the marker is accidental, repair the identifier at its source and update the references that should follow the new value. If the exact identifier must be preserved, construct an appropriate escaped selector rather than deleting data merely to fit a hard-coded spelling. Test the intended element after the change and check references such as labels and fragment links separately. A cleaner report cannot coordinate those references automatically. The downloadable browser test reproduces the two matching questions without altering a live document or claiming that every CSS selector issue is invisible text.

Reproduce this test

Download the independent browser test and open it locally to rerun the destination observer. Original Chromium record identifies the browser version. The Node harness rechecks the cleanup callback and joins its outputs with those saved browser observations; it does not rerun the browser validator. Save browser-record.json beside the other downloads for that join. 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

CSSOM CSS.escape 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.