Zerowidth CleanerAll measured guides

CLAUDE WATERMARK REMOVER · PRACTICAL TEST

Why is Buffer.byteLength larger than the decoded Base64 buffer?

Our marked, whitespace and punctuation wrappers report two bytes with Buffer.byteLength(base64) but decode to one byte. The plain QQ== reference reports one. Measure the decoded Buffer length for actual output size; a successful permissive decode is not strict Base64 validation.

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

Open the Claude text cleaner · Full measured data

Code-point comparison for Marker in wrapper

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
Marker in wrapper
direct string / keep / invisible true
"Q​Q=="
U+0051 U+200B U+0051 U+003D U+003D
"QQ=="
Removed 1 invisible character
{"estimatedBytes":2,"decodedBytes":1,"decodedHex":"41","canonicalBase64":"QQ=="}
{"estimatedBytes":1,"decodedBytes":1,"decodedHex":"41","canonicalBase64":"QQ=="}
Plain reference
direct string / keep / invisible true
"QQ=="
U+0051 U+0051 U+003D U+003D
"QQ=="
No selected invisible characters found
{"estimatedBytes":1,"decodedBytes":1,"decodedHex":"41","canonicalBase64":"QQ=="}
{"estimatedBytes":1,"decodedBytes":1,"decodedHex":"41","canonicalBase64":"QQ=="}
Whitespace in wrapper
direct string / keep / invisible true
"Q Q=="
U+0051 U+0020 U+0051 U+003D U+003D
"Q Q=="
No selected invisible characters found
{"estimatedBytes":2,"decodedBytes":1,"decodedHex":"41","canonicalBase64":"QQ=="}
{"estimatedBytes":2,"decodedBytes":1,"decodedHex":"41","canonicalBase64":"QQ=="}
Punctuation in wrapper
direct string / keep / invisible true
"Q#Q=="
U+0051 U+0023 U+0051 U+003D U+003D
"Q#Q=="
No selected invisible characters found
{"estimatedBytes":2,"decodedBytes":1,"decodedHex":"41","canonicalBase64":"QQ=="}
{"estimatedBytes":2,"decodedBytes":1,"decodedHex":"41","canonicalBase64":"QQ=="}

The size estimate and actual output disagree

The first source inserts U+200B between the two Q characters of QQ==. Buffer.byteLength with the base64 encoding argument reports two, while Buffer.from decodes a one-byte buffer with hex 41. After the homepage removes the marker, the size estimate becomes one and the decoded buffer remains the same one byte. This is an important difference from an encoded hidden payload: the marker here is literal wrapper text and no decoded U+200B is involved. We save decoded hex and a canonical re-encoding alongside both lengths, making the exact output observable instead of assuming an estimate equals the bytes actually produced.

Whitespace and punctuation survive cleanup

The plain QQ== reference estimates and decodes one byte. A space inserted into the wrapper yields the same two-versus-one discrepancy as the marked input, but the cleaner leaves that space unchanged. The punctuation control with # also remains unchanged and has the same recorded discrepancy. All four outputs decode to hex 41 in this Node runtime and re-encode as QQ==. These controls show why a no-findings message cannot reconcile every size mismatch and why permissive acceptance by this decoder cannot establish a strict alphabet policy. We report the actual controls instead of generalizing to every malformed Base64 spelling or another decoder.

Allocate and validate under separate rules

If actual decoded size matters, obtain it from the decoded buffer at the stage where those bytes exist. If an application accepts only a strict Base64 grammar, validate that grammar independently before relying on a permissive decoder. Do not use a convenient length estimate as an authentication, content-type or integrity check. Preserve the original wrapper when rejecting malformed input so an operator can see whether it contained whitespace, punctuation or an unwanted selected character. Our observer does not fetch an attachment, execute decoded content or treat canonical re-encoding as proof that the original spelling met an application’s input policy.

A size question differs from payload inspection

The earlier Base64 guide decodes a deliberately encoded hidden character and explains why cleaning ASCII wrapper text cannot remove that payload character. This page measures the size API on wrappers containing literal extra characters and compares it with the real decoded buffer length. No payload text is cleaned after decoding. The one-byte output is an authored control, not a sampled document or signature. The runtime and full script make the discrepancy reproducible, while other encodings or Node versions require their own records. These bytes do not identify an author, detect hidden watermark information or demonstrate removal of a statistical signal.

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

Node.js Buffer.byteLength 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.