Skip to content
Developer

Base64 Encoder & Decoder

Base64 encodes arbitrary bytes as text using a 64-character alphabet, packing three bytes into four characters and growing the data by about a third. It exists so binary can pass through channels built for text. It has no key and no secret, so it is not encryption.

By Updated Runs in your browser — nothing is uploaded

Input · plain text

On this page
  1. Base64 is not encryption
  2. How the encoding works
  3. The URL-safe variant
  4. The UTF-8 problem
  5. Decoding JSON Web Tokens
  6. Where Base64 is genuinely the right tool
  7. Related encodings
  8. What this tool does not do

Base64 is not encryption

This is the most important thing on the page, so it goes first.

Base64 has no key, no secret, and no security property whatsoever. It is a reversible mapping from bytes to a 64-character alphabet, and anyone holding the encoded string can recover the original in seconds — with this page, with a command-line utility, or by eye if they have seen enough of it.

Its purpose is transport, not protection. It exists so that arbitrary bytes can pass through channels that were designed for text and would otherwise mangle them.

The failure mode this warning exists for is real and common: a password Base64-encoded in a config file, a personal record Base64-encoded in a database column, an API key Base64-encoded in a log entry. In every case the data is stored in plain text with a step that makes it slightly less obvious to a casual reader, and not at all less accessible to anyone who matters. HTTP Basic authentication is the canonical example — the header is just a username and password Base64-encoded, which is precisely why Basic auth over plain HTTP is unsafe and always was.

If you need confidentiality, you need encryption. If you need integrity, you need a signature or a MAC. Base64 provides neither.

How the encoding works

Base64 reads the input three bytes at a time. Three bytes is 24 bits, and 24 divides evenly into four groups of 6 bits. Each 6-bit group indexes into a 64-character alphabet: A–Z, then a–z, then 0–9, then two symbols.

So three bytes in, four characters out. That ratio is where the roughly 33% size increase comes from — you are spending 8 bits of character to carry 6 bits of data.

Worked example

Encoding the three characters Man:

  • ASCII values: 77, 97, 110
  • In binary: 01001101 01100001 01101110
  • Regrouped into six-bit chunks: 010011 010110 000101 101110
  • As numbers: 19, 22, 5, 46
  • Indexed into the alphabet: T, W, F, u

So Man becomes TWFu. This example is from the original MIME specification and has been the standard teaching case for thirty years.

Padding

When the input length is not a multiple of three, the final group is short, and the encoder pads it.

  • Input length ≡ 0 (mod 3): no padding
  • Input length ≡ 1 (mod 3): output ends with ==
  • Input length ≡ 2 (mod 3): output ends with =

The equals signs are not data. They tell the decoder how many bytes of the final group were real, so it does not invent one or two extra zero bytes. This is also why a Base64 string can never be exactly one character longer than a multiple of four — that length is impossible, and this tool rejects it rather than guessing.

Padding is optional in some contexts. Where the length is known by other means, as it is in a JWT, it is conventionally dropped.

The URL-safe variant

The standard alphabet's last two characters are + and /. Both are hostile to URLs.

A slash separates path segments, so a Base64 value in a URL path fragments into pieces. A plus is interpreted as an encoded space in a query string by long-standing convention, so a value round-tripped through a form comes back with spaces where plusses were.

RFC 4648 section 5 defines the base64url alphabet, which substitutes - for + and _ for / and leaves everything else identical. Padding is usually omitted, since = also needs escaping in a query string.

JSON Web Tokens use this variant throughout, as do many URL shorteners, cache keys and identifiers. The two alphabets are trivially interconvertible — this decoder accepts either without being told which.

The UTF-8 problem

The browser's built-in btoa function only accepts characters in the range 0–255. It predates Unicode being the default and it has never been fixed, because fixing it would break existing code.

That means btoa throws on é, on , and on every emoji ever defined. The failure is not subtle — it raises an exception — but it is late, because during development everything is ASCII and the first failure arrives from a customer whose name has an accent in it.

The correct approach is to convert the text to UTF-8 bytes first and Base64 those bytes. This tool does exactly that, using TextEncoder, which is why it handles any input you can type.

It matters for a second reason too. A single emoji is four UTF-8 bytes, and an accented Latin character is usually two. A string of 10 characters can easily be 25 bytes, which is why the character count and the byte count reported above are different numbers, and why length limits expressed in bytes and length limits expressed in characters are not interchangeable.

Decoding JSON Web Tokens

A JWT is three segments separated by dots: header, payload, signature. The first two are URL-safe Base64-encoded JSON.

Paste the middle segment into the decoder above and the claims come out readable. That is a useful debugging technique — and it is also a demonstration worth taking seriously.

A JWT payload is signed, not encrypted. The signature proves the token was not altered. It does nothing to hide the contents. Anyone holding the token — including the user it was issued to, and anyone who reads it out of a browser's local storage — can read every claim in it.

So never put anything confidential in a JWT payload. Internal user IDs and roles are normal; email addresses are usually acceptable; anything you would not show the user should not be there at all.

Where Base64 is genuinely the right tool

Email attachments. This is the original use case. SMTP was specified for 7-bit text, and MIME uses Base64 to move binary through it. RFC 2045 requires the encoded output to be broken into lines of at most 76 characters, which is why Base64 in an email source has newlines in it and Base64 in a URL does not.

Data URIs. A small image inlined into CSS or HTML as data:image/png;base64,... saves a round trip. It stops being worthwhile quickly — the 33% overhead plus the loss of separate caching means it is only sensible for genuinely small assets.

Binary inside JSON or XML. Neither format has a binary type, so bytes are Base64'd into a string. If a payload is mostly binary, this is a sign the format is wrong rather than a reason to encode harder.

Cryptographic material in text form. Keys, certificates and signatures are bytes that need to live in text files. PEM format is Base64 with header and footer lines around it.

Base32 uses a 26-letter-plus-digits alphabet with no case sensitivity and no easily confused characters. It is 60% larger than the input rather than 33%, and it is used where a human might read the value aloud or type it — TOTP secrets, for example.

Base16, or hex, is exactly 100% overhead and maps each byte to two characters. It is the most readable and the least efficient, which is why it is used for hashes and checksums where people compare values by eye.

Percent-encoding, the %20 style used in URLs, is not a general binary encoding at all — it escapes individual reserved characters and leaves the rest alone. It is far more compact than Base64 for mostly-ASCII text and far worse for binary.

What this tool does not do

It works with text. Encoding a file is a different job — the browser can do it, but a page that accepts file uploads invites exactly the confusion about where data goes that this page is careful to avoid.

It also does not decode binary payloads into anything meaningful. If the bytes are a PNG rather than text, the decoder says so and shows the first bytes as hex, which is usually enough to identify what you have from its magic number.

Everything runs locally, using the browser's own atob, btoa, TextEncoder and TextDecoder. No request is made with your input. The encoding rules follow RFC 4648, the line-length convention comes from RFC 2045, and the UTF-8 handling follows the WHATWG Encoding Standard — all linked below.

Common questions

Frequently asked questions

Is Base64 encryption?

No, and treating it as such is a genuine security failure rather than a pedantic distinction. Base64 is a reversible encoding with no key and no secret — anyone who sees the string can decode it in seconds, including with this page. Its purpose is to carry arbitrary bytes safely through channels that only accept text. If a password, API key or personal record is Base64 in a database or a log, it is stored in plain text with an extra step.

Why does Base64 make data bigger?

Because it packs 6 bits of information into each 8-bit character. Three bytes of input become four characters of output, so the encoded form is about 33% larger, plus padding and any line breaks. That overhead is the price of being able to send binary data through email bodies, JSON strings, XML documents and URLs without anything being mangled in transit.

What is URL-safe Base64?

A variant that swaps two characters from the standard alphabet: plus becomes minus, and slash becomes underscore. Both of the originals have special meanings in URLs — a plus can be read as an encoded space in a query string, and a slash separates path segments — so a standard Base64 value pasted into a URL can be corrupted. Padding is usually dropped too. RFC 4648 section 5 defines this variant, and JSON Web Tokens use it throughout.

What are the equals signs at the end for?

Padding. Base64 works on groups of three input bytes, and when the input length is not a multiple of three the final group is short. One or two equals signs mark how many bytes were missing, so a decoder knows not to invent them. An input whose length is a multiple of three needs no padding at all, which is why some Base64 strings end in equals signs and others do not.

Why does btoa fail on emoji and accented characters?

Because the browser’s built-in btoa only accepts characters in the range 0–255 — it predates Unicode being the default. Anything above that, including é, 中 and every emoji, throws an error. The fix is to convert the text to UTF-8 bytes first and encode those, which is what this tool does. It is why a naive implementation appears to work perfectly until the first customer with an accent in their name.

Can I decode the payload of a JWT here?

Yes, and it is a common reason to reach for a Base64 decoder. A JSON Web Token is three dot-separated URL-safe Base64 segments: header, payload and signature. Paste the middle segment with URL-safe mode on and the claims come out as readable JSON. Note what that demonstrates — a JWT payload is signed, not encrypted, so anyone holding the token can read its contents. Never put a secret in one.

What is Base64 actually used for?

Anywhere binary data has to travel through a text-only channel. Email attachments, under MIME. Images inlined into CSS or HTML as data URIs. Binary fields inside JSON and XML. HTTP Basic authentication headers, which are just a username and password Base64-encoded — again, encoded, not protected, which is why Basic auth over plain HTTP is unsafe.

References

Sources

The formulas and reference ranges on this page come from the following publications. Where a source has been revised, we cite the current edition.

  1. 1RFC 4648 — The Base16, Base32, and Base64 Data EncodingsInternet Engineering Task Force (IETF)
  2. 2RFC 2045 — MIME Part One: Format of Internet Message Bodies, section 6.8Internet Engineering Task Force (IETF)
  3. 3Encoding Standard — UTF-8 encode and decodeWHATWG

Keep going