В кодировке UTF-8 базовая латинская буква без диакритики, цифра от 0 до 9 или обычный пробел занимают 1 байт, на русскую букву уходит 2 байта, на некоторые знаки вроде № по 3, а на простой эмодзи вроде 😀 по 4. Составные эмодзи занимают больше. Поэтому размер текста в байтах почти всегда больше числа символов, а русский текст весит примерно вдвое больше латинского той же длины.
Это важно учитывать, когда лимит для поля в базе данных, для формы или для файла задан в байтах, а не в символах.
Диапазоны UTF-8 по стандарту RFC 3629
Сколько байт займёт символ в UTF-8, зависит от его номера в Unicode, то есть от кодовой точки. Стандарт RFC 3629 делит все кодовые точки на четыре диапазона.
| Диапазон кодовых точек | Байт в UTF-8 |
|---|---|
| от U+0000 до U+007F | 1 |
| от U+0080 до U+07FF | 2 |
| от U+0800 до U+FFFF | 3 |
| от U+10000 до U+10FFFF | 4 |
Базовая латиница без диакритики (символы ASCII), цифры, обычный пробел и основные знаки препинания попадают в первый диапазон. Латинская é уже во втором и занимает 2 байта. Русские буквы находятся во втором (у строчной «а» номер U+0430, у заглавной «А» номер U+0410), поэтому каждая из них занимает 2 байта. Знак № имеет номер U+2116 и относится к третьему диапазону, поэтому занимает 3 байта. Эмодзи вроде 😀 находятся в четвёртом и занимают по 4 байта. Но многие эмодзи состоят из нескольких кодовых точек. В нашей проверке ❤️ занял 6 байт, флаг 🇷🇺 занял 8, а 👩💻 занял 11. Значения от U+D800 до U+DFFF в третьем диапазоне зарезервированы для UTF-16 и в UTF-8 как отдельные символы не кодируются.
Сколько байт занимают русские слова и знаки
Русское слово в UTF-8 занимает вдвое больше байт, чем в нём букв, а каждый обычный пробел, цифра, точка или запятая добавляет ещё 1 байт. Типографские знаки весят больше, например кавычки «» занимают по 2 байта, а длинное тире 3. 29 октября 2026 года мы измерили несколько строк в Python 3.13. Символом здесь считается одна кодовая точка.
| Текст | Символов | Байт в UTF-8 |
|---|---|---|
| Hello | 5 | 5 |
| Привет | 6 | 12 |
| Ёлка | 4 | 8 |
| Москва 2026 | 11 | 17 |
| Привет, мир! | 12 | 21 |
| № | 1 | 3 |
| 😀 | 1 | 4 |
Слово «Привет» из 6 букв даёт 12 байт, по 2 на букву. В строке «Москва 2026» шесть русских букв дают 12 байт, пробел и четыре цифры добавляют ещё 5, всего 17. В «Привет, мир!» запятая, пробел и восклицательный знак занимают по 1 байту, поэтому выходит 21 байт, а не 24.
Почему число символов и число байт расходятся
Число кодовых точек обычно совпадает с числом знаков, которые вы видите, но не всегда, ведь один видимый знак может состоять из нескольких кодовых точек. Число байт показывает размер текста после кодирования в UTF-8. Объём в памяти программы и размер сохранённого файла могут быть другими. В UTF-8 один символ занимает от 1 до 4 байт, поэтому эти два числа совпадают только в тексте, где есть лишь латиница, цифры и простые знаки.
Есть и менее очевидная причина. Буква, которая выглядит одинаково, может быть записана двумя способами. Стандарт Unicode описывает это в документе о формах нормализации UAX #15, где определены составная форма NFC и разложенная форма NFD. В русском языке это касается букв «й» и «ё».
| Запись | Кодовых точек | Байт в UTF-8 | Байты |
|---|---|---|---|
| й одной кодовой точкой (U+0439, NFC) | 1 | 2 | D0 B9 |
| й в разложенном виде (и + U+0306, NFD) | 2 | 4 | D0 B8 CC 86 |
| ё одной кодовой точкой (U+0451) | 1 | 2 | D1 91 |
| ё в разложенном виде (е + U+0308) | 2 | 4 | D0 B5 CC 88 |
В составной форме буква «й» записывается одной кодовой точкой и занимает 2 байта. В разложенной форме она хранится как буква «и» и отдельный надстрочный знак, то есть как две кодовые точки и 4 байта. С буквой «ё» происходит то же самое. Обычно на экране разницы нет, но счётчик кодовых точек покажет 2 вместо 1, а размер в байтах удвоится. Такая запись иногда встречается в тексте, скопированном из некоторых источников. Если слово с «й» или «ё» весит больше, чем вы рассчитывали, проверьте, не в этом ли дело.
Байты русских букв в шестнадцатеричном виде
Каждая русская буква в UTF-8 записывается двумя байтами, и в таблице ниже первый из них всегда D0 или D1. Значения мы посчитали в Python 3.13 в тот же день, 29 октября 2026 года.
| Буква | Кодовая точка | Байты UTF-8 | Байт |
|---|---|---|---|
| а | U+0430 | D0 B0 | 2 |
| ё | U+0451 | D1 91 | 2 |
| щ | U+0449 | D1 89 | 2 |
| ъ | U+044A | D1 8A | 2 |
| ы | U+044B | D1 8B | 2 |
| э | U+044D | D1 8D | 2 |
Именно эти пары байтов превращаются в кракозябры, если программа прочитает их не в той кодировке. Подробнее об этом ниже.
UTF-8, UTF-16 и Windows-1251 на одном примере
Фраза «Привет, мир» из 11 символов занимает 20 байт в UTF-8, 22 байта в UTF-16 и 11 байт в Windows-1251. Если файл UTF-16 сохранён с двухбайтовой меткой порядка байтов (BOM), выйдет 24 байта.
| Кодировка | Как считаются байты | «Привет, мир» |
|---|---|---|
| UTF-8 | от 1 до 4 байт на символ, русская буква занимает 2 байта | 20 байт |
| UTF-16 | 2 байта на символ до U+10000, 4 байта выше | 22 байта (без BOM) |
| Windows-1251 | 1 байт на символ | 11 байт |
Правило для UTF-16 описано в RFC 2781. Символ с номером меньше U+10000 кодируется одним 16-битным числом, то есть 2 байтами, а символ с бо́льшим номером, например эмодзи, записывается парой таких чисел и занимает 4 байта. Все русские буквы и знаки препинания из примера укладываются в 2 байта каждый.
Windows-1251 устроена проще. В таблице соответствия от Unicode Consortium почти каждому байту от 0x00 до 0xFF сопоставлен один символ, только значение 0x98 помечено как неопределённое. Например, 0xC0 означает «А», 0xE0 означает «а», а 0xA8 означает «Ё». Поэтому русская буква здесь занимает 1 байт, но набор символов ограничен этой таблицей.
Школьная формула I = K × i и UTF-8
Формула I = K × i, где K обозначает число символов, а i обозначает число бит на символ, работает только для кодировок, в которых все символы одинаковой длины. В Windows-1251 i равно 8 битам, и для «Привет, мир» получается 11 × 8 = 88 бит, то есть 11 байт.
В UTF-8 длина символа переменная, поэтому единого i для всего текста нет и байты приходится складывать символ за символом. В «Привет, мир» девять русских букв дают 18 байт, запятая и пробел добавляют ещё 2, всего 20 байт, или 160 бит. Если подставить в формулу i = 8, выйдет 11 байт, а при i = 16 получится 22 байта; для UTF-8 оба ответа неверны. А вот для UTF-16 формула с i = 16 к этой фразе подходит, потому что в ней нет символов выше U+FFFF.
Сколько русского текста помещается в лимит в байтах
В лимит, заданный в байтах, русского текста помещается примерно вдвое меньше символов, чем латинского. Возьмём вымышленный пример. Допустим, поле принимает не больше 160 байт (число взято наугад и не относится ни к какой конкретной платформе). Текст только из латиницы, цифр и пробелов поместится целиком, если в нём не больше 160 символов. Русский текст занимает по 2 байта на букву, поэтому символов влезет примерно вдвое меньше. Пробелы, цифры и простые знаки вроде запятой или точки весят по 1 байту, так что на практике поместится чуть больше половины.
- Измерьте текст в байтах, а не в символах.
- Сравните результат с лимитом поля.
- Если текст не помещается, сокращайте его. Каждая убранная русская буква освобождает 2 байта, а каждый пробел или цифра освобождает 1 байт.
- После правки измерьте ещё раз, особенно если текст скопирован из другого источника и в нём могут оказаться разложенные «й» и «ё».
Почему вместо русских букв появляются кракозябры
Чаще всего кракозябры появляются, когда байты UTF-8 читаются в однобайтовой кодировке и программа показывает каждую русскую букву как два посторонних символа. Если прочитать байты фразы «Привет, мир» из UTF-8 как Windows-1251, получится «РџСЂРёРІРµС‚, РјРёСЂ». Запятая и пробел занимают по 1 байту и остаются на месте, а вместо каждой буквы появляется пара знаков.
| Буква | Байты UTF-8 | Как выглядит при чтении в Windows-1251 |
|---|---|---|
| а | D0 B0 | Р° |
| ё | D1 91 | С‘ |
| щ | D1 89 | С‰ |
| ы | D1 8B | С‹ |
| э | D1 8D | СЌ |
Сами байты при этом не повреждены. Если открыть файл в кодировке UTF-8, текст, как правило, снова отображается правильно. Конкретный вид кракозябр зависит от того, в какой кодировке прочитаны байты. Примеры выше посчитаны только для Windows-1251.
Как измерить размер текста в калькуляторе Digily Link
Откройте «Калькулятор размера текста», вставьте или наберите текст в поле «Текст», и значение в поле «Размер» сразу обновится. Калькулятор входит в Digily Link, наш собственный продукт.
- Откройте страницу калькулятора в браузере.
- Вставьте текст в поле «Текст». Нажимать кнопку не нужно, размер пересчитывается при каждом изменении.
- Посмотрите значение в поле «Размер».
Расчёт выполняется прямо в браузере, для вычисления текст не отправляется на сервер, а нормализация NFC или NFD перед измерением не применяется. Калькулятор считает байты в UTF-8. Единицы двоичные, то есть 1 KB здесь равен 1024 байтам (по стандарту такую единицу обозначают KiB), а результат округляется до двух знаков после запятой. Поэтому, например, 1025 и 1026 байт оба отобразятся как 1.00 KB, и для точной проверки лимита больше 1024 байт этой точности может не хватить. Ровно 1024 байта отображаются как «1024 B», начиная с 1025 байт результат показывается в KB, а дальше идут MB, GB и TB.
Если нужно проверить лимит поля или сравнить два варианта формулировки, измерьте размер своего текста в байтах в калькуляторе.
Что калькулятор размера текста не учитывает
Калькулятор показывает размер текста в UTF-8, и в другой кодировке результат может быть иным. Если файл сохранён, например, в Windows-1251, его размер на диске может отличаться от того, что калькулятор покажет для того же текста. Для текста только из символов ASCII размер совпадёт, а файл UTF-8 с меткой BOM будет на 3 байта больше. Переносы строк тоже входят в результат. Разложенные буквы «й» и «ё» калькулятор считает как есть, по 4 байта, потому что текст перед измерением не меняется.