Tech
UTF-8 Byte Counter
Count how many bytes a string takes in UTF-8 and compare against UTF-16, UTF-32, and ASCII. See per-plane breakdowns, surrogate flags, and where database VARCHAR limits, tweet caps, and API tokens really land.
Count UTF-8 bytes
Counts update live in your browser. Nothing is uploaded.
Characters
0
UTF-8 bytes
0
UTF-16 bytes
0
UTF-32 bytes
0
JS string.length
0
Bytes per char
0
Encoding
ASCII
Emoji count
0
Frequently Asked Questions about the UTF-8 Byte Counter
Why is UTF-8 variable length and how many bytes does each character take?
UTF-8 was designed by Ken Thompson and Rob Pike in 1992 to encode every Unicode code point in 1 to 4 bytes, picking the shortest length that fits. Code points U+0000 to U+007F (ASCII) take 1 byte, U+0080 to U+07FF (most Latin scripts plus Greek, Cyrillic, Hebrew, Arabic) take 2 bytes, U+0800 to U+FFFF (most CJK, plus most other living scripts) take 3 bytes, and anything from U+10000 upward (emoji, historic scripts, rare CJK) takes 4 bytes. The variable length is what makes UTF-8 compact for English-heavy text while still covering every character in the Unicode standard.
Why is ASCII a subset of UTF-8?
UTF-8 encodes every code point from U+0000 to U+007F as a single byte with the exact same numeric value as ASCII. The byte 0x41 means "A" in pure ASCII and in UTF-8, so any file that contains only ASCII characters is already valid UTF-8 with no conversion needed. This is the design property that let UTF-8 spread so fast: existing English-only systems kept working, and the upgrade path for adding accented letters, emoji, or CJK was to just start emitting multi-byte sequences alongside the existing ASCII.
Why does an emoji take 4 bytes in UTF-8?
Most emoji live in the supplementary planes above U+FFFF, for example the grinning face is U+1F600 and the rocket is U+1F680. Anything above U+FFFF needs 4 UTF-8 bytes by the encoding rules, because the leading byte has to flag a 4-byte sequence and the remaining 21 bits of the code point are split across the continuation bytes. Skin tone modifiers, ZWJ-joined family emoji, and country-flag pairs are each their own code point too, so a single visual emoji like a family of four can easily run 16 to 28 bytes. The counter reports per-code-point bytes, not per-grapheme bytes.
Why does JavaScript's string.length differ from the character count?
JavaScript strings are stored as UTF-16 code units, and string.length returns the count of those units, not characters. Anything in the Basic Multilingual Plane (U+0000 to U+FFFF) is one code unit, so .length agrees with the character count. But every supplementary code point (every emoji, rare CJK character, historic script) uses a surrogate pair of two code units, which means string.length counts it as 2. The counter uses Array.from(text) or the string iterator (both yield code points) to give the true character count, while still showing the raw .length value next to it so you can spot where the gap comes from.
Where do these byte counts actually matter?
Anywhere a system measures size in bytes rather than characters. Postgres VARCHAR(n) and most database string columns count UTF-8 bytes against the limit, so VARCHAR(255) holds 255 ASCII characters but only 63 emoji. HTTP Content-Length headers, S3 object size, and most API rate-limit token budgets are byte counts. Twitter and X are a famous exception: they count weighted code points, not bytes, so an emoji costs 2 weighted characters even though it is 4 UTF-8 bytes. LLM token counts are a different unit again (subword tokens), but knowing the byte count is the first sanity check on whether a payload will fit before you ever reach for a tokenizer.