ByteTips.

Guide

How to Encode Text to Base64

Base64 looks like encryption, but it is not. Learn how the encoding works, how to do it safely in JavaScript, and when to reach for it.

October 14, 2026 · 4 min read · Shayan

Paste a long string of letters, numbers, plus signs, and slashes into a chat window and a developer will recognize it instantly: Base64. It shows up in data URIs, email attachments, API tokens, and config files. It looks like encryption, but it is not — anyone can decode it in seconds. Base64 is simply a way to represent binary data as plain text, so bytes can travel through systems that only handle text. Once you understand the encoding, you will recognize it everywhere and stop treating it as security.

What Base64 is — and is not

Base64 takes any bytes — text, an image, a PDF — and encodes them using only 64 safe characters: A–Z, a–z, 0–9, plus + and /. The result is plain ASCII text with no control characters, no null bytes, and nothing that breaks a JSON field, a URL parameter, or an email body. What Base64 does not do is hide anything. There is no key, no secret, no password. Decoding is a one-liner in every language. Never use Base64 to protect a secret: it is wrapping paper, not a lock. If you need secrecy, encrypt; if you need to move bytes through a text-only channel, encode.

How it works: 3 bytes become 4 characters

The math is simple. Every three bytes (24 bits) are split into four groups of 6 bits, and each 6-bit group maps to one of the 64 characters. Three bytes in, four characters out — which is why Base64 output is about a third larger than the input. When the input is not a multiple of three bytes, padding with = fills the gap: one = means the last group held two bytes, two = means it held one. That is why so many Base64 strings end in = or ==. You can see the structure yourself:

"Man"  ->  "TWFu"       (3 bytes -> 4 chars, no padding)
"Ma"   ->  "TWE="       (2 bytes -> 3 chars + 1 pad)
"M"    ->  "TQ=="       (1 byte  -> 2 chars + 2 pads)

Base64 in JavaScript: btoa, atob, and the Unicode trap

JavaScript has built-in Base64 functions, but they come with a famous gotcha: btoa only handles Latin-1 characters. Feed it an emoji or non-English text and it throws. The fix is to convert the string to UTF-8 bytes first, then encode:

// Safe Base64 encode/decode for any Unicode text
function toBase64(str) {
  return btoa(String.fromCodePoint(...new TextEncoder().encode(str)));
}
function fromBase64(b64) {
  return new TextDecoder().decode(
    Uint8Array.from(atob(b64), (c) => c.charCodeAt(0))
  );
}

toBase64("héllo 🌍"); // "aMOpbGxvIPCfjI0="
fromBase64("aMOpbGxvIPCfjI0="); // "héllo 🌍"

For quick one-offs you do not need code at all — an encoder tool does the same thing instantly, including the UTF-8 handling.

Base64URL: the variant used by JWTs and URLs

Base64 has one weakness: + and / are special characters in URLs, and = padding confuses query strings. Base64URL fixes this by swapping + for -, / for _, and dropping the padding. The result is safe to paste into a URL unchanged. This is the variant JWTs use — every token you have seen is three Base64URL segments joined by dots. Converting between the two is a string replace plus adding or removing padding, and most encoder tools offer both variants.

When to use it

Reach for Base64 when:

  • Embedding small images or fonts directly in CSS or HTML as data URIs.
  • Sending binary data through JSON APIs that only accept text.
  • HTTP Basic Authentication, which sends username:password as Base64.
  • Email attachments (MIME), the oldest everyday use of Base64.
  • Storing binary blobs in config files or databases that expect text.

Try it

Encode or decode any text with the URL & Base64 Encoder — it handles URL encoding and Base64 side by side, all locally. For images, the Image to Base64 tool turns any picture into a data URI you can paste straight into CSS or HTML. And since JWTs are built on Base64URL, What Is a JWT? How to Decode One Safely shows where this encoding matters most in real systems.

More guides