When a byte count differs from a string length, the encoding may be working exactly as intended. A visible character, a Unicode code point and a JavaScript UTF-16 code unit are different units. Name the unit before using the number to validate a payload.
Count the bytes that actually travel
Input: Ship it, café ☕
UTF-16 code units: 15
UTF-8 bytes: 18
Base64: U2hpcCBpdCwgY2Fmw6kg4piV
Most characters in this example are ASCII and occupy one UTF-8 byte. The accented é occupies two bytes. The coffee symbol occupies three. The Lab’s byte count is the size of the UTF-8 sequence, not a count of displayed characters. Using a byte-oriented encoder directly on JavaScript text can fail or corrupt characters outside its expected range.
Run the Unicode text example →
Visually identical need not mean byte-identical
The accented letter é can be represented as the single code point U+00E9, or as U+0065 followed by the combining acute accent U+0301. The strings may look the same. Their code points, UTF-8 bytes and Base64 encodings differ.
U+00E9
UTF-8: c3 a9
Base64: w6k=
U+0065 U+0301
UTF-8: 65 cc 81
Base64: ZcyB
The tools do not silently normalize Unicode. Normalization may be appropriate for a search index or a username policy, but it changes the input representation and should be a deliberate application decision. An inspection tool preserves that distinction so you can locate the mismatch.
Handle invalid sequences without losing evidence
The UTF-8 decoder uses strict validation. Malformed bytes produce an error while your Base64 input remains editable. A leading byte-order mark is preserved as a character in text mode; it is not silently stripped. Binary mode keeps every byte and offers a hexadecimal preview when the data is not text.
JavaScript can also hold unpaired surrogate code units that are not valid Unicode scalar values. A default UTF-8 encoder may replace them. The Lab rejects unpaired surrogates instead of silently introducing replacement characters. This matters when debugging damaged strings or truncated data.
Choose your comparison deliberately
JSON Compare ignores object key order but compares decoded string values exactly. Escaped and literal spellings of the same code points compare equal. Composed and decomposed Unicode sequences remain different unless you normalize them before inspection. Neither result is inherently wrong; they answer different questions about the source.