Skip to content
Control Plane Labs

Base64 Encoder/Decoder

Encode and decode Base64 in your browser, with correct UTF-8 handling, a URL-safe alphabet toggle, and file mode for binary payloads.

Privacy: Everything runs in your browser. Files are read with FileReader inside this tab and are never uploaded; text you paste is never logged.

14 characters encoded as 17 UTF-8 bytes. Text is converted with TextEncoder/TextDecoder, so non-ASCII characters survive the round trip. Files are read with FileReader in this tab and never uploaded.

What it does

Encodes text or a local file to Base64, and decodes Base64 back to text or to downloadable bytes. There is a toggle for the URL-safe alphabet, a byte counter so you can see the 4/3 size penalty, and real error messages when the input is not Base64 at all.

Two details make it more useful than the one-liner in your browser console. First, text is converted through UTF-8 properly, so café and emoji encode the way a server expects instead of throwing or silently mangling. Second, decoding detects when the bytes are not text and offers a download instead of pretending a PNG is a string.

How it works

Encoding takes your text through TextEncoder to get UTF-8 bytes, then packs those bytes into the Base64 alphabet. Decoding reverses it and runs the bytes through TextDecoder in strict mode, which is how the tool knows whether the payload was really text. Files are read with FileReader in this tab, capped at 5 MB so the page stays responsive, and never uploaded.

The naive approach you will find in a lot of snippets is btoa applied straight to a string. btoa operates on a “binary string” where every character must be in the range U+0000 to U+00FF. Feed it an emoji and it throws InvalidCharacterError; feed it café and you get the Latin-1 byte 0xE9 rather than the two UTF-8 bytes 0xC3 0xA9, which decodes to mojibake anywhere that expects UTF-8. Converting to bytes first removes the whole class of bug.

Standard versus URL-safe, and why padding matters

Base64 is defined in RFC 4648. Section 4 gives the standard alphabet, which ends in + and /. Section 5 gives “base64url”, identical except that + becomes - and / becomes _, so a value can sit in a query string or a filename without further escaping. The two are not interchangeable: a / inside a URL path segment will be read as a separator, and a + in a query string is often decoded back to a space by form-decoding rules.

Padding is the other point of confusion. Base64 works on 3-byte groups that become 4 characters, and = pads the final group when the input length is not a multiple of 3. RFC 4648 §3.2 allows a specification to make padding optional when the data length is known by other means, which is why JWTs strip it. RFC 7515, the JWS specification, mandates base64url with no padding for exactly that reason. This tool accepts padded and unpadded input, ignores whitespace so PEM-wrapped blobs paste cleanly, and only complains when the length is genuinely impossible.

Worth saying plainly: Base64 is not encryption and offers no confidentiality. A Kubernetes Secret is Base64 because YAML needs a text-safe representation of arbitrary bytes, not because anything is protected. Anyone with read access to the object has the value.

When to reach for it

  • A Kubernetes Secret, Authorization: Basic header, or JWT segment needs reading and you want it decoded without piping it through a shell.
  • You have to embed a small image or certificate in a config file or data URI.
  • An API is rejecting your encoded value and you want to check whether the problem is the alphabet, the padding, or the UTF-8 handling.
  • You need to confirm that a downloaded blob is actually the binary you expect and not an error page that happened to be Base64 encoded.
  • URL encoder/decoder for the percent-encoding layer that usually sits over the top of a Base64 value.
  • Hash generator when you need a digest of the bytes rather than a reversible encoding.
  • JSON formatter for the JSON that falls out of a decoded payload.

Also nearby: the JWT decoder if the string you are holding has two dots in it, and the YAML ↔ JSON converter for the manifest the Secret came from.

Frequently asked questions

Why does plain btoa() break on emoji and accented characters?+
btoa only accepts code points 0–255, so anything above U+00FF throws InvalidCharacterError and Latin-1 characters get encoded as one byte instead of their UTF-8 form. This tool runs your text through TextEncoder first, so café becomes the 5 UTF-8 bytes a server expects rather than 4 Latin-1 bytes.
What is the difference between Base64 and Base64url?+
Same 6-bits-per-character scheme, different last two alphabet entries. Standard Base64 (RFC 4648 §4) uses + and /; the URL-safe variant (§5) uses - and _ so the value survives a query string or a filename untouched, and usually drops the = padding. Toggle URL-safe alphabet for the second form. Decoding accepts either without being told which it is.
Is Base64 encryption?+
No. It is a reversible transport encoding with no key, and anyone can decode it in one step. Kubernetes Secrets, HTTP Basic credentials, and JWT payloads are all Base64 and all readable by whoever holds the blob. Encode to move bytes through a text-only channel; encrypt when you need secrecy.
Can I decode a string with no padding, or with newlines in it?+
Yes. Whitespace is stripped and padding is recomputed, so PEM-style wrapped output and unpadded Base64url both decode. The one length that cannot work is a remainder of one character after padding is removed, which always means the value was truncated — the tool says so instead of returning plausible garbage.
What happens when the decoded bytes are not text?+
You get a warning that the payload is not valid UTF-8, and the preview shows U+FFFD replacement characters where the invalid sequences are. Use Download bytes to save the real payload to disk rather than copying the mangled preview. That is the normal path for PNGs, protobufs, and gzip blobs.