creatorvalet

Base64 decode and encode

Base64 encodes bytes, not characters. Which bytes depends on the character encoding — so this tool lets you choose it, both ways.

Runs in your browser0 bytes uploaded
Waiting
Variant
Characters
Decodes to

What the web, JSON and every modern API use. Base64 gives you bytes; this is how those bytes become characters.

No variant to choose here: standard, URL-safe, base64url and MIME all decode the same way. Whichever one you pasted is detected and named above.

№ 4988waiting

Nothing at the counter yet. Paste a base64 string, a data URI or a JWT.

What a base64 decode actually returns: bytes, not characters

This is the one sentence that explains almost every confusing thing about base64, and almost no tool says it out loud. Base64 is a way to write arbitrary bytes using 64 printable characters, so that data survives a channel that only carries text — an email body, a JSON string, a URL, an XML attribute. It has no opinion about characters, languages or alphabets. It never sees them.

So before any text can be base64-encoded, something has to turn it into bytes, and that something is a character encoding. The letter å is two bytes in UTF-8 (C3 A5, which encodes to w6U=) and one byte in ISO-8859-1 (E5, which encodes to 5Q==). Both are correct base64. They are base64 of different bytes, because the same letter was written down two different ways before base64 ever got involved.

That step is where the mojibake comes from. You are handed a string from a legacy system, you paste it into whichever decoder ranks first, the decoder assumes UTF-8 because it always assumes UTF-8, and out comes VästerÃ¥s instead ofVästerås. Nothing is broken. The decoder just answered a question you did not ask. Here the encoding is a control in both directions, and the comparison table shows all six at once, so you can pick by looking at the result rather than by remembering which system produced the string.

What the four variants are, and when they bite

Standard base64, defined in RFC 4648, uses A–Z, a–z,0–9, + and /, and pads the end with =so the length is always a multiple of four. Two of those characters are a problem the moment the string goes into a URL: + means a space in a query string and/ is a path separator. The URL-safe variant swaps them for -and _.

base64url goes one step further and drops the padding, because= is also reserved in a query string. That is the variant JSON Web Tokens use, which is why a JWT never contains an equals sign. Dropping the padding is harmless: the original length can be worked out from what is left, and a decoder that refuses unpadded input is being pedantic rather than careful.

MIME base64 is standard base64 broken into lines. RFC 2045 says 76 characters per line, because that is what a 1990s mail transfer agent would carry without mangling. PEM files — certificates, private keys, the -----BEGINblocks — wrap at 64 instead. The line breaks are not part of the data and any decoder must ignore them, but plenty of encoders will not produce them, which is why a certificate pasted into a tool sometimes comes back as one enormous line that the next system rejects. Both widths are one click apart above, and the field takes any number.

When decoding, none of this matters and the tool does not ask. All four variants decode identically; the input is examined, the variant is named on the status line, and the decoding proceeds. Offering you a variant selector for decoding would be a control that does nothing.

When the decoded bytes are not text at all

A large share of base64 in the wild is not text. It is a gzip blob, a PNG, a PDF, a protobuf message, a certificate, a session cookie full of binary. Decode that as UTF-8 and a normal tool shows you a wall of replacement characters — the exact same output for a PNG, a zip and a corrupted string, which makes it useless for telling them apart.

This tool refuses to do that. UTF-8 has strict rules about which byte sequences are legal, so invalid data is detectable rather than merely ugly: continuation bytes without a lead byte, overlong encodings, surrogate halves, anything above U+10FFFF. When the bytes fail those rules, you get the byte offset of the first invalid sequence, a guess at what the data actually is based on its magic bytes, and a hex dump with an ASCII column. 1F 8B is gzip. 89 50 4E 47 is a PNG.25 50 44 46 is a PDF. 50 4B 03 04 is a zip, which also means a .docx or an .xlsx or a .jar. That is information you can act on; a row of diamonds is not.

The single-byte encodings need the opposite treatment. ISO-8859-1 and Windows-1252 map every one of the 256 possible byte values to a character, so they cannot fail — decoding a PNG as Latin-1 produces a perfectly valid, perfectly meaningless string. The control-byte count catches that case and says so instead of handing you nonsense with a confident face.

JWTs: decoded, not verified

Most people who search for a base64 decoder are holding a JSON Web Token. It is three base64url segments joined by dots — header, payload, signature — and the dot is not a base64 character, so a plain decoder fails on it with a message about an invalid character at position 37 and no hint about the obvious. Paste a token here and all three segments are decoded separately, the header and payload are shown as formatted JSON, and the exp, iat and nbf claims are turned into real dates with a plain-English note: expired three days ago, expires in forty minutes.

The signature is shown and nothing more. Verifying it requires the shared secret or the issuer's public key, and pasting either into a web page is a bad idea in any tool, including this one. That is a limitation worth stating clearly rather than papering over: this decodes, it does not validate. A token whose payload reads correctly can still be forged. And the reverse is worth knowing too — anyone who intercepts a JWT can read its payload without any key at all, because base64 is an encoding, not encryption. Tokens should never carry anything you would mind a stranger reading.

Errors that say what is wrong

"Invalid base64" is not an answer. A base64 string can fail for exactly a few reasons and each has a different fix. A character outside the alphabet usually means something came along with the copy — a quote, a variable name, a trailing bracket — and you get the position, the line, the column and the character itself, named when it is invisible. A non-breaking space and a zero-width space both look like nothing at all, and both are common in text copied out of PDFs and chat clients.

A length that is one more than a multiple of four cannot exist, because four base64 characters carry three bytes and there is no group of one. That means a character was lost or an extra one was copied, and the fix is to copy the string again rather than edit it. Padding in the middle almost always means two separate strings were pasted end to end. Missing padding is fine and is added back silently — but the receipt says it was added, because silent tolerance is how you never find out your input was truncated.

Nothing is uploaded

The encoder and decoder are a few hundred lines of arithmetic running in this tab, and there is no endpoint to send anything to. That matters more here than for most formats. The strings people need to decode are session tokens, API keys, basic-auth headers, signed URLs, config blobs and JWTs containing customer identifiers — precisely the material that should never be pasted into a page that might keep it. Open your browser's Network tab and paste something. No request will appear, because there is nowhere for one to go.

If you are working with an image rather than text, the sibling toolimage to base64 handles files: it takes a PNG or a JPEG, shows the size increase before you copy, and wraps the result as a data URI, a CSS rule or an <img> tag. Same encoding layer underneath, different question at the front.

Questions

Why does the same text give a different base64 string in different tools?

Because base64 encodes bytes, and text is not bytes until a character encoding turns it into some. The letter "å" is two bytes in UTF-8 (C3 A5, which encodes to w6U=) and one byte in ISO-8859-1 (E5, which encodes to 5Q==). Neither is wrong; they encode different bytes. Most tools hard-code UTF-8 and never mention the step, so a string that came out of an older system decodes to mojibake with no explanation. This tool asks which encoding you mean, in both directions, and shows all six side by side so you can pick by looking rather than by guessing.

Can this decode a JWT, and does it check the signature?

It decodes, and it does not check. A JSON Web Token is three base64url segments separated by dots: header, payload, signature. Paste one and all three are decoded separately, with the header and payload shown as formatted JSON and the exp, iat and nbf claims turned into readable dates. The signature is shown as bytes and nothing more. Verifying it requires the secret or the public key, which you should never paste into a web page — so a tool that claimed to verify would either be lying or asking for something you should not give it. Anyone who can read the token can read the payload; that is by design, and it is why tokens should not carry secrets.

What are URL-safe base64 and base64url, and do I need to care?

Standard base64 uses "+" and "/", both of which mean something else in a URL, plus "=" padding, which means something else in a query string. The URL-safe variant swaps them for "-" and "_"; base64url goes one step further and drops the padding entirely, which is what JWTs use. MIME adds line breaks every 76 characters, and PEM files wrap at 64. When decoding you do not need to care — all four are detected automatically and the tool tells you which one it found. When encoding you do need to care, so all four are offered, with the line width as an editable field.