Home / Code & Data / Base64 Encoder
04.02Code & Data

Base64 Encoder & Decoder

Encode and decode text with proper UTF-8 handling, switch to the URL-safe alphabet for JWTs and query strings, turn files into data URIs, and turn Base64 back into a real file.

Updated

Text

File to Base64 / data URI

Base64 to file

What Base64 actually does

Base64 takes raw bytes and rewrites them using only 64 safe characters: A-Z, a-z, 0-9, + and /. Every 3 bytes become 4 characters, which is why encoded output is always about 33% larger than the input, and why you sometimes see one or two = signs of padding at the end. The point is transport: it lets binary data travel through systems that only expect text, such as JSON, email, HTML attributes and HTTP headers.

It is not encryption and it is not compression. If you see Authorization: Basic dXNlcjpwYXNz, that decodes straight back to user:pass.

The UTF-8 trap in JavaScript

The browser's built-in btoa() was designed for binary strings where each character is one byte. Feed it an emoji or "é" and it throws InvalidCharacterError. Old snippets work around it with unescape(encodeURIComponent(str)), which is deprecated. The modern, correct version converts text to UTF-8 bytes first:

// encode
const bytes = new TextEncoder().encode('Héllo 👋');
const b64 = btoa(String.fromCharCode(...bytes));

// decode
const bin = atob(b64);
const text = new TextDecoder().decode(
  Uint8Array.from(bin, c => c.charCodeAt(0))
);

For large inputs, build the binary string in chunks instead of spreading the whole array, or you will hit the engine's argument limit. That is what this tool does internally. In Node, Buffer.from(str).toString('base64') handles all of it for you.

Standard vs URL-safe

+ and / have special meanings in URLs and file paths, and = needs escaping in query strings. The URL-safe alphabet (RFC 4648 section 5) swaps them for - and _ and usually drops padding. JSON Web Tokens use it for all three of their segments, which is why you can paste a JWT segment into the decoder above with URL-safe enabled and read its header or payload. The decoder accepts both alphabets and missing padding either way.

Data URIs: when inlining helps and when it hurts

A data URI embeds a file directly in HTML or CSS: data:image/svg+xml;base64,.... It saves one HTTP request, which made sense in the HTTP/1.1 era. With HTTP/2 and HTTP/3 the request is cheap, and inlining has real costs: 33% larger payload, no separate caching, and it blocks the CSS or HTML it lives in from finishing sooner. Good uses today are tiny icons, a low-quality image placeholder, and email templates where external images may be blocked. For SVG specifically, URL-encoding the markup is usually smaller than Base64.

Decoding back to a file

Paste a data URI or plain Base64 into the last panel to get a real file. If you paste a data URI, the MIME type comes from its header. With plain Base64, the tool sniffs the first bytes for common signatures (PNG, JPEG, GIF, WebP, PDF, ZIP) and picks the right extension.

Frequently asked questions

Is Base64 encryption?

No. Base64 is an encoding, not encryption. Anyone can decode it instantly. Never use it to hide passwords, keys or personal data.

Why does btoa() throw on emoji or accented characters?

btoa() only accepts characters in the Latin-1 range. Encode the text to UTF-8 bytes first with TextEncoder, then Base64 the bytes. This tool does that for you.

When should I use URL-safe Base64?

Whenever the value goes into a URL, a filename or a cookie. URL-safe Base64 replaces + with - and / with _, and usually drops the = padding. JWTs use this variant.

Should I inline images as data URIs?

Only small ones, roughly under 2 to 4 KB, such as icons or a blurred placeholder. Base64 adds about 33% to the size and inlined images cannot be cached separately.