creatorvalet Search

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.

  • SECURE
  • NO UPLOADS
  • NO SIGNUP
  • BROWSER BASED
  • FREE
  • FOREVER.

Support us with a link or a share

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.

№ 2367waiting

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 of Vä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 Base64 is

Base64
Full name Base64 binary-to-text encoding
Extension — not a file format
Format type An encoding, RFC 4648. Grows the data by about a third
MIME type — carried inside another format

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 -----BEGIN blocks — 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.

One base64 string you will meet on web pages is a hash rather than a file: the integrity attribute on a <script> tag carries a SHA-256, SHA-384 or SHA-512 digest written in base64 instead of the usual hexadecimal, prefixed with sha256-. Decoding one here gives you the raw 32 bytes, which is rarely what you want; if the question is whether a file matches a published digest, the SHA256 checksum tool takes that same sha256- form directly and compares it against a file for you.

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 payload view is deliberately modest — enough to read a token, not a full editor. A claim set that runs to hundreds of lines, or one you want to sort, minify or compare against yesterday's, is better handled by copying the decoded JSON into the JSON formatter, which keeps long integer IDs intact rather than rounding them, and duplicate keys visible rather than dropping one.

Here the signature is shown and nothing more: this page decodes, it does not validate. A token whose payload reads correctly can still be forged, and establishing otherwise means running the algorithm named in the header against a key. Which key depends on the algorithm, and the difference matters more than it is usually given credit for. RS256 and ES256 are settled with the issuer's public key — published at a URL for exactly that purpose, so there is no secret involved and nothing to be careful about. HS256 uses a shared secret, and that one you should keep out of any page that cannot show you it computes locally. Our JWT decoder does both with the browser's own crypto.subtle, and refuses the pairing — an HS256 token offered a public key — that turns a checker into the attack it should be catching.

Worth knowing in the other direction too: anyone who intercepts a JWT can read its payload without any key at all, because base64 is an encoding rather than 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.

This turns up at inconvenient hours, on whatever is nearby

The string rarely appears while you are settled at your own desk. It is in a log line at two in the morning, in a paged alert, in a support ticket somebody forwarded from a customer, in a manifest read over a jump host where the only local program is a terminal. The thing you are holding might be a phone at a kitchen table, a spare laptop with somebody else's browser profile signed into it, or a workstation in a room you badged into forty minutes ago.

None of those are good places to go shopping for a utility, and several of them would refuse the request outright. A tab opens the same way on all of them, and everything above is small enough to be ready before you have finished pasting. That evenness is the practical argument, separate from the one below it: the reading you get at two in the morning on a phone is arrived at by the same arithmetic as the reading you would have got at work.

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 tool image 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.

Have an idea for this tool?

Tell us what would make this tool more useful, or suggest another tool you would like us to build.

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. Proving a token genuine means running its algorithm against a key, and which key that is decides whether any caution applies: RS256 and ES256 settle with the issuer's public key, which is published at a URL precisely so that strangers can fetch it, while HS256 rides on a shared secret that belongs nowhere near a page you cannot audit. That distinction is why /jwt-decoder exists as its own tool — it runs the check through the browser's built-in crypto engine, matches the right key out of a JWK Set by kid, and declines to HMAC a token against a public key, which is the confusion trick rather than a helpful fallback. Either way, anyone holding the token can already 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.