UTF-8 Byte Viewer
See the UTF-8 bytes and Unicode code point of every character
Working…
0.0
It hasn't frozen — the result will appear when the calculation finishes.
About UTF-8 Byte Viewer
This tool splits your input into code points and runs each one through the browser's built-in TextEncoder, listing the UTF-8 bytes next to the U+ number. The phrase “character count” can mean at least three different things — code points, UTF-16 code units, or what a human sees as one character. This tool counts code points, and its byte totals are UTF-8.
It is most useful when something rejects your text for being too long even though it looks short: a database column, an API field with a byte limit, a filename limit, a push-notification payload. Seeing the bytes usually explains the mismatch within seconds.
One character, three lengths
Unicode assigns every character a number (its code point); an encoding decides how that number is written as bytes. UTF-8 uses one to four bytes. UTF-16 uses one or two 16-bit code units. JavaScript's str.length, Java's String.length() and C#'s string.Length all return UTF-16 code units, which is why they disagree with this tool for emoji.
- A (U+0041): UTF-8 41 — 1 byte; UTF-16 1 unit
- é (U+00E9): UTF-8 C3 A9 — 2 bytes; UTF-16 1 unit
- 한 (U+D55C, Korean “han”): UTF-8 ED 95 9C — 3 bytes; UTF-16 1 unit
- 😀 (U+1F600): UTF-8 F0 9F 98 80 — 4 bytes; UTF-16 2 units (D83D DE00)
Decoding the bytes by hand
RFC 3629 defines UTF-8 as a set of bit templates chosen by code point range: U+0000–007F fits in 0xxxxxxx; U+0080–07FF uses 110xxxxx 10xxxxxx; U+0800–FFFF uses 1110xxxx 10xxxxxx 10xxxxxx; and U+10000–10FFFF uses 11110xxx followed by three continuation bytes.
Take é, U+00E9, which is 000 1110 1001 in binary. Split the 11 bits as 5 + 6: 00011 and 101001. Drop them into the two-byte template and you get 11000011 10101001, which is C3 A9. For 한 (U+D55C = 1101 0101 0101 1100) the 16 bits split 4 + 6 + 6 and land in the three-byte template as ED 95 9C.
Two properties fall out of this design. The number of leading 1s in the first byte tells you how long the sequence is, and every continuation byte starts with 10. So a program dropped into the middle of a UTF-8 stream can skip forward to the next character boundary, and a byte below 0x80 is always plain ASCII — never a fragment of something else. That second property is why UTF-8 text survives tools that only understand ASCII delimiters like / and newline.
When one visible character becomes several rows
The tool prints one row per code point. When something that looks like a single character produces several rows, that is usually the clue you were looking for.
- Family emoji 👨👩👧: man, ZERO WIDTH JOINER (U+200D), woman, ZWJ, girl — five code points, 18 bytes. Each ZWJ is E2 80 8D.
- Thumbs up with a skin tone 👍🏽: U+1F44D plus modifier U+1F3FD — 8 bytes.
- é as two rows: e (U+0065) followed by COMBINING ACUTE ACCENT (U+0301, bytes CC 81). It renders the same as the single C3 A9 form but compares unequal until both strings are normalized to the same form (NFC or NFD).
- Korean filenames created on a Mac often arrive decomposed: 한 becomes three conjoining jamo U+1112, U+1161, U+11AB — 9 bytes instead of 3.
Where the three-byte/four-byte line bites
MySQL's old utf8 character set (now named utf8mb3) stores at most three bytes per character. Any four-byte character — nearly all emoji, plus rare CJK ideographs in the supplementary planes — is rejected or truncated. The fix is utf8mb4. Note that VARCHAR(n) counts characters, but index key limits are counted in bytes, so the same n costs more with utf8mb4.
Truncating by bytes is the other classic bug. Cut an accented Spanish or French string at an arbitrary byte and you can split a C3 from its A9; the orphan byte is invalid and gets displayed as U+FFFD (�). Use the cumulative byte counts here to find a safe cut point, or truncate by code point in your code instead.
Finding invisible characters
Space is shown as ␣, tab and line breaks as \t, \n and \r, and other control characters as labels like \x1B. Unicode spaces that would otherwise look blank get labels too: U+00A0 NO-BREAK SPACE (C2 A0) shows as [NBSP], U+200B ZERO WIDTH SPACE (E2 80 8B) as [ZWSP], U+FEFF, the byte order mark (EF BB BF), as [BOM] and U+3000 IDEOGRAPHIC SPACE (E3 80 80) as [IDSP]; ZWJ, ZWNJ, WJ and the soft hyphen are labelled the same way. If a pasted value refuses to match in a search, a spreadsheet lookup or a password field, look for [NBSP], [ZWSP] or [BOM].
Worked examples
Why a short string overflows a byte limit
- Input
Olé 😀- Output
5 characters, 9 bytes — 4F 6C C3 A9 20 F0 9F 98 80
O, l and the space are one byte each, é is two, the emoji is four: 1+1+2+1+4 = 9. JavaScript's length reports 6 because the emoji is two UTF-16 units. A field limited to 8 bytes would reject this five-character string.
Two strings that look identical
- Input
café typed on a keyboard vs. café pasted from a macOS filename- Output
First: 63 61 66 C3 A9 (4 rows, 5 bytes). Second: 63 61 66 65 CC 81 (5 rows, 6 bytes)
The second one is decomposed (NFD). Normalize both to NFC — in JavaScript, str.normalize("NFC") — before comparing or using them as keys.
A non-breaking space from a web page
- Input
10 kg (copied from a product page)- Output
The row between 0 and k is C2 A0 — U+00A0
Regex \s matches it in JavaScript, but split(" ") and many spreadsheet functions do not treat it as a space.
How to use it
- Type or paste your text.
- Read each row: the character, its U+ code point and its UTF-8 bytes.
- Check the totals at the top for code points and bytes.
- Copy the hex dump if you need to compare against another system's bytes.
Key terms
- Code point
- The number Unicode assigns to a character, from U+0000 to U+10FFFF.
- Code unit
- The smallest unit an encoding works in: one byte in UTF-8, two bytes in UTF-16.
- Surrogate pair
- Two UTF-16 code units (D800–DBFF then DC00–DFFF) that together represent one code point above U+FFFF.
- NFC / NFD
- Unicode normalization forms: composed (é as one code point) versus decomposed (e + combining accent).
Frequently asked questions
How many bytes is an emoji in UTF-8?
A single-code-point emoji above U+FFFF is four bytes. Older symbols such as ☺ (U+263A) are three. Sequences with skin tones, ZWJ joins or flags are several code points and commonly run 8 to 25+ bytes.
Why does JavaScript say my string is longer than this tool does?
length counts UTF-16 code units, so every character above U+FFFF counts as 2. [...str].length counts code points and will match this tool.
Does the tool count grapheme clusters?
No, it counts code points, so the family emoji is 5, not 1. A grapheme-aware counter (Intl.Segmenter in modern browsers) would give 1.
Can it show Latin-1 or UTF-16 bytes?
No, only UTF-8. For UTF-16 code units, the Unicode escape converter shows them as \uXXXX.
What does a BOM look like here?
One row for U+FEFF with bytes EF BB BF, labelled [BOM] in the character cell.
Related guides
Sources
- RFC 3629: UTF-8, a transformation format of ISO 10646
- Unicode FAQ: UTF-8, UTF-16, UTF-32 & BOM
- Unicode Standard Annex #15: Unicode Normalization Forms
- MySQL 8.0 Reference Manual: The utf8mb4 Character Set
Last reviewed: