Sizing Text in Bytes When a Character Is Not a Byte
Sooner or later a limit is expressed in kilobytes while the thing you are measuring is counted in characters. A message body, a translation catalogue, a cookie value, a column definition — each is ultimately a run of bytes, and UTF-8 does not spend the same number of bytes on every character. Converting the KB figure into a plain byte count is the first step in checking whether your text fits.
bytes = KB × 1000. A 15 KB localisation file is 15 × 1000 = 15 000 bytes. If that file is Simplified Chinese, where a typical character costs 3 bytes in UTF-8, those 15 000 bytes hold only about 5 000 characters — while the same 15 KB of plain ASCII would hold 15 000.One Sentence, Three Different Sizes
Where the Limit Really Lives
Columns Count Differently
VARCHAR(255) may mean 255 characters, but under utf8mb4 the engine must reserve up to 4 bytes each — 1 020 bytes for one column. Knowing the byte total explains index-length errors that character counts never predict.Checking a String Budget in a Few Steps
Enter the KB figure your tooling reported
Type the size your editor, build log or file listing shows for the string bundle, JSON payload or template. A comma or a dot works as the decimal separator, and spaces inside the number are ignored, so 4,5 and 4.5 both parse.
Read the byte total as you type
The byte figure updates live in the second field. This is the number to compare against a documented byte limit — a queue message cap, a header budget, or the column width you are about to declare.
Copy the bare number into a test
The copy button on each field puts the plain digits on the clipboard with no unit and no spacing, ready to paste straight into an assertion, a config value or a migration script. Pressing Ctrl+C inside a field does the same thing.
Go the other way when you start from bytes
Counting bytes first is just as common — a strlen() call gives you raw bytes. Press swap to run bytes back into kilobytes, or pick another unit from the searchable dropdown if your figure is in MB or KiB.
What Each Script Costs in UTF-8
UTF-8 is a variable-width encoding: a character occupies between one and four bytes depending on its Unicode code point. The table below shows the cost per character for the scripts you are most likely to ship, and how much text a single kilobyte therefore holds. This is why a byte budget that feels generous for an English interface can overflow the moment the same interface is localised.
| Characters | UTF-8 bytes each | Fits in 1 KB (1 000 bytes) |
|---|---|---|
| ASCII letters, digits, basic punctuation | 1 | 1 000 characters |
| Accented Latin, Greek, Cyrillic, Hebrew, Arabic | 2 | 500 characters |
| Chinese, Japanese kana and kanji, Korean, Thai, Devanagari | 3 | about 333 characters |
| Emoji and rare CJK beyond the Basic Multilingual Plane | 4 | 250 characters |
| Flag emoji (two regional-indicator code points) | 8 | 125 flags |
| Four-person family emoji joined by three ZWJ characters | 25 | 40 emoji |
A UTF-8 byte-order mark adds a fixed three bytes (EF BB BF) at the very start of a file — trivial for size, but enough to break a parser that expects the first byte to be { or a column header. Line endings matter too: switching a 2 000-line file from LF to CRLF adds exactly 2 000 bytes, or 2 KB.
Byte counts you can paste into an assertion
Each field copies as bare digits, so the value drops straight into a test expectation or a length constant without stripping units first.
Every storage unit in one searchable list
Both dropdowns list the whole range — bytes, KB, MB, KiB, MiB and the bit units — so a payload quoted in MB and a limit quoted in bytes can be compared on the same page.
Both fields accept typing
Type into either side and the other follows, which suits encoding work where you sometimes start from a file size and sometimes from a raw byte length.
Small values stay readable
Results carry up to eight decimals and only switch to scientific notation at extreme magnitudes, so a fraction of a kilobyte still reads as a normal number.
Encoding and Byte-Count Questions
Why does my 255-character name field reject a much shorter Japanese string?
Because the check is almost certainly running on bytes, not characters. Many validation layers, ORMs and legacy columns measure length with a byte-based function, so 90 Japanese characters at 3 bytes each already reach 270 bytes and trip a 255 limit. Convert your expected worst case into bytes first, then size the column and the validator against that figure rather than against a character count.
Does a UTF-8 file need a byte-order mark, and what does it cost?
UTF-8 has no byte-order ambiguity, so the mark is optional and most Unix-oriented tooling prefers it absent. It costs three bytes once per file, which never matters for size — but it does matter for parsing, because those three bytes appear before your first real character and can make a CSV header, a JSON document or a PHP file behave strangely. If a file is three bytes larger than you expected, a BOM is the usual explanation.
Why does one emoji count as two in JavaScript but four bytes on disk?
JavaScript strings are sequences of UTF-16 code units, and any code point above U+FFFF is stored as a surrogate pair — two units, which is what String.length reports. Encoded as UTF-8 on disk, the same code point takes four bytes. Neither number matches what the reader sees, since a composed emoji can be several code points joined together into one visible glyph.
My translated string file is far larger than the English source — is something wrong?
Usually not. Two effects stack: translations into German or Russian tend to run longer in character count, and each of those characters may cost two bytes instead of one. A 40 KB English catalogue growing to 70 KB in Russian is ordinary. If the growth is far larger, check whether the file was written as UTF-16, or whether an escaping step turned every accented character into a six-byte ASCII escape sequence.
Should a length limit be documented in bytes or in characters?
Document both, and state which one is enforced. Authors think in characters; storage engines, protocols and buffers enforce bytes. The safe pattern is to publish a character limit that holds in the worst case — divide the byte budget by four if emoji are allowed, by three for CJK-heavy content — and validate against the byte figure in code.
No comments yet. Be the first to comment!