Base64 записывает любые байты обычным текстом из 64 символов: латинских букв A–Z и a–z, цифр 0–9, знаков + и /. Ещё есть знак =, им добивают конец строки. Каждые три байта превращаются в четыре символа, поэтому данные вырастают примерно на треть.
Закодировать строку можно одной командой: btoa() в браузере, модуль base64 в Python, утилита base64 в терминале macOS и Linux. Ниже разберём алгоритм на примере, рабочий код для JavaScript и Python и ошибки, на которых чаще всего ломаются.
Важно с самого начала: Base64 не шифрует. Любой, кто видит строку, раскодирует её за секунду.
Что такое Base64 и где он нужен

Многие форматы и протоколы рассчитаны на текст. Письмо, JSON, адрес страницы, атрибут в HTML: туда нельзя просто положить байты картинки или архива, часть из них окажется управляющими символами и сломает разбор. Base64 переводит такие байты в безопасный набор символов, а на другой стороне их восстанавливают без потерь.
Где кодировка встречается чаще всего:
- Вложения в письмах. Почтовый стандарт MIME (RFC 2045) описывает передачу файлов в Base64 и требует, чтобы строки были не длиннее 76 символов.
- Картинки прямо в HTML и CSS. Схема
data:вставляет файл в код страницы:data:text/plain;base64,SGVsbG8sIFdvcmxkIQ==(MDN). - Файлы в запросах к API. В JSON нет типа «байты», поэтому изображение или PDF кладут в поле строкой Base64.
- Заголовок авторизации. В схеме Basic логин и пароль склеиваются через двоеточие и кодируются в Base64 (RFC 7617):
Authorization: Basic QWxhZGRpbjpvcGVuIHNlc2FtZQ==. - Токены JWT. Три части токена записаны вариантом Base64url, о нём ниже.
Base64 прячет текст от беглого взгляда, но не защищает его. Стандарт RFC 4648 прямо пишет в разделе о безопасности, что такая кодировка не даёт никакой вычислительной конфиденциальности.
Если нужно, чтобы посторонний не прочитал данные, нужен ключ и настоящий шифр. Чем шифр отличается от кодировки, удобно посмотреть на простом примере вроде шифра Цезаря: там без знания сдвига текст уже не прочитать сразу, а Base64 раскодирует любой онлайн-конвертер.
Как работает кодирование Base64

Алгоритм удобно разобрать на слове Man. Его три буквы занимают три байта, то есть 24 бита. Base64 делит эти 24 бита на четыре группы по 6 бит, а 6 бит дают ровно 64 варианта, отсюда и название.
- Берём коды символов: M = 77, a = 97, n = 110.
- Записываем их в двоичном виде подряд:
01001101 01100001 01101110. - Режем ту же цепочку по 6 бит:
010011 010110 000101 101110. - Переводим группы в числа: 19, 22, 5, 46.
- Находим символы по таблице алфавита: 19 → T, 22 → W, 5 → F, 46 → u.
Получилось TWFu. Python выдаёт то же самое: base64.b64encode(b"Man") возвращает b'TWFu'.
Таблица символов Base64
Алфавит устроен по порядку, поэтому его не нужно заучивать целиком:
| Значение | Символы | В варианте Base64url |
|---|---|---|
| 0–25 | A–Z | A–Z |
| 26–51 | a–z | a–z |
| 52–61 | 0–9 | 0–9 |
| 62 | + | — |
| 63 | / | _ |
| выравнивание | = | = или без него |
Откуда берутся знаки = в конце
Если длина данных не делится на три, последней группе не хватает байтов. Тогда недостающее место помечают знаком =: один байт в хвосте даёт два знака, два байта дают один. Вот контрольные примеры из раздела 10 того же стандарта, мы прогнали их через Python, совпадение полное:
| Исходная строка | Base64 |
|---|---|
| f | Zg== |
| fo | Zm8= |
| foo | Zm9v |
| foob | Zm9vYg== |
| fooba | Zm9vYmE= |
| foobar | Zm9vYmFy |
Из этого же правила видно, насколько вырастет файл. Три байта всегда превращаются в четыре символа, так что прирост около 33 %: фрагмент программы размером 3 000 байт у нас превратился в строку из 4 000 символов. В письмах добавляются ещё переводы строк через каждые 76 символов.
Из-за этого прироста через data: в HTML и CSS имеет смысл встраивать мелкие иконки. Крупную фотографию выгоднее подключить отдельным файлом.
Base64 в JavaScript: btoa, atob и кириллица
В браузере есть две встроенные функции: btoa() кодирует, atob() раскодирует. С латиницей они работают сразу:
btoa("Hello"); // "SGVsbG8="
atob("SGVsbG8="); // "Hello"
На кириллице btoa() падает. Функция принимает только символы, которые помещаются в один байт, а русская буква в UTF-8 занимает два. В Chrome это выглядит так:
btoa("Привет");
// InvalidCharacterError: Failed to execute 'btoa' on 'Window':
// The string to be encoded contains characters outside of the Latin1 range.
Самым простым решением MDN называет такое: сначала перевести строку в байты UTF-8 через TextEncoder, а при раскодировании собрать её обратно через TextDecoder.
const bytes = new TextEncoder().encode("Привет");
let bin = "";
for (const b of bytes) bin += String.fromCharCode(b);
btoa(bin); // "0J/RgNC40LLQtdGC"
const back = Uint8Array.from(atob("0J/RgNC40LLQtdGC"), c => c.charCodeAt(0));
new TextDecoder().decode(back); // "Привет"
Новый способ: toBase64 и fromBase64
У массивов байтов Uint8Array появились собственные методы, и цикл стал не нужен. По данным MDN, они работают в актуальных версиях всех основных браузеров с сентября 2025 года, но в старых браузерах их может не быть.
new TextEncoder().encode("Привет").toBase64(); // "0J/RgNC40LLQtdGC"
Uint8Array.fromBase64("0J/RgNC40LLQtdGC"); // байты строки «Привет»
new Uint8Array([251, 255, 254]).toBase64({ alphabet: "base64url" }); // "-__-"
Node.js: Buffer
На сервере привычнее работать через Buffer, он сразу понимает UTF-8:
Buffer.from("Привет", "utf8").toString("base64"); // "0J/RgNC40LLQtdGC"
Buffer.from("0J/RgNC40LLQtdGC", "base64").toString("utf8"); // "Привет"
Все примеры этого раздела мы запустили в Node.js 25 и в Chrome 152, вывод в комментариях взят из консоли.
Base64 в Python
В Python за кодировку отвечает стандартный модуль base64, ставить ничего не нужно. Функции работают с байтами, поэтому строку перед кодированием переводят через .encode("utf-8"):
import base64
code = base64.b64encode("Привет".encode("utf-8"))
print(code) # b'0J/RgNC40LLQtdGC'
print(base64.b64decode(code).decode("utf-8")) # Привет
Если вы раньше не запускали код на Python, сначала посмотрите первые простые примеры, а потом возвращайтесь сюда.
Для адресов и имён файлов есть urlsafe_b64encode(). По документации Python, она подставляет - вместо + и _ вместо /:
raw = bytes([251, 255, 254])
print(base64.b64encode(raw)) # b'+//+'
print(base64.urlsafe_b64encode(raw)) # b'-__-'
Если файл нужно отправить письмом, подойдёт base64.encodebytes(): она сама вставляет перевод строки после каждых 76 символов, как требует MIME. Проверяли в Python 3.14.
Как закодировать в Base64 в терминале
В macOS и Linux утилита base64 уже установлена. Кодировать удобно так:
printf 'Привет' | base64 # 0J/RgNC40LLQtdGC
echo '0J/RgNC40LLQtdGC' | base64 -d # Привет
Обратите внимание на printf. Команда echo добавляет в конец перевод строки, и он тоже попадает в результат:
echo 'Hello' | base64 # SGVsbG8K (закодирован и перевод строки)
printf 'Hello' | base64 # SGVsbG8=
Чтобы закодировать файл целиком, в macOS пишут base64 -i файл -o результат.txt. В Linux (GNU coreutils) достаточно base64 файл, но вывод там по умолчанию режется на строки по 76 символов. Одной строкой его отдаст флаг -w 0.
Чем Base64url отличается от обычного Base64
В адресе страницы знаки + и / имеют своё значение: плюс в параметрах читается как пробел, а косая черта делит путь. Поэтому для ссылок, имён файлов и токенов придумали вариант с другими двумя символами (раздел 5 стандарта).
| Что сравниваем | Base64 | Base64url |
|---|---|---|
| 62-й и 63-й символы | + и / | — и _ |
| Знак = в конце | ставится | часто опускают |
| Где встречается | письма, data:, JSON | ссылки, имена файлов, JWT |
| Пример для байтов 251, 255, 254 | +//+ | -__- |
В JWT знаков = в конце нет: стандарт RFC 7515 описывает Base64url без знаков = в конце и без переводов строк. Если такую часть токена нужно разобрать обычным декодером, знаки = сначала придётся вернуть.
Как раскодировать Base64 и понять, что внутри
Строку Base64 обычно видно сразу. В ней только латиница, цифры, + и /, длина делится на четыре, а в конце часто стоят один или два знака =. Раскодировать такую строку можно тремя способами, выбирайте по тому, что у вас открыто.
- Консоль браузера (F12 → Console):
atob("SGVsbG8="). Подходит для латиницы, для кириллицы нужен код сTextDecoderиз раздела выше. - Терминал macOS и Linux:
echo 'SGVsbG8=' | base64 -d. - Python из командной строки, без единой строчки кода:
echo '0J/RgNC40LLQtdGC' | python3 -m base64 -dвыведет «Привет». Нужен только установленный Python.
Как узнать файл по первым символам
Иногда в Base64 лежит не текст, а файл: картинка в JSON, вложение из письма, документ из API. Тип часто видно ещё до раскодирования, потому что у форматов постоянное начало, и в Base64 оно тоже даёт постоянные символы. Мы закодировали стандартные сигнатуры форматов и получили вот что:
| Строка начинается с | Скорее всего это |
|---|---|
| iVBORw0KGgo | картинка PNG |
| /9j/ | картинка JPEG |
| R0lGODlh | анимация GIF |
| JVBERi0 | документ PDF |
| UEsDB | архив ZIP, а также файлы DOCX и XLSX, которые внутри устроены как ZIP |
Такую строку не печатают как текст, а сохраняют в файл: base64 -d -i data.txt -o picture.png в macOS или base64 -d data.txt > picture.png в Linux.
И совет из практики: строки с токенами, паролями и личными данными не вставляйте в онлайн-декодеры. Консоль браузера и терминал справятся не хуже, а данные останутся у вас.
Частые ошибки при работе с Base64

Почти все проблемы сводятся к двум вещам: путаница байтов и символов и испорченный хвост строки.
| Что видите | Причина | Что сделать |
|---|---|---|
InvalidCharacterError в btoa() |
в строке кириллица или эмодзи | перевести строку в UTF-8 через TextEncoder или взять toBase64() |
После atob() вместо текста набор вроде «ÐÑивеѻ |
байты UTF-8 прочитаны как отдельные символы | собрать Uint8Array и раскодировать TextDecoder |
binascii.Error: Incorrect padding в Python |
потерялись знаки =, например строка пришла из JWT или ссылки |
дописать =, пока длина не станет кратна четырём |
Строка из терминала кончается на K, o= или Cg== |
echo добавил перевод строки |
кодировать через printf или echo -n |
| Сервер получил строку с пробелами вместо плюсов | обычный Base64 вставили в параметр ссылки | использовать Base64url или encodeURIComponent() |
Отдельно про безопасность. Пароль, ключ API или персональные данные в Base64 остаются открытыми: заголовок Basic, по словам самого RFC 7617, передаёт логин и пароль открытым текстом. Такие запросы отправляют только по HTTPS, а секреты в коде и конфигах хранят отдельно.
Как устроены сами запросы и заголовки, мы разбирали в статьях про методы HTTP и сетевые протоколы.
Где освоить JavaScript системно
Если Base64 понадобился впервые, скорее всего, вы как раз дошли до загрузки файлов, запросов к API или авторизации. Это базовые темы курсов по JavaScript, и там их разбирают на практических заданиях.
Ниже курсы по JavaScript с рейтингом и отзывами учеников, полный список на странице курсов JavaScript.
| Курс | Школа | Стоимость со скидкой | В рассрочку | Длительность | Обзор курса от Checkroi |
|---|---|---|---|---|---|
| JavaScript Перейти на сайт курса | 63 829 ₽ | 4086 ₽/мес. | 3 месяца | Обзор курса | |
| Fullstack разработчик JavaScript Перейти на сайт курса | 75 000 ₽ | 20 000 ₽/мес. | 6 месяцев | Обзор курса | |
| Факультет fullstack JavaScript Перейти на сайт курса | 134 700 ₽ | 3742 ₽/мес. | 15 месяцев | Обзор курса | |
| Fullstack-разработчик на Node.js Перейти на сайт курса | 109 000 ₽ | 6137 ₽/мес. | 12 месяцев | Обзор курса | |
| Fullstack-разработчик на JavaScript Перейти на сайт курса | 158 760 ₽ | 6615 ₽/мес. | 11 месяцев | Обзор курса |
Больше программ — в полном каталоге курсов по JavaScript




