Base64 Encoder & Decoder
How it works
Why btoa() fails on Unicode
The browser built-in btoa() only accepts characters up to U+00FF, so btoa('安静 👋') throws InvalidCharacterError. Base64 encodes bytes, not characters — text has to become bytes first, and the encoding that makes the result portable is UTF-8. This tool encodes your text as UTF-8 bytes and Base64-encodes those, so emoji and CJK survive the round trip.
Base64 vs base64url
base64url is the variant used in JWTs and URLs: '+' becomes '-', '/' becomes '_', and the trailing '=' padding is dropped. That is why the segments of a JWT never end in '='. The decoder here accepts both alphabets and restores missing padding automatically.
Previewing Base64 images
Base64-encoded images are everywhere in modern payloads: data: URIs in CSS and HTML, image blocks in LLM vision API requests, screenshots in API error dumps. The IMAGE mode decodes the payload, identifies the format from its magic bytes (PNG, JPEG, GIF, WebP, AVIF, SVG, BMP, ICO) and renders it right below the output — a pasted full data URI works too, the data:image/...;base64, prefix is stripped automatically. Rendering uses a local blob: URL, so the image is never sent anywhere; the page's Content-Security-Policy still forbids every network request.
Examples
| Clean everything · 安静 👋 | Q2xlYW4gZXZlcnl0aGluZyDCtyDlronpnZkg8J+Riw== |
| hello | aGVsbG8= |
| 👋 | 8J+Riw== |
FAQ
Why does btoa() throw InvalidCharacterError?
btoa() only accepts Latin-1 input (code points up to U+00FF). Any emoji, CJK or accented character outside that range makes it throw. Encode the string to UTF-8 bytes first, then Base64-encode the bytes — which is exactly what this tool does.
Why does my JWT Base64 have no = padding?
JWTs use base64url, which drops the '=' padding and swaps '+' and '/' for '-' and '_'. A strict standard-Base64 decoder rejects it. This decoder normalizes the alphabet and re-adds padding before decoding.
Is my text uploaded to a server?
No. The page ships a strict Content-Security-Policy: connect-src 'none' blocks fetch, XHR, WebSockets and beacons, while default-src 'self' and form-action 'none' block every other way markup could send data off-site. Encoding happens in your browser and cannot leave it.
Can I decode Base64 that contains line breaks?
Yes. Whitespace (including MIME-style 76-column line wrapping) is stripped before decoding.
Why does DECODE say my input 'may be binary data'?
DECODE expects the bytes to be UTF-8 text. Base64 of an image, an archive or any other binary produces bytes that are not valid UTF-8, so the text decoder refuses rather than show garbage. If it is an image, switch to the IMAGE mode, which renders it instead of decoding it as text.
Can I preview a data: URI?
Yes — paste the whole thing. The IMAGE mode strips a leading data:image/...;base64, prefix automatically and identifies the real format from the magic bytes, ignoring the MIME type the URI claims.