Skip to content
Server-sideDeleted in 30 minutes

Base64 Encoder and Decoder

Convert text to Base64 and back, in both the standard and URL-safe alphabets. Unlike the one-line implementation most sites ship, this encodes to UTF-8 first, so accented letters and emoji survive the round trip instead of throwing an error. What people usually paste into a Base64 decoder is a token, which is exactly why nothing pasted here is ever stored — it is converted and discarded per request.

Use this without the search next time. Prathom Workbench puts Prathom's tools in your toolbar.

Add to Chrome — free
Input
Result

What it does

  • Correct UTF-8 handling for accents, CJK, and emoji
  • Standard and URL-safe (RFC 4648 section 5) alphabets
  • Optional MIME-style line wrapping
  • Distinguishes invalid Base64 from valid Base64 that is not text

How to use Base64 Encode / Decode

  1. 1

    Choose a direction

    Text to Base64, or Base64 to text. The decoder accepts both alphabets and works with or without padding, so you can paste a JWT segment straight in without repairing it first.

  2. 2

    Paste the input

    Whitespace and line breaks in Base64 input are ignored, which means a wrapped PEM-style block or a value copied out of a log file works without being joined back into one line by hand.

  3. 3

    Set the alphabet if it is going into a URL

    URL-safe swaps plus and slash for hyphen and underscore and removes the padding, so the result can sit in a query string or a path segment untouched.

  4. 4

    Copy, or swap direction to check the round trip

    Swap direction moves the result into the input box, so encoding then decoding gets you back to exactly what you started with — the fastest way to confirm a value was not mangled in transit.

How it works

Encoding is three steps, and only the middle one is Base64.

First the text is converted to UTF-8 bytes with TextEncoder. This is the step most implementations skip. Base64 encodes bytes, not characters, and a JavaScript string is a sequence of UTF-16 code units — those are different things, and the difference is invisible until someone types an é.

Then those bytes become a binary string, in chunks. The obvious one-liner here is String.fromCharCode(...bytes), and it works beautifully until the input is around a hundred kilobytes, at which point spreading the array into function arguments overflows the call stack. It is a bug that passes every test anyone writes by hand and fails on the first real file. Encoding in 32 KB slices avoids it entirely.

Then btoa does the actual Base64, and for the URL-safe alphabet the two offending characters are substituted and the padding is stripped.

Decoding runs the same path backwards, with padding restored first. The URL-safe form has no = on the end by design, but atob insists on it, so the length is rounded up to a multiple of four before decoding. A length that leaves a remainder of one is rejected outright, because no valid Base64 string can have that length.

Two different failures, reported differently

The last step is where this tool departs from most others.

After decoding you have bytes. Turning those into text can fail on its own, and that failure means something completely different from "the Base64 was malformed". So the decoder runs TextDecoder in fatal mode, which throws instead of quietly substituting the replacement character U+FFFD for every byte it cannot interpret.

Without that flag, decoding a PNG gives you a wall of black diamonds and no explanation. With it, you get told the payload is eight valid bytes that are not UTF-8 — which points you at the actual situation, that someone handed you an embedded file and called it a string.

When you'd use this

Reading a token or a header value that arrived Base64-encoded, which is most of the time. Decoding the payload segment of a JWT to see its claims. Checking that a value survived a round trip through a system that may have mangled it. Producing a data URI, or an encoded credential for a config file.

The one thing not to use it for is hiding anything. Base64 looks like ciphertext to the naked eye and is not, and that resemblance is responsible for a steady supply of secrets committed to public repositories by people who thought encoding them was enough.

Examples

An accent and an emoji, which break naive encoders

Hello, café 🌍
SGVsbG8sIGNhZsOpIPCfjI0=

Thirteen characters become seventeen bytes before encoding, because é takes two bytes in UTF-8 and the globe takes four. An encoder built on btoa alone throws an InvalidCharacterError on this input and usually reports it as "invalid input" — when the input was perfectly fine and the encoder was not.

Base64 that is valid but is not text

iVBORw0KGgo=
Decoded to 8 bytes that are not UTF-8 text — this looks like binary data, such as an image or a compressed file.

Those eight bytes are the PNG file signature, so this is the beginning of an embedded image. The distinction is worth making: the Base64 decoded perfectly, and it is the bytes underneath that are not a string. Told "invalid Base64" instead, you would go and check the wrong thing.

Frequently asked questions

Is what I paste here kept anywhere?

No. Because this is so often a token rather than ordinary text, this is worth being precise about: the value is sent over an encrypted connection to be encoded or decoded, and nothing is written to disk, logged, or retrievable afterward. It exists only for the moment it takes to produce the result, then the request ends and it is gone.

Why do other Base64 tools fail on emoji and accented characters?

Because they call the browser's btoa function directly. That function takes a binary string in which every character must have a code below 256, so anything outside Latin-1 throws immediately. The fix is to encode the text to UTF-8 bytes first and Base64 those, which is what this tool does, and it is also what makes the result decode correctly in Python, Java, or anything else.

Is Base64 a form of encryption?

No, and treating it as one is a genuinely common and serious mistake. It is a reversible encoding with no key and no secret — anyone holding the string can read it in one step, including this page. Its purpose is to carry arbitrary bytes safely through channels that only accept text, such as email bodies, JSON strings, and URLs. If a value needs to stay secret, it needs encryption, and Base64 adds nothing.

What is the URL-safe alphabet and when do I need it?

Standard Base64 uses plus and slash, both of which have meaning inside a URL — slash separates path segments and plus is read as a space in query strings by many servers. RFC 4648 defines an alternative alphabet using hyphen and underscore instead, with the trailing equals padding dropped. Use it whenever the value is going into a path, a query parameter, or a JWT, which uses this variant throughout.

Why does the output get about a third longer?

Base64 represents three bytes with four characters, so the encoded form is about 133% of the original size, plus padding. That overhead is the price of being safe to put anywhere. It is worth remembering when embedding images in CSS or HTML as data URIs — a 40 KB image becomes roughly 54 KB of text, and it can no longer be cached separately from the document.

Can I decode a file, not just text?

You can paste the Base64 and it will decode, but the result is shown as text and binary data has no meaningful text form. The tool tells you the byte count and says so explicitly rather than printing a screen of replacement characters. To recover an actual file you need something that writes the decoded bytes to disk with the right extension.