Two alphabets, one decoder
Standard Base64 uses + and /; the URL-safe variant swaps them for - and
_ so the value survives inside a URL. Both arrive here and both decode, with
no switch to set — the alphabets do not overlap, so there is no ambiguity to
resolve.
Where you will meet each one
- Standard, with padding:
Authorization: Basic, data URIs, MIME attachments - base64url, usually unpadded: JWT header and payload, OAuth PKCE challenges, signed URLs, webhook signatures
What the error actually means
Decoding always produces bytes. Turning bytes into text only works if they are valid UTF-8, and this tool reports failure rather than substituting replacement characters — a silent � is worse than a clear message, because it looks like data.
If you hit that, the input is almost certainly a file rather than a string.
Questions
Do I need to add the = padding?+
No. Padding is stripped by convention in base64url — JWT segments never carry it — so this tool restores it before decoding. Paste the segment exactly as you found it.
It says the bytes are not valid UTF-8. What now?+
The input probably encodes a binary file rather than text: a PNG, a PDF, a compressed blob. Base64 carries bytes, and only some byte sequences are text. That message means the decode worked and the result simply is not readable as characters.
Can I decode a JWT with this?+
You can decode each segment, but the [JWT decoder](/t/jwt-decoder) splits the three parts, formats the JSON and converts the expiry timestamp for you, which is what you actually want.
Is Base64 a way to hide a value?+
No. Decoding needs no key and this page proves it. If you found a Base64 string in a config file or a URL, treat its contents as public — because they are.