Zerowidth CleanerAll measured guides

CLAUDE WATERMARK REMOVER · PRACTICAL TEST

Does an empty cleaned query value mean the parameter is absent?

No. Our q plus U+200B value becomes empty after cleanup, but has(q) stays true and get(q) returns an empty string. The missing-key control instead returns null. A bare q and q= both parse as a present empty value in this test.

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

Open the Claude text cleaner · Full measured data

Code-point comparison for Marked empty-looking value

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 empty-looking value
direct string / keep / invisible true
"q=​"
U+0071 U+003D U+200B
"q="
Removed 1 invisible character
{"get":"​","hasKey":true,"hasEmpty":false,"hasMarker":true,"serialized":"q=%E2%80%8B"}
{"get":"","hasKey":true,"hasEmpty":true,"hasMarker":false,"serialized":"q="}
Empty assignment
direct string / keep / invisible true
"q="
U+0071 U+003D
"q="
No selected invisible characters found
{"get":"","hasKey":true,"hasEmpty":true,"hasMarker":false,"serialized":"q="}
{"get":"","hasKey":true,"hasEmpty":true,"hasMarker":false,"serialized":"q="}
Bare key
direct string / keep / invisible true
"q"
U+0071
"q"
No selected invisible characters found
{"get":"","hasKey":true,"hasEmpty":true,"hasMarker":false,"serialized":"q="}
{"get":"","hasKey":true,"hasEmpty":true,"hasMarker":false,"serialized":"q="}
Missing key
direct string / keep / invisible true
"x=1"
U+0078 U+003D U+0031
"x=1"
No selected invisible characters found
{"get":null,"hasKey":false,"hasEmpty":false,"hasMarker":false,"serialized":"x=1"}
{"get":null,"hasKey":false,"hasEmpty":false,"hasMarker":false,"serialized":"x=1"}

Cleanup can change a value without removing its pair

The marked query has the key q and a value consisting only of U+200B. Before cleaning, has(q) is true, has(q, empty string) is false and the value-sensitive marker check is true. After cleaning, has(q) remains true, the empty-value check becomes true and the marker check becomes false. The serialized pair is now q=. Deleting the selected character therefore does not delete the key or turn the entire pair into an absent parameter. The observer’s get field retains the exact value so empty text is distinguishable from a value that merely looks empty on screen.

Null and empty string are different observations

The explicit q= reference returns an empty string and reports key presence. The bare q control yields the same observations and serializes as q=. In contrast, x=1 has no q key: get(q) returns null and every q membership check is false. These controls matter because a truthiness test on get alone would treat both null and empty string as false, losing the distinction the parser exposes. We use the optional value argument of has to ask a separate question from key existence. No pair is deleted or overwritten by the observer; this is a membership inspection experiment.

Define how the destination interprets an empty value

An application may interpret a present empty field differently from an omitted one. Preserve that distinction unless its own contract explicitly collapses them. Check key presence when presence matters, inspect the value when content matters, and decide whether cleanup producing an empty value should trigger review. Our fixed key prevents a repaired-key collision from explaining the result. The earlier query lookup guide addresses key spelling and duplicates; the value-sensitive deletion guide removes selected pairs. Here every parsed pair stays in place and the question is how to tell a present empty value from a missing key after a content edit.

Local query inspection has limited reach

The four synthetic query strings are parsed by URLSearchParams in the recorded runtime. We do not send them to a server framework, validate a form submission or infer how a website handles an empty option. Those consumers can impose additional rules. The cleaner receives the literal serialized text and removes only the selected marker before parsing; it does not know that q is a query key. Exact output, membership booleans and serialized values are available for reproduction. None of these results establishes a watermark, a source author, an accepted remote request or the intended business meaning of an empty field.

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

WHATWG URLSearchParams.has 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.