Base64 encoder and decoder
Encode and decode Base64 with full Unicode support, including a URL-safe alphabet, and encode any file to Base64 without uploading it.
Encode a file instead
Drag a file here, or
The file is read in your browser. It is not uploaded.
Ready · runs on your device
Nothing is uploaded. This tool runs entirely inside your browser tab. Your files and figures stay on your device - we never receive them, so we cannot read, store or lose them.
How Base64 works
Base64 takes binary data and represents it using 64 characters that survive any text channel: A–Z, a–z, 0–9, + and /, with = for padding.
The mechanism is a regrouping of bits. Three bytes - 24 bits - are split into four 6-bit groups, and each group indexes into the 64-character alphabet.
Input: M a n
ASCII: 77 97 110
Binary: 01001101 01100001 01101110
Regroup: 010011 010110 000101 101110
Index: 19 22 5 46
Output: T W F u
So Man encodes to TWFu. When the input length is not a multiple of three, = pads the output - one = if two bytes remain, two if one byte remains.
Where it is genuinely used
- Email attachments. MIME has encoded binary this way since 1992, because SMTP was designed for 7-bit text.
- Data URIs.
data:image/png;base64,...embeds an image directly in HTML or CSS. - JSON Web Tokens. All three segments are URL-safe Base64.
- HTTP Basic authentication. The
Authorizationheader carries a Base64 ofuser:password- encoded, emphatically not encrypted, which is precisely why Basic auth requires HTTPS. - Binary in JSON. JSON has no binary type, so bytes travel as Base64 strings.
- Cryptographic material. PEM certificates and SSH keys are Base64 with header lines.
The Unicode trap
The browser’s built-in btoa accepts only Latin-1. Passing it "héllo" throws, and passing it text that happens to survive can still corrupt on the way back.
The correct sequence is to encode the string to UTF-8 bytes first, then Base64 those bytes:
// Correct
const b64 = btoa(String.fromCharCode(...new TextEncoder().encode(text)));
// Broken for anything outside Latin-1
const b64 = btoa(text);
This tool does the former, which is why 日本語, Привет and 🎉 all survive a round trip intact.
Size, and when to inline
Base64 output is roughly 4/3 the size of the input. For a data URI in CSS, that overhead is offset by saving an HTTP request - worthwhile for a small icon under about 2 KB, and counterproductive above it. Large inlined assets bloat the stylesheet, cannot be cached separately, and block rendering while the CSS parses.
Base64 is not a security boundary
It is worth stating plainly because the mistake is so common. Base64 in a cookie, a URL parameter or a config file provides zero protection. If the data needs protecting, encrypt it and manage the key properly. If it merely needs to travel through a text channel, Base64 is exactly the right tool - and nothing more.
Common questions
Is Base64 encryption?
No, and treating it as such is a genuine security mistake. Base64 is a reversible encoding with no key - anyone can decode it instantly. It exists to move binary data safely through text-only channels, not to hide anything. Never use it to obscure credentials.
Why does encoding make my data bigger?
Base64 represents every 3 bytes as 4 characters, so output is about 133% of the input, plus padding. This is unavoidable - it is the cost of restricting yourself to 64 safe characters. It is why inlining large images as data URIs is usually a false economy.
What is URL-safe Base64?
Standard Base64 uses + and /, which have special meanings in URLs and must be percent-encoded. The URL-safe variant (RFC 4648 §5) substitutes - and _ and usually drops the = padding. JSON Web Tokens use it, which is why a JWT contains no + or / characters.
Why do some decoders mangle non-English text?
Because they use the browser's atob directly, which only handles Latin-1. Anything outside that range - accented characters, Cyrillic, Arabic, CJK, emoji - comes out corrupted. This tool converts through TextEncoder and TextDecoder, so UTF-8 round-trips correctly in every language.
Last reviewed