Base64 encoding explained
Base64 is a binary-to-text encoding that represents bytes with a 64-character alphabet. Each complete three-byte block becomes four characters, so long inputs grow by about one third before line wrapping or other protocol overhead1.
Base64 appears in formats and protocols that need to carry bytes as text, including MIME email, data URLs, HTTP Basic authentication, JSON Web Signatures, and PEM-style certificate files.
Origins
RFC 989 described a printable encoding for Privacy Enhanced Mail (PEM) in 19872. It represented encrypted message data and signatures with characters that could pass through mail systems designed around restricted text.
Later PEM specifications retained the encoding, including RFC 1421 in 19933. RFC 2045 then defined Base64 as a MIME content-transfer encoding for email bodies in 19964. RFC 4648 documented the general-purpose Base64 and base64url alphabets in 20061.
How encoding works
The algorithm processes input in groups of three bytes — 24 bits total. Those 24 bits split into four 6-bit groups, and each group (a value from 0 to 63) indexes into the Base64 alphabet1:
- Values 0–25:
AthroughZ - Values 26–51:
athroughz - Values 52–61:
0through9 - Value 62:
+ - Value 63:
/
Plus = for padding.
The MIME alphabet uses characters represented identically in the referenced ASCII and EBCDIC variants, while excluding characters with special meaning in SMTP4.
Take "Man". ASCII values 77, 97, 110 give us 01001101 01100001 01101110 — 24 bits. Split into four 6-bit chunks: 010011 (19), 010110 (22), 000101 (5), 101110 (46). Look each up: T, W, F, u. So "Man" becomes TWFu.
Padding
When input length isn't a multiple of three, the encoder pads with zeros and appends = characters. Two remaining bytes produce three Base64 characters plus one =. One remaining byte produces two characters plus ==1.
"Ma" (two bytes) encodes to TWE=. "M" (one byte) encodes to TQ==. Padding completes the final four-character output unit and indicates whether its encoded data came from one or two input bytes. Specifications that define an unpadded profile, such as JWS, recover the final length from the unpadded data.
The 33% overhead
Every complete three-byte block produces four ASCII characters: a ratio of 4/3, or about 33.3% growth4. Short inputs can have a larger percentage increase because the final block still uses four characters.
Base16 uses two characters per input byte, while Base32 uses eight characters per five-byte block. Of the Base16, Base32, and Base64 encodings in RFC 4648, Base64 has the lowest character overhead for complete blocks1.
Where it shows up
Email (MIME) — RFC 2045 specifies Base64 as a Content-Transfer-Encoding and limits encoded lines to 76 characters4.
Data URLs — RFC 2397 defines the data: scheme for including data directly in a URL and provides a ;base64 form for non-text-safe bytes5.
HTTP Basic authentication — A client joins a user ID, a colon, and a password, then Base64-encodes that sequence for the credentials field6. Base64 provides no confidentiality; RFC 7617 therefore warns against using Basic authentication without a secure transport such as TLS.
JSON Web Tokens — JWT represents its parts as URL-safe strings separated by periods7. Signed JWTs use the unpadded base64url encoding specified by JWS8.
PEM-style certificate files — RFC 7468 describes textual encodings that place Base64 data between BEGIN and END boundaries9.
Browser APIs — JavaScript's btoa() converts a binary string to Base64, and atob() converts Base64 back to a binary string. Text containing code points above 0xff must first be converted to bytes, for example with TextEncoder10.
The URL-safe variant
Standard Base64 uses + and / as characters 62 and 63. Those characters can require special handling in filenames and URLs. RFC 4648 therefore defines base64url, which uses - and _ instead1. Padding remains part of the general base64url definition unless the referring specification says otherwise; JWS is one specification that omits it8.
| Character | Standard | URL-safe |
|---|---|---|
| Index 62 | + | - |
| Index 63 | / | _ |
| Padding | = unless specified otherwise | = unless specified otherwise |
The bit grouping is unchanged. Only the two alphabet characters differ, with padding governed by the protocol that uses base64url.
Base64 vs. its siblings
RFC 4648 standardizes three related schemes1:
Base16, commonly called hexadecimal, represents each byte with two characters. Its RFC 4648 alphabet is case-insensitive when decoding.
Base32 uses the letters A–Z and digits 2–7. Its alphabet excludes 0 and 1, which can be confused with the letters O, I, and L1.
Base64 uses fewer output characters for the same complete input blocks: four for three bytes, compared with eight for five bytes in Base32 and two for one byte in Base16.
Not encryption
Base64 is an encoding, not encryption. It uses no key and provides no confidentiality or integrity. For example, SGVsbG8gV29ybGQ= decodes to Hello World; the encoded form should be treated as plainly recoverable data.
Citations
-
RFC 4648: The Base16, Base32, and Base64 Data Encodings. S. Josefsson, October 2006 ↩ ↩2 ↩3 ↩4 ↩5 ↩6 ↩7 ↩8
-
RFC 989: Privacy Enhancement for Internet Electronic Mail: Part I. J. Linn, February 1987 ↩
-
RFC 1421: Privacy Enhancement for Internet Electronic Mail: Part I. J. Linn, February 1993 ↩
-
RFC 2045: Multipurpose Internet Mail Extensions (MIME) Part One. N. Freed, N. Borenstein, November 1996 ↩ ↩2 ↩3 ↩4
-
RFC 2397: The "data" URL scheme. L. Masinter, August 1998 ↩
-
RFC 7617: The 'Basic' HTTP Authentication Scheme. J. Reschke, September 2015 ↩
-
RFC 7519: JSON Web Token (JWT). M. Jones, J. Bradley, N. Sakimura, May 2015 ↩
-
RFC 7515: JSON Web Signature (JWS). M. Jones, J. Bradley, N. Sakimura, May 2015 ↩ ↩2
-
RFC 7468: Textual Encodings of PKIX, PKCS, and CMS Structures. S. Josefsson, S. Leonard, April 2015 ↩
-
MDN Web Docs: Window: btoa() method. Retrieved March 16, 2026 ↩
Updated: September 7, 2026