Decoding Base64 is not the same as trusting it
The companion piece to this one, on Base64 not being encryption, covers the encode direction and the mistake of treating unreadable as protected. This is the other direction: what happens when a Base64 string arrives and you turn it back into bytes. There is a second, quieter mistake waiting there, and it is the one that survives after everybody has learned the first.
What a decoder is doing
Four characters carry six bits each, twenty-four bits in total, which is three bytes. So the decoder walks the string four characters at a time, looks each one up in the sixty-four-character alphabet, glues the bits together and emits three bytes. The output is about three-quarters the size of the input, and nothing about the operation requires a key, a permission or a secret.
What the padding is for
The trailing = signs exist because the input length was not a multiple of three, and the decoder needs to know how much of the final group was real data rather than zero bits added to fill it out.
The ladder is short enough to see all of at once. One byte, g, encodes to Zw==: two characters of data and two of padding. Two bytes, gg, encode to Z2c=: three and one. Three bytes, ggs, encode to Z2dz: four characters and no padding at all. Longer inputs just repeat the pattern — gg network is ten bytes and encodes to Z2cgbmV0d29yaw==, which is nine data characters and two of padding, because ten leaves one byte over.
Padding matters when Base64 strings are concatenated or streamed, because it tells the decoder where one ends. When a string stands alone, its own length already says how many bytes it holds, which is why so much of the world drops the padding and why a decoder that insists on it will reject strings that are perfectly readable.
Two alphabets
Standard Base64's last two characters are + and /, and both of them are awkward in a URL: one may be read as a space, the other is a path separator. Base64url swaps them for - and _ and usually drops the padding, because = is structural in a query string too. That is the form JWT segments and many API tokens use.
The two alphabets agree on the first sixty-two characters, so a decoder can accept either simply by mapping - the way it maps + and _ the way it maps /. That is what this site's decoder does, and it also skips whitespace and treats padding as optional, so a string that has been wrapped across lines in an email header or a config file decodes without being tidied up first.
Two ways decoding fails
The first is a character outside both alphabets, at which point there is nothing sensible to produce and the tool says the input is not valid Base64 rather than returning something that looks like a result.
The second is subtler and worth knowing: Base64 carries bytes, and bytes are not necessarily text. An image, a compressed archive or an encrypted blob all decode perfectly into bytes that are not valid UTF-8, and a decoder asked for text has to say so instead of substituting replacement characters. Getting "not valid UTF-8" back is not a failure of the decode; it is the decode succeeding and the content simply not being text.
The part people skip
Here is the point of the whole page. Decoding tells you what a string contains. It tells you nothing whatsoever about whether the contents are true, well-formed, or something you should act on. A Base64 blob in a request parameter, a cookie, a header or a data URI was written by whoever sent it, and encoding it added no authority of any kind.
So decoded content is still untrusted input, and it arrives after most of your defences. Values are usually validated on the way in while they are still opaque, and the decode happens later, deeper in the code, where the checks are thinner. Which means:
- Decoded text going into a page needs HTML escaping, exactly like text from a form field.
- Decoded text going into a URL needs percent-encoding for the slot it lands in.
- Decoded JSON needs parsing and schema validation, not trust because it parsed.
- Decoded bytes claiming to be an image need to be checked as an image, not accepted on the strength of a filename.
- Length limits belong on the decoded size as well as the encoded string, since the two differ by a third.
And if the blob is a signed token, decoding it is reading, not verifying. Reading tells you what it says. Only checking the signature tells you whether to believe it.
The tool
The Base64 Decode tool accepts standard or URL-safe input, ignores whitespace, treats padding as optional, and returns the text on your device with nothing uploaded. It is the right tool for reading a config blob, a data URI or a token segment while you are debugging. Treat what comes out the way you would treat anything else a stranger typed.