Base64 and URL encoding solve the same basic problem: some channels only accept a limited set of characters. Email was designed for text, URLs reserve characters like ?, & and #, and JSON can’t hold raw binary bytes. Encoding converts data into a safe alphabet and back again, losslessly. Developers meet both every day, in API tokens, data URLs, email attachments and query strings, and mixing them up causes confusing bugs. Use our Base64 encoder/decoder and URL encoder to try the examples below.
Base64: how it works
Base64 (defined in RFC 4648) represents binary data using 64 printable characters:
A–Z a–z 0–9 + / (and = for padding)
The algorithm:
- Take the input 3 bytes (24 bits) at a time.
- Split the 24 bits into four 6-bit groups.
- Map each 6-bit value (0–63) to a character in the alphabet.
- If the input isn’t a multiple of 3 bytes, pad the output with
=.
Worked example: “Man”
| M | a | n | |
|---|---|---|---|
| ASCII | 77 | 97 | 110 |
| Binary | 01001101 | 01100001 | 01101110 |
Regrouped into 6 bits: 010011 010110 000101 101110 → 19, 22, 5, 46 → TWFu.
More examples:
| Input | Base64 |
|---|---|
Man |
TWFu |
Hi! |
SGkh |
Hi |
SGk= |
café (UTF-8) |
Y2Fmw6k= |
Note that é is two bytes in UTF-8, so the text must be converted to bytes (normally UTF-8) before encoding. In JavaScript, btoa("café") fails or gives wrong results with non-Latin characters; encode to UTF-8 first with TextEncoder.
Size overhead
Output is 4/3 the size of the input: about 33% larger. A 3 MB image becomes about 4 MB of Base64 text. MIME email also inserts line breaks every 76 characters, adding a little more. That’s why attachments use more of your mailbox’s size limit than the file size suggests.
Where Base64 is used
- Email attachments (MIME) and images embedded in HTML emails.
- Data URLs: embedding small files directly in HTML or CSS:
<img src="data:image/png;base64,iVBORw0KGgo..." alt="icon">
- HTTP Basic authentication:
Authorization: Basic dXNlcjpwYXNzis justuser:passencoded. It is protected only by HTTPS. - JSON Web Tokens (JWT) and other tokens, using the URL-safe variant.
- Storing binary data (keys, certificates, small files) in JSON, XML or environment variables. PEM certificates are Base64 between
-----BEGINand-----ENDlines.
When not to use data URLs
Inlining images saves an HTTP request but adds 33% to the size, can’t be cached separately and bloats your HTML or CSS. Use it only for very small assets (a few KB, such as tiny icons). For everything else, serve normal image files; see our image optimisation guide.
Base64URL
Standard Base64 uses + and /, which have special meaning in URLs and file names. Base64URL (also RFC 4648) replaces them:
| Standard | Base64URL |
|---|---|
+ |
- |
/ |
_ |
= padding |
Often omitted |
JWTs, many API tokens and some file-naming schemes use Base64URL. Decoding a Base64URL string with a standard decoder may fail until you swap the characters back and restore the padding.
URL encoding (percent-encoding)
URLs can only contain a limited set of ASCII characters, and some characters are reserved for structure (RFC 3986):
: / ? # [ ] @ ! $ & ' ( ) * + , ; =
Percent-encoding replaces any unsafe or reserved character with % followed by its byte value in hexadecimal. Non-ASCII characters are first converted to UTF-8 bytes, each of which is encoded.
| Character | Encoded |
|---|---|
| Space | %20 (or + in form data) |
& |
%26 |
= |
%3D |
? |
%3F |
/ |
%2F |
# |
%23 |
£ |
%C2%A3 |
é |
%C3%A9 |
Unreserved characters never need encoding: A–Z a–z 0–9 - _ . ~.
Example
A search query fish & chips / £5 placed in a query parameter:
https://example.com/search?q=fish%20%26%20chips%20%2F%20%C2%A35
Without encoding, & would start a new parameter and the query would be cut off at “fish “.
In code
encodeURIComponent("fish & chips / £5");
// "fish%20%26%20chips%20%2F%20%C2%A35"
const url = new URL("https://example.com/search");
url.searchParams.set("q", "fish & chips / £5"); // encodes for you (spaces as +)
from urllib.parse import quote, urlencode
quote("fish & chips / £5", safe="")
urlencode({"q": "fish & chips / £5"})
Common mistakes
- Treating encoding as security. Base64-encoded passwords in config files or URLs are effectively plain text. For passwords, use proper hashing; see our strong password guide.
- Double encoding. Encoding an already-encoded string turns
%20into%2520. Encode once, at the point where you build the URL. - Using encodeURI for parameter values. It leaves
&and=unencoded and breaks the query. - Forgetting UTF-8. Encode text to UTF-8 bytes before Base64 or percent-encoding.
- Mixing Base64 and Base64URL when decoding tokens.
- Putting sensitive data in URLs. URLs are logged by servers, proxies and browser history, even over HTTPS.
Checklist
- Base64 for binary-to-text (attachments, tokens, small embeds); expect +33% size.
- Base64URL for anything that goes in a URL or file name.
- Percent-encode each query parameter value with a proper function.
- Encode exactly once and use UTF-8.
- Never rely on encoding to hide information.