Zerowidth CleanerAll measured guides

CLAUDE WATERMARK REMOVER · PRACTICAL TEST

Why can encodeInto write zero bytes for a cleaned emoji?

Our three-byte destination cannot hold the four-byte emoji, so encodeInto reports read 0 and written 0. A cleaned éX fits with read 2 and written 3. Use the returned counts rather than assuming the destination contains a complete encoding.

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

Open the Claude text cleaner · Full measured data

Code-point comparison for Marker before accent

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 before accent
direct string / keep / invisible true
"​éX"
U+200B U+00E9 U+0058
"éX"
Removed 1 invisible character
{"read":1,"written":3,"bufferHex":"e2808b","writtenHex":"e2808b","remaining":"éX"}
{"read":2,"written":3,"bufferHex":"c3a958","writtenHex":"c3a958","remaining":""}
Accent control
direct string / keep / invisible true
"éX"
U+00E9 U+0058
"éX"
No selected invisible characters found
{"read":2,"written":3,"bufferHex":"c3a958","writtenHex":"c3a958","remaining":""}
{"read":2,"written":3,"bufferHex":"c3a958","writtenHex":"c3a958","remaining":""}
Emoji control
direct string / keep / invisible true
"😀X"
U+1F600 U+0058
"😀X"
No selected invisible characters found
{"read":0,"written":0,"bufferHex":"000000","writtenHex":"","remaining":"😀X"}
{"read":0,"written":0,"bufferHex":"000000","writtenHex":"","remaining":"😀X"}
ASCII control
direct string / keep / invisible true
"ABX"
U+0041 U+0042 U+0058
"ABX"
No selected invisible characters found
{"read":3,"written":3,"bufferHex":"414258","writtenHex":"414258","remaining":""}
{"read":3,"written":3,"bufferHex":"414258","writtenHex":"414258","remaining":""}

The destination can fill before the source is consumed

The first synthetic string begins with U+200B followed by éX. Its three-byte marker fills the entire destination before cleanup: read is one UTF-16 unit, written is three bytes, and the remainder is éX. After the actual cleaner removes that marker, the accented letter and X together fit exactly. Their read count is two while their written count remains three. The plain accent control confirms that result without deletion. The emoji control cannot fit its first character, so neither count advances. Its zero-filled buffer is allocation state, not encoded text. The ASCII control consumes all three units and writes three bytes. We save both the whole buffer and the actually written prefix to expose that distinction.

Capacity reporting differs from cutting an existing buffer

The earlier byte-prefix experiment encodes first and then deliberately slices an incomplete character. Here TextEncoder receives a limited destination up front and stops without writing a partial leading emoji. These are different operations even though both involve byte limits. The remaining string is selected with the returned read count, whose unit is UTF-16 rather than bytes. We use a fresh three-byte Uint8Array for each observation. No network backpressure, reused buffer contents, streaming transport or retry loop is tested. The recorded empty written prefix must not be replaced by the full allocation when deciding what data was produced. Our observer does not change the cleaner or claim that its homepage exposes an encodeInto interface.

Track progress before retrying a remaining source

A caller that keeps offering the same undersized buffer to this emoji would make no progress under the measured conditions. Select capacity and retry behavior according to the actual encoder contract, and send only the written region onward. Retain any unconsumed source rather than treating a returned object as completion. The accent example also prevents confusing the read count with a byte offset: using two as the written length would omit the final X. These four local cases do not establish a universal buffer allocation strategy or a safe display truncator. They provide concrete counters to check in a destination integration. The downloaded harness preserves exact byte hex, remaining text and runtime metadata for independent reruns.

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 TextEncoder.encodeInto 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.