In short
- Base64 writes binary data as text using A-Z, a-z, 0-9, + and /, with = as padding. It's defined in RFC 4648.
- Every 3 bytes become 4 characters, so Base64 output is about 33% larger than the input (4/3).
- Base64url swaps + and / for - and _ so the result is safe in URLs and file names. JWTs use it without padding.
- Base64 is not encryption. Anyone can decode it without a key.
What is Base64?
Base64 is a way to represent any binary data, such as an image, a PDF or an encryption key, using only 64 printable characters: the uppercase letters A-Z, lowercase a-z, the digits 0-9, plus + and /. An = sign pads the end when needed. The standard alphabet is defined in RFC 4648, published in 2006.
It exists because many systems were built to carry text, not raw bytes. Email (MIME attachments), JSON and XML documents, HTML and CSS, HTTP headers and configuration files can all mangle or reject arbitrary bytes. Base64 output survives all of them because it only uses characters that every system treats the same way. You'll see it in email attachments, data URIs, JSON Web Tokens, HTTP Basic authentication headers and PEM certificate files.
How Base64 encoding works: "Man" becomes "TWFu"
Base64 works on groups of 3 bytes (24 bits) and splits each group into four 6-bit pieces. Six bits can hold a value from 0 to 63, and each value picks one character from the alphabet. Here's the classic example, the word Man:
| Step | M | a | n |
|---|---|---|---|
| ASCII code | 77 | 97 | 110 |
| 8-bit binary | 01001101 | 01100001 | 01101110 |
Join the three bytes into one 24-bit string, 010011010110000101101110, then cut it into four groups of six:
| 6-bit group | Value | Base64 character |
|---|---|---|
010011 | 19 | T |
010110 | 22 | W |
000101 | 5 | F |
101110 | 46 | u |
The alphabet maps 0-25 to A-Z, 26-51 to a-z, 52-61 to 0-9, 62 to + and 63 to /. So 19 is T, 22 is W, 5 is F, and 46 is the 21st lowercase letter, u. Three bytes in, four characters out: TWFu. Decoding runs the same steps backwards.
Padding: why Base64 ends in = or ==
Input rarely divides evenly into 3-byte groups. When the last group is short, the encoder fills the missing bits with zeros and adds = signs so the output length stays a multiple of four:
Man(3 bytes) becomesTWFu, no padding.Ma(2 bytes) becomesTWE=: 16 bits fill three characters, then one=.M(1 byte) becomesTQ==: 8 bits fill two characters, then two=.
So a Base64 string never ends in more than two = signs, and the padding tells you whether the original length was a multiple of 3. RFC 4648 requires padding unless the format using it says otherwise, and allows dropping it when the length is known some other way. That's why some systems omit it, and why a decoder that insists on padding can fail on valid input from one of them.
Base64 size overhead: why files grow by a third
Every 3 bytes of input become 4 characters of output, so encoded data is 4/3 the size of the original, about 33% larger. The exact length is 4 times the number of bytes divided by 3, rounded up to a whole group: 100 bytes become 136 characters, and a 100 KB image (102,400 bytes) becomes 136,536 characters.
Line breaks can add a little more. MIME email requires Base64 lines of no more than 76 characters, and a CRLF after each line adds about 2.6%. The GNU base64 command also wraps at 76 by default. RFC 4648 itself says encoders must not add line breaks unless the format calls for them, which is why JSON and URLs carry one long line.
Data URIs: when inlining an image is worth it
A data URI puts a Base64 file straight into HTML or CSS, like <img src="data:image/png;base64,iVBORw0KGgo...">. It saves an HTTP request, but the image grows by a third, can't be cached separately from the page, and is downloaded again on every page that includes it. Google's image SEO guidance also warns that data URIs can make pages much larger. Keep them for very small icons and SVGs. Our image to Base64 converter shows the data URI size next to the original so you can judge, and offers a URL-encoded SVG option that's often smaller than Base64.
Base64url vs standard Base64
Two characters in the standard alphabet cause trouble in web addresses: + means a space in form-encoded query strings, and / separates path segments. RFC 4648 defines a second alphabet, called URL and filename safe, that replaces them with - and _. Everything else is identical.
| Standard Base64 | Base64url | |
|---|---|---|
| Values 62 and 63 | + and / | - and _ |
| Padding | Required by default | Often omitted |
| Bytes FB FF BF encode to | +/+/ | -_-_ |
| Used in | Email, data URIs, PEM files, most APIs | JWTs, URL parameters, file names |
JSON Web Tokens are the best-known user: RFC 7515 defines their encoding as Base64url with all trailing = characters removed and no line breaks. That's why pasting a JWT segment into a strict standard decoder can fail. Our Base64 decoder accepts both alphabets and missing padding, and the JWT decoder splits a token and decodes each part for you.
Base64 vs URL encoding
They solve different problems. URL encoding (percent-encoding, RFC 3986) escapes only the characters that would break a URL, writing each byte as % plus two hex digits. Base64 re-encodes every byte, readable or not.
Take the text café & crème. URL-encoded it's caf%C3%A9%20%26%20cr%C3%A8me: the plain letters stay readable, the space becomes %20 and the accented letters become their UTF-8 bytes. Base64-encoded it's Y2Fmw6kgJiBjcsOobWU=, which hides everything.
- Putting a text value in a query string or form field: use URL encoding. Our URL encoder and decoder handles both
%20and+for spaces. - Putting binary data such as a hash, token or small file in a URL: Base64url it first.
- Putting standard Base64 in a URL: percent-encode it as well, or the
+signs may arrive as spaces.
Is Base64 encryption?
No. Encryption needs a secret key, and Base64 has none: the alphabet is public and any decoder reverses it instantly. An HTTP header like Authorization: Basic dXNlcjpwYXNz looks scrambled but decodes to user:pass. That header is only protected because HTTPS encrypts the connection around it.
| Encoding (Base64) | Encryption (AES) | Hashing (SHA-256) | |
|---|---|---|---|
| Purpose | Carry bytes as text | Keep data secret | Fingerprint data |
| Needs a key | No | Yes | No |
| Reversible | By anyone | Only with the key | No |
If you need to hide text, encrypt it. Our text encryption tool uses AES-256-GCM with a password. If you need to check that data hasn't changed, hash it; our comparison of MD5, SHA-1 and SHA-256 explains which algorithm to pick.
How to encode and decode Base64
For a quick string or file, paste or drop it into the Base64 encoder and decoder; it runs in your browser and can output a raw string or a full data URL. From the command line or in code:
# Linux (GNU coreutils): wraps at 76 characters unless you add -w 0
base64 -w 0 photo.jpg > photo.b64
base64 -d photo.b64 > photo.jpg
# macOS or Linux with OpenSSL (-A keeps it on one line)
openssl base64 -A -in photo.jpg -out photo.b64
openssl base64 -d -A -in photo.b64 -out photo.jpg
# Windows PowerShell
[Convert]::ToBase64String([IO.File]::ReadAllBytes("C:\photos\photo.jpg"))
# Python
import base64
base64.b64encode(b"Man") # b'TWFu'
base64.urlsafe_b64encode(data) # Base64url, keeps the = paddingIn JavaScript, btoa() and atob() work on single-byte strings only. MDN documents that btoa() throws an InvalidCharacterError for any character above code point 255, and recommends converting text to UTF-8 bytes with TextEncoder first:
// btoa() only accepts characters up to code point 255
btoa("Man"); // "TWFu"
btoa("price: 5 €"); // throws InvalidCharacterError
// Encode Unicode text as UTF-8 bytes first
const bytes = new TextEncoder().encode("price: 5 €");
btoa(String.fromCodePoint(...bytes));When decoding fails, check three things in order: whitespace or line breaks pasted into the string, - and _ from Base64url fed to a standard decoder, and missing = padding.
Frequently asked questions
Is Base64 encryption?
No. Base64 is an encoding with a public alphabet and no key, so anyone can decode it. Use real encryption such as AES when data must stay secret.
Why do Base64 strings end with = or ==?
The = signs are padding. Base64 encodes 3 bytes at a time, and when the input length isn't a multiple of 3, one or two = characters fill out the last 4-character group.
How much bigger does Base64 make a file?
About 33%. Every 3 bytes become 4 characters, so a 300 KB image becomes about 400 KB of text, plus a little more if the output is wrapped into lines.
What is the difference between Base64 and Base64url?
Base64url replaces + with - and / with _ so the output is safe in URLs and file names, and it usually drops the = padding. The rest of the alphabet and the encoding steps are identical.
Why won't my Base64 string decode?
The usual causes are spaces or line breaks inside the string, Base64url characters (- and _) passed to a standard decoder, missing = padding, or a data URI prefix such as data:image/png;base64, left at the start. Remove or convert those and try again.
What is Base64 used for?
Carrying binary data through channels built for text: email attachments, images embedded in HTML or CSS as data URIs, binary values inside JSON, JSON Web Tokens and HTTP Basic authentication headers.