Developer

Base64 Encoder and Decoder

Paste text on one side and get Base64 on the other. Accents and emoji survive the round trip, which is more than btoa() in the console will do for you. Nothing is sent anywhere — the conversion happens in this tab.

URL-safe swaps the two characters that break inside a query string, and drops the = padding. Decoding accepts either.

Affects encoding only. Line breaks are stripped before decoding.

0Input bytes
0Base64 characters
0%Size change

What Base64 actually does

Base64 rewrites arbitrary bytes using only 64 characters that survive being sent through systems that expect text. It takes three bytes — 24 bits — and splits them into four groups of six bits. Six bits hold a number from 0 to 63, and each number maps to one character. Three bytes in, four characters out, always.

That ratio is the whole cost story: Base64 output is a third larger than the input, before any line breaks. When the input length is not a multiple of three, the encoder pads the last group and marks it with = signs — one for two leftover bytes, two for one leftover byte. That is why so many Base64 strings end in = or ==, and why none of them ever end in three.

Two alphabets, and the bug that comes from mixing them

The standard alphabet from RFC 4648 is A–Z, a–z, 0–9, plus + and /. Both of those last two are hostile in a URL: + is read as a space in form-encoded data, and / ends a path segment. So the same RFC defines a second alphabet, base64url, which substitutes - and _ and usually drops the padding, since = also needs escaping.

JSON Web Tokens use base64url. So do most signed cookies and a lot of API identifiers. If a token decodes to garbage in one library and fine in another, the alphabet is the first thing to check — the two are not interchangeable, even though they look almost identical. The decoder here accepts both and normalises them, which is convenient but also means it will happily read input that a strict library would reject.

Why btoa() breaks on the word "café"

The browser's built-in btoa() does not take text. It takes a binary string, meaning every character must fit in one byte. Anything above U+00FF throws InvalidCharacterError, which is why accented characters and emoji fail and plain English does not — a bug that survives testing and then appears in production the first time somebody types their own name.

The fix is to convert the text to UTF-8 bytes first and hand those to btoa(). This tool does that with TextEncoder, so its output matches Python's base64.b64encode(s.encode("utf-8")) and Node's Buffer.from(s, "utf8").toString("base64") exactly. It also means the byte count in the stats above is not the character count: an accented Latin character is two bytes, most emoji are four.

Base64 is not encryption

It has no key and no secret. Anyone who sees the string can reverse it in a second, using this page. A password stored Base64-encoded in a config file is a plaintext password with a costume on. The same goes for JWT payloads: they are signed, not hidden, and anyone holding the token can read every claim inside it.

It is also not compression. Base64-encoding a zip makes it bigger, not smaller.

Where this tool stops

The line-wrapping question

MIME, the standard behind email attachments, limits lines to 76 characters. PEM, the format holding certificates and private keys, wraps at 64. Both exist because old mail transfer agents mangled long lines. Decoders are supposed to ignore line breaks, and most do — but a few strict parsers, especially in embedded and older enterprise systems, do not. If a Base64 blob copied out of an email fails to decode somewhere, the hard line breaks are the usual culprit.

Frequently asked questions

Why does my accented text break when I use btoa() but work here?

btoa() only accepts characters below U+0100, so anything with an accent or an emoji throws InvalidCharacterError. This tool converts your text to UTF-8 bytes first and encodes those, which is what Python and Node do by default.

What is the difference between Base64 and base64url?

The last two characters of the alphabet. Standard Base64 uses + and /, base64url uses - and _, and base64url normally has no = padding. JWTs and most URL-embedded tokens use base64url. The rest of the encoding is identical.

Is Base64 secure?

No. It is an encoding, not encryption — there is no key and anyone can reverse it instantly. Use it to move bytes through text-only channels, never to hide anything.

Why does my Base64 string end with = signs?

Because the input length was not a multiple of three. One trailing = means the last group held two bytes, two = means it held one. A string can never end in three padding characters.

Can I decode a string that is missing its padding?

Yes. The decoder here adds the padding back before decoding. Many strict libraries will not, which is the most common reason a base64url token fails elsewhere but works on this page.

Last updated September 19, 2026