Unicode & UTF-8 Inspector
Paste any text to see what is actually inside it: every character's code point, decimal value, UTF-8 bytes, HTML entity and JavaScript escape — plus the counts that decide whether a string fits in a database column or a 64-byte limit.
| # | Char | Code point | UTF-8 bytes | Entity | JS escape |
|---|
Why Character Count Is Not Byte Count
A JavaScript string is a sequence of UTF-16 code units, a database column like VARCHAR(64) usually counts characters, and a buffer or an HTTP header counts bytes. Those are three different numbers for the same text, and the gap is exactly where truncation bugs live. "café".length is 4, but in UTF-8 it is 5 bytes. A single emoji such as 👍 is one character, two UTF-16 code units (length === 2) and four UTF-8 bytes.
The Four Number Systems
- Code points — what humans call "characters", written
U+XXXX. This is what you actually mean. - UTF-16 code units — what
.lengthandslice()count in JavaScript, Java and C#. Anything aboveU+FFFF(most emoji) costs two units, so string slicing can split a character in half. - UTF-8 bytes — what storage, network and hashing count. 1 byte for ASCII, 2 for most Latin accents, 3 for CJK, 4 for emoji.
- Grapheme clusters — what the eye sees. A flag or a skin-toned emoji is several code points joined by zero-width joiners, so
Intl.Segmenteror theuflag in a regex is the only reliable way to count them.
Where This Bites in Production
- Password hashing. bcrypt hashes at most 72 bytes. A 64-character password is already near the wall, and one emoji pushes it over — the remainder is silently ignored.
- Database columns. MySQL's
utf8mb4allows 4-byte characters; the olderutf8alias only 3, so an emoji insert fails or gets mangled. Index key length is measured in bytes too, which is whyVARCHAR(255)can still blow up a unique index. - String comparison. Lookalike characters are different code points: Cyrillic
аisU+0430, LatinaisU+0061. They render identically and never compare equal — use NFKC normalisation before comparing user input. - Truncation in the UI.
str.slice(0, 20)can cut an emoji in half and leave a lone surrogate, which renders as a replacement box in the browser.
Invisible Characters Are Usually the Bug
Switch the table to "invisible" and paste a string that "looks fine" but fails validation. Non-breaking space (U+00A0), zero-width space (U+200B), direction marks and the byte-order mark do not show up in a diff, a log line or a code review, but they break equality checks, JSON keys and shell arguments. Copy-pasted from a PDF or a Word document, this is the most common cause of "the same string" behaving differently.
FAQ
- Q: Is my text uploaded anywhere?
- No. Everything is computed in your browser with
TextEncoderandcodePointAt(). Open the Network tab while you type: there are no requests after the page loads. - Q: Why does one emoji count as two characters?
- Because JavaScript strings are UTF-16, and every code point above
U+FFFFis stored as a surrogate pair — two code units."👍".lengthis 2 while its code point count is 1 and its UTF-8 size is 4 bytes. UseArray.from(str).lengthor[...str].lengthfor the code point count. - Q: What is the difference between NFKC and NFC here?
- Both are Unicode normalisation forms. NFC composes
e+ combining acute intoé; NFKC additionally folds compatibility variants such as the Kelvin sign toK, ligatures to letters and full-width forms to ASCII. Compare user input with NFC, and sanitise for search or identifiers with NFKC — but never store NFKC-normalised text as the user's own content, because it destroys meaningful distinctions. - Q: How many characters fit in a 64-byte field?
- It depends on the script: 64 ASCII characters, 32 accented Latin characters, 21 CJK characters or 16 emoji. That is why limits should be stated in code points for users and enforced in bytes at the storage layer. Check the byte count above before betting on a column size.
- Q: Why do two identical-looking strings never compare equal?
- Lookalikes are distinct code points: Cyrillic
а(U+0430) versus Latina(U+0061), or a precomposedéversuseplus a combining accent. Normalise both sides (NFC for display, NFKC for identifiers) and compare the result — or, better, never use display text as a primary key.
Why Use This Inspector?
No signup, no upload, and no guessing: paste the string, read the four counts, and see exactly which characters cost extra bytes. It is the fastest way to debug a truncation bug, a lookalike-character mismatch, or a "but the strings are identical" validation failure.