Content-Type and MIME Types: Headers, Uploads, and API Responses
Get Content-Type right for APIs, file uploads, and static assets — charset parameters, multipart boundaries, sniffing risks, and a practical MIME lookup workflow.
A practical guide to Base64 and Base64url on the web — encoding binaries for data URLs and Authorization headers, padding rules, size costs, and when client-side tools keep secrets offline.
By codefunc
Base64 shows up everywhere in web development: data: URLs for small images, HTTP Basic Auth headers, PEM certificates, JWT segments, and clipboard-friendly dumps of binary blobs. It is not encryption. It is a reversible text encoding that turns arbitrary bytes into an ASCII-safe alphabet. Misusing it — treating it as obfuscation, stuffing megabyte images into HTML, or pasting production secrets into upload-based converters — creates real production and privacy problems.
Bottom line: Use Base64 when you need binary-safe text transport. Prefer Base64url for tokens and URLs. Never confuse encoding with confidentiality. For sensitive material, encode and decode with client-side tools that keep data in the browser.
Frontend and full-stack developers who paste credentials into headers, embed assets, debug JWTs, or ship small icons as data URIs. If you only remember "Base64 makes binary look like text," this guide fills in the rules that prevent broken padding, bloated bundles, and accidental secret leaks.
Base64 maps every 3 bytes (24 bits) of input to 4 characters from a 64-character alphabet. When the input length is not a multiple of three, the encoder appends = padding so the output length is a multiple of four.
Standard alphabet (RFC 4648):
ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789+/
| Concept | Value |
|---|---|
| Input unit | 3 bytes → 4 chars |
| Expansion | ~33% larger than binary |
| Padding | = or == when needed |
| Character set | ASCII-safe (letters, digits, +, /) |
| Variant | Alphabet difference | Padding | Typical use |
|---|---|---|---|
| Base64 | + and / |
Often kept | MIME, PEM, Basic Auth |
| Base64url | - and _ |
Often stripped | JWT, URL query values |
JWTs use Base64url without padding. If you decode a JWT segment with a strict padded Base64 decoder, you may need to restore = characters first. The Base64 encoder/decoder on codefunc supports the common web workflows; confirm which variant you need before pasting production tokens.
Modern browsers expose encoding helpers:
// Text → Base64 (UTF-8 safe path)
const encoded = btoa(unescape(encodeURIComponent("café")));
const decoded = decodeURIComponent(escape(atob(encoded)));
// Binary → Base64 (Uint8Array)
function bytesToBase64(bytes) {
let binary = "";
for (const b of bytes) binary += String.fromCharCode(b);
return btoa(binary);
}
btoa / atob operate on binary strings (each character is one byte). Passing Unicode directly to btoa throws. Prefer TextEncoder / TextDecoder plus a byte→Base64 helper in new code, or use a dedicated Base64 tool when you need a quick paste workflow.
A data URL inlines content:
data:[<mediatype>][;base64],<data>
Example — 1×1 PNG as Base64:
data:image/png;base64,iVBORw0KGgoAAAANSUhEUgAAAAEAAAABCAYAAAAfFcSJAAAADUlEQVR42mP8z8BQDwAEhQGAhKmMIQAAAABJRU5ErkJggg==
data: URLsUse the Image to Base64 encoder for quick conversion, then decide whether the result belongs in the repo or should stay as a static file. Parse unknown data URLs with the Data URI parser to inspect media type and payload before you trust them.
HTTP Basic Auth encodes username:password as Base64:
Authorization: Basic dXNlcjpwYXNz
const token = btoa(`${username}:${password}`);
fetch(url, {
headers: { Authorization: `Basic ${token}` },
});
Important: Base64 does not protect the password. Without TLS, anyone on the path can decode it. Even with TLS, Basic Auth credentials often end up in proxy logs, browser history, and support tickets. Prefer OAuth bearer tokens, session cookies, or API keys designed for rotation.
Bearer tokens (including JWTs) are often Base64url segments already — you decode them for inspection, you do not "encrypt" them by re-encoding.
| Input length mod 3 | Padding |
|---|---|
| 0 | none |
| 1 | == |
| 2 | = |
Common failure modes:
=; decoders that require padding fail until you restore it.atob.-/_) as standard Base64 (+//) produces garbage or errors.Quick padding restore for JWT-style segments:
function padBase64url(s) {
const b64 = s.replace(/-/g, "+").replace(/_/g, "/");
const pad = (4 - (b64.length % 4)) % 4;
return b64 + "=".repeat(pad);
}
| Situation | Prefer instead |
|---|---|
| Hiding secrets from users | Real encryption (Web Crypto, server-side KMS) |
| Large images or videos | File URLs, CDN, responsive <img> |
| Database binary columns | Native BLOB / BYTEA types |
| High-throughput APIs | Raw binary (application/octet-stream) over HTTP/2 |
| Obfuscating API keys in frontend | Never — anything in the browser is public |
Base64 is a transport encoding, not a security control. If a junior engineer Base64-encodes an API key "so it is not plain text in the repo," reverse it in one paste into the Base64 decoder.
Rough cost:
base64_size ≈ 4 * ceil(binary_size / 3)
A 300 KB image becomes ~400 KB of text. Inlined into a JS bundle, that text:
Rule of thumb: keep data URLs under a few KB unless you have a measured reason.
Production credentials, PEM private keys, session cookies, and customer file bytes should not go to unknown upload APIs. Client-side tools run the transform in JavaScript on your machine:
Recommended workflow:
data: strings, inspect with the Data URI parser before embedding elsewhere.Rule of thumb: If you would not paste it into a public Slack channel, do not paste it into a server-side encoder.
| Symptom | Likely cause | Fix |
|---|---|---|
InvalidCharacterError in atob |
Wrong alphabet, truncated string, bad padding | Normalize url-safe chars; restore = |
| Garbled Unicode after decode | Used atob without UTF-8 round-trip |
Use TextDecoder on bytes |
Image will not render in data: URL |
Wrong media type or truncated Base64 | Re-encode; verify with Data URI parser |
| Auth header rejected | Extra newline or missing Basic prefix |
Trim; check exact header format |
| JWT segment will not decode | Padding stripped / url-safe alphabet | Convert -/_ and pad |
Treat Base64 as binary-safe text, not as security. Use standard Base64 for Basic Auth and PEM-style blobs; use Base64url for tokens and URL components. Keep data URLs small. Watch padding and alphabet mismatches when integrations fail. Prefer client-side Base64, Image Base64, and Data URI parser tools when the payload is sensitive — no data needs to leave your machine to encode or decode.
Get Content-Type right for APIs, file uploads, and static assets — charset parameters, multipart boundaries, sniffing risks, and a practical MIME lookup workflow.
Learn when Base58 beats Base64 — alphabet rules, leading-zero handling, checksum variants, and how to encode or decode safely in the browser.
Break down URL parts, encode query values correctly, and know when to use encodeURIComponent vs encodeURI — plus reserved characters that break APIs.
Find a developer tool