What is Base64? Encoding, not encryption

Base64 hides nothing. It turns any data into letters, digits and a few symbols so it can travel through systems that only handle text, and anyone can undo it in a second. It is worth understanding anyway: it shows up in emails, tokens and URLs, and the bugs it causes are always the same ones.

Reviewed on 3 October 2026 · 4 min read

What Base64 does

RFC 4648 defines Base64 as a way to represent arbitrary sequences of bytes in a form that allows both upper- and lowercase letters but need not be human readable. It uses a 65-character subset of US-ASCII: 64 characters to carry data (A–Z, a–z, 0–9, + and /), enough to represent 6 bits each, plus = for padding.

The process takes the input three bytes at a time (24 bits), splits them into four groups of 6 bits and turns each into one character. That is the whole idea, and it explains the two facts everyone should know: the output is made only of printable characters, and it is about a third larger than the input, because 3 bytes become 4 characters. Ten bytes become 16 characters, 1,000 bytes become 1,336, and 3 MB become 4 MB.

A short example: the text Ana:clave encodes to QW5hOmNsYXZl. Paste that into the Base64 encoder and decoder and you get the original back, which is exactly the point.

It is not encryption

This is the misunderstanding with consequences. Base64 has no key and no secret: decoding is a mechanical step that anybody can do. It is used to make data transportable, not private. If a password, a token or a document is "protected" only by Base64, it is not protected.

The HTTP "Basic" authentication scheme shows how this plays out. It sends the user name and password joined by a colon and encoded with Base64. RFC 7617 states plainly that the scheme is not a secure method of user authentication unless used with something like TLS, because the user ID and password are passed over the network as cleartext. Base64 there is just a convenient wrapper, and the security comes (or does not come) from HTTPS. The same applies to the payload of a JWT, which is base64url-encoded and readable by anyone holding the token (see how to read a JWT).

Where you will see it

  • Email attachments. Email was built for text; files are Base64-encoded (MIME) to travel inside a message. This is one reason an attachment adds roughly a third to the size on the wire.
  • Data URIs. Small images embedded directly in HTML or CSS look like data:image/png;base64,iVBOR…. Convenient for tiny icons, wasteful for big images because of the extra third and because they cannot be cached separately.
  • JSON and APIs. JSON has no binary type, so files and keys are often sent as Base64 strings.
  • Tokens and keys. JWTs, certificates in PEM format and many API keys use Base64 or its URL-safe variant.

The padding: why there is sometimes an =

Input comes in groups of three bytes. When the last group has only one or two bytes, the output is padded with = signs so its length is a multiple of 4: one leftover byte gives two =, two leftover bytes give one. The padding carries no information; it just tells the decoder how many bytes the last group held. RFC 4648 notes that when the length of the data is known in advance, padding can be omitted, which is what base64url usually does.

Base64url: the URL-safe variant

The characters + and / have special meaning in URLs and file names. RFC 4648 section 5 defines a variant that replaces them with - and _, and says it should be referred to as "base64url" rather than just "base64". JWTs use it. Mixing them up is a common source of decode errors: a base64url string fed to a plain decoder fails as soon as it hits a - or _. For example, the three bytes 251, 255, 254 encode as +//+ in Base64 and as -__- in base64url.

The accents problem (btoa and atob)

Base64 encodes bytes, not text, so how text becomes bytes matters. In browsers, btoa() treats each character as one byte, which only works for code points below 256. MDN documents that passing a character that does not fit in a byte throws an InvalidCharacterError (try btoa("€")). And even when it does not throw, you may get a different result from other tools: btoa("Mañana") gives TWHxYW5h, because the "ñ" is treated as the single byte 0xF1, while a UTF-8 encoder gives TWHDsWFuYQ==, with "ñ" as two bytes. When you exchange Base64 text with other systems, the right choice is almost always to convert the text to UTF-8 bytes first, then encode. The tool above does that.

Common decoding errors

  • Invalid character or length: spaces, line breaks or a missing character from copy and paste. Some decoders tolerate whitespace, others do not.
  • Wrong alphabet: a URL-safe string (-, _) sent to a standard decoder, or the reverse.
  • Missing padding: some decoders insist on the = signs; add them until the length is a multiple of 4.
  • Garbled text after decoding: the bytes were decoded correctly but read with the wrong character set. If the original was UTF-8, read it as UTF-8.

Sources and further reading

Figures checked on 3 October 2026.

Do it now, free, in your browser. Your files are not uploaded.

Convert text, files and images to and from Base64, in your browser.

Frequently asked questions

Is Base64 encryption?
No. It is a reversible encoding with no key. Anyone can decode it, so it gives no protection to passwords or other secrets.
Why is Base64 output bigger than the input?
Because every 3 bytes of input become 4 characters, so the output is about a third (33%) larger, plus a little padding.
What does the = at the end mean?
Padding, so the length is a multiple of 4. One missing byte in the last group gives two = signs, two missing bytes give one. It carries no data.
What is the difference between Base64 and Base64url?
Base64url replaces + and / with - and _ so the text is safe in URLs and file names, and usually omits the padding. JWTs use it.
Why does btoa() fail with accented characters or the euro sign?
btoa() only accepts characters that fit in one byte. Characters like the euro sign throw an InvalidCharacterError, and others such as ñ are encoded differently from UTF-8. Convert the text to UTF-8 bytes first.
Is it safe to put a password in Base64 in an HTTP header?
Only over HTTPS. Basic authentication sends the credentials encoded, not protected; RFC 7617 says it is not secure without something like TLS.