Base64 and URL Encoding: A Developer's Complete Guide
TL;DR
Base64 converts binary data to ASCII text (33% size increase) for safe transport in text-only contexts like JSON, email, or data URIs. URL encoding replaces unsafe characters with percent-encoded values (%XX) for valid URLs. Use Base64 for binary data in text contexts; use URL encoding for query parameters and path segments.
Key Facts:
- Base64 uses 64 characters: A-Z, a-z, 0-9, +, / (and = for padding)
- URL encoding converts spaces to
%20(or+in query strings) - Base64 increases size by ~33%; URL encoding varies by content
- Both are encoding (reversible), not encryption (not secure)
Understanding Base64 Encoding
What is Base64?
Base64 is a binary-to-text encoding scheme that represents binary data using 64 ASCII characters. It's designed to carry binary data through text-only channels without corruption.
The Base64 Alphabet
A-Z (26) + a-z (26) + 0-9 (10) + '+' + '/' = 64 characters
Padding character: '='
How Base64 Works
- Take input bytes (8 bits each)
- Combine into 24-bit groups (3 bytes)
- Split into four 6-bit groups
- Map each 6-bit value to a Base64 character
Input: "Hi" (ASCII: 72, 105)
Binary: 01001000 01101001
6-bit: 010010 000110 1001xx
Base64: S G k=
Result: "SGk="
Common Base64 Use Cases
| Use Case | Example |
|---|---|
| Data URIs | data:image/png;base64,iVBORw0... |
| Email attachments | MIME encoding |
| API authentication | Basic Auth header |
| JSON payloads | Binary data in JSON |
| JWT tokens | Header and payload encoding |
---
Understanding URL Encoding
What is URL Encoding?
URL encoding (percent-encoding) converts characters that are unsafe or have special meaning in URLs into a percent sign followed by two hexadecimal digits representing the character's ASCII value.
Reserved vs Unreserved Characters
Unreserved (safe, no encoding needed):A-Z a-z 0-9 - _ . ~
Reserved (have special meaning):
: / ? # [ ] @ ! $ & ' ( ) * + , ; =
URL Encoding Examples
| Character | Encoded | Description |
|---|---|---|
| (space) | %20 | Space character |
! | %21 | Exclamation mark |
# | %23 | Hash/pound sign |
$ | %24 | Dollar sign |
& | %26 | Ampersand |
+ | %2B | Plus sign |
@ | %40 | At sign |
When to URL Encode
- Query parameters - Values in
?key=value - Path segments - Dynamic parts of URL paths
- Form data -
application/x-www-form-urlencoded - Fragment identifiers - After the
#
---
Base64 vs URL Encoding: When to Use Each
Use Base64 When:
- Embedding binary data (images, files) in text formats
- Sending data through email (MIME)
- Including binary in JSON/XML payloads
- Basic authentication headers
- Data URIs in HTML/CSS
Use URL Encoding When:
- Building query strings
- Encoding URL path segments
- Submitting HTML form data
- Passing special characters in URLs
- Creating SEO-friendly URLs
Key Differences
| Aspect | Base64 | URL Encoding |
|---|---|---|
| Purpose | Binary → Text | URL-safe text |
| Size change | +33% always | Varies (0-200%+) |
| Character set | 64 chars + padding | Original + %XX |
| Reversible | Yes | Yes |
| Binary safe | Yes | No (text only) |
Practical Examples
Example 1: Inline Image in HTML (Base64)
When to use: Small icons, reducing HTTP requests, email templates.
Example 2: API Authentication (Base64)
// Basic Auth header
const credentials = 'username:password';
const encoded = btoa(credentials);
const header = Basic ${encoded};
// Result: "Basic dXNlcm5hbWU6cGFzc3dvcmQ="
Example 3: Search Query (URL Encoding)
// User searches for "C++ tutorials"
const query = "C++ tutorials";
const encoded = encodeURIComponent(query);
const url = /search?q=${encoded};
// Result: "/search?q=C%2B%2B%20tutorials"
Example 4: Form Submission (URL Encoding)
// Form data: name="John Doe", email="john@example.com"
// Encoded: name=John%20Doe&email=john%40example.com
---
JavaScript Encoding Functions
Base64 Functions
// Encode string to Base64
const encoded = btoa('Hello World');
// Result: "SGVsbG8gV29ybGQ="// Decode Base64 to string
const decoded = atob('SGVsbG8gV29ybGQ=');
// Result: "Hello World"
// Handle Unicode (UTF-8)
function utf8ToBase64(str) {
return btoa(encodeURIComponent(str).replace(
/%([0-9A-F]{2})/g,
(_, p1) => String.fromCharCode(parseInt(p1, 16))
));
}
function base64ToUtf8(str) {
return decodeURIComponent(atob(str).split('').map(
c => '%' + ('00' + c.charCodeAt(0).toString(16)).slice(-2)
).join(''));
}
URL Encoding Functions
// Encode URI component (most common)
encodeURIComponent('hello world'); // "hello%20world"
encodeURIComponent('a=b&c=d'); // "a%3Db%26c%3Dd"// Decode URI component
decodeURIComponent('hello%20world'); // "hello world"
// Encode full URI (preserves :/?#[]@!$&'()*+,;=)
encodeURI('https://example.com/path?q=hello world');
// "https://example.com/path?q=hello%20world"
// Note: encodeURI() does NOT encode reserved chars
// Use encodeURIComponent() for query parameter values
---
Common Pitfalls and Solutions
Pitfall 1: Double Encoding
// WRONG - Double encoding
const value = encodeURIComponent('hello world');
const url = encodeURI(/search?q=${value});
// Result: "/search?q=hello%2520world" (space encoded twice!)// CORRECT - Encode only once
const value = encodeURIComponent('hello world');
const url = /search?q=${value};
// Result: "/search?q=hello%20world"
Pitfall 2: Base64 with Unicode
// WRONG - btoa() fails with non-ASCII
btoa('Привет'); // Error: Invalid character// CORRECT - Encode to UTF-8 first
function encodeUnicode(str) {
return btoa(unescape(encodeURIComponent(str)));
}
encodeUnicode('Привет'); // "0J/RgNC40LLQtdGC"
Pitfall 3: + vs %20 for Spaces
// In query strings, + often means space
// But encodeURIComponent uses %20// For x-www-form-urlencoded (forms)
const formEncode = str =>
encodeURIComponent(str).replace(/%20/g, '+');
// For URL paths, always use %20
Pitfall 4: Base64 URL-Safe Variant
// Standard Base64 uses + and /
// These are reserved in URLs!// Base64URL variant uses - and _ instead
function toBase64Url(base64) {
return base64
.replace(/\+/g, '-')
.replace(/\//g, '_')
.replace(/=+$/, ''); // Remove padding
}
// Used in: JWT tokens, URL parameters
---
Security Considerations
Base64 is NOT Encryption
// This is easily decoded!
const "encoded" = btoa('password123');
// Anyone can decode: atob('cGFzc3dvcmQxMjM=')
Never use Base64 to hide sensitive data. It's encoding, not encryption.
URL Encoding and XSS
URL encoding alone does not prevent XSS attacks. Always sanitize user input and use proper escaping for the output context (HTML, JavaScript, CSS, URLs).
---
Server-Side Encoding
Python
import base64
from urllib.parse import quote, unquote
Base64
encoded = base64.b64encode(b'Hello').decode() # 'SGVsbG8='
decoded = base64.b64decode('SGVsbG8=') # b'Hello'
URL encoding
encoded = quote('hello world') # 'hello%20world'
decoded = unquote('hello%20world') # 'hello world'
Node.js
// Base64
const encoded = Buffer.from('Hello').toString('base64');
const decoded = Buffer.from('SGVsbG8=', 'base64').toString();// URL encoding (built-in)
const encoded = encodeURIComponent('hello world');
const decoded = decodeURIComponent('hello%20world');
PHP
// Base64
$encoded = base64_encode('Hello'); // 'SGVsbG8='
$decoded = base64_decode('SGVsbG8='); // 'Hello'// URL encoding
$encoded = urlencode('hello world'); // 'hello+world'
$encoded = rawurlencode('hello world'); // 'hello%20world'
---
Quick Reference
When to Use What
| Scenario | Solution |
|---|---|
| Image in JSON | Base64 |
| File in email | Base64 (MIME) |
| Query parameter | URL encode |
| Path segment | URL encode |
| JWT payload | Base64URL |
| Binary in localStorage | Base64 |
| Form submission | URL encode |
| Data URI | Base64 |
Free Tools
---Conclusion
Base64 and URL encoding are fundamental tools for web developers. Base64 safely transports binary data through text channels, while URL encoding ensures special characters don't break URLs. Understanding when and how to use each will help you build more robust applications. Key takeaways:
- Base64 for binary data in text contexts
- URL encoding for query strings and URL parameters
- Neither is encryption - don't use for security
- Use the correct function for your use case
- Watch out for double encoding and Unicode issues