Back to tool
Tools / Base64
Encode / Decode

Base64 Encoder & Decoder

Encode text or a local file to Base64 and back, with proper UTF-8 handling, the URL-safe alphabet, and the byte overhead shown.

Base64 Workspace

ready
Any Unicode text. Converted to UTF-8 bytes before encoding, so accents and emoji round-trip correctly.
The file is read in your browser with FileReader. It is never uploaded. Files over 2 MB are rejected to keep the page responsive.
Base64 output
Input bytes
Output bytes
Overhead
Padding
You might also need
Unix Timestamp ConverterNumber Base ConverterSlug Generator

What Base64 actually does

Base64 maps arbitrary binary data onto 64 printable ASCII characters, so that data can survive a channel built for text. It takes three bytes at a time — 24 bits — and re-slices them into four six-bit groups. Each six-bit group indexes a character from the alphabet A–Z a–z 0–9 + /, which has exactly 64 entries.

The mapping
3 bytes (24 bits) → 4 characters (4 × 6 bits)

Output length = 4 × ceil(input bytes ÷ 3)

That ratio is the whole reason Base64 output is roughly 33% larger than the input. Four characters carry what three bytes carried. There is no compression and no cleverness — it is a fixed-width re-encoding, and the size penalty is the price of using only safe characters.

Base64 is not encryption. It provides zero confidentiality. Anyone can decode it instantly — this page will do it in one click. It is not obfuscation either; the character distribution is instantly recognisable and every scanner in existence decodes it automatically. Storing a password or an API key Base64-encoded is storing it in plaintext with an extra step, and it regularly appears in incident reports for exactly that reason.

Padding, and why = appears

Input is processed three bytes at a time, but real data rarely divides evenly by three. When the final group is short, the encoder pads with zero bits and appends = characters to record how many bytes were actually present.

Final groupOutput charactersPaddingExample
3 bytes4noneabcYWJj
2 bytes3 + 1 pad=abYWI=
1 byte2 + 2 pad==aYQ==

Padding is optional in some contexts — JWTs strip it, and so do several URL-safe variants — because the length remainder is enough to reconstruct it. A Base64 string whose length leaves a remainder of 1 when divided by 4 is impossible and always indicates truncation. This decoder detects that case and tells you rather than returning garbage.

Standard versus URL-safe

The standard alphabet's last two characters, + and /, are both problematic in URLs: + is interpreted as a space in query strings, and / is a path separator. RFC 4648 defines a URL-safe variant that substitutes - and _ respectively.

Index 62Index 63VariantUsed by
+/Standard (RFC 4648 §4)Email, data URIs, HTTP Basic auth
-_URL-safe (RFC 4648 §5)JWTs, URL parameters, filenames

The decoder above accepts both automatically — it normalises - and _ back before decoding, so you never have to know which variant you were handed.

A worked example

Encoding the three characters Man:

  1. ASCII bytes: M = 77, a = 97, n = 110
  2. As binary: 01001101 01100001 01101110
  3. Re-split into six-bit groups: 010011 010110 000101 101110
  4. As decimal: 19, 22, 5, 46
  5. Index the alphabet: T, W, F, u
  6. Result: TWFu

Three bytes in, four characters out, no padding — because 3 divides evenly by 3. Drop Man into the encoder above and you will get exactly that.

The Unicode problem

Most browser-based Base64 tools call JavaScript's built-in btoa() directly on the input string. That function only accepts characters in the range U+0000 to U+00FF — it throws an InvalidCharacterError on anything else, or silently mangles it depending on the path taken.

The correct approach converts the string to UTF-8 bytes first, then Base64-encodes those bytes:

Correct Unicode handling
const bytes = new TextEncoder().encode(str);
const b64 = btoa(String.fromCharCode(...bytes));

This tool does that, which is why café and emoji round-trip cleanly. It also explains why the byte count for accented text exceeds the character count: é is two bytes in UTF-8, and most emoji are four.

Where Base64 is genuinely the right tool

Frequently asked questions

Is Base64 secure?
No, in any sense of the word. It offers no confidentiality, no integrity and no authentication. It is a transport encoding. If you need secrecy use encryption; if you need integrity use a MAC or signature. Base64 sometimes wraps encrypted data so the ciphertext can travel through a text channel — that is the encryption doing the work, not the encoding.
Why is my encoded string bigger than the file?
Because four characters carry three bytes, a fixed 4:3 ratio, plus up to two padding characters. Expect about 33% growth, or 37% once MIME line breaks are added. This is the main argument against data URIs for anything but small assets — a 100 KB image becomes roughly 133 KB of markup that cannot be cached separately.
My decoded output is full of question-mark diamonds
The decoded bytes are not valid UTF-8. Almost always this means the original data was binary — an image, a PDF, a compressed archive — rather than text. Base64 will faithfully return those bytes, but rendering them as text produces replacement characters. The tool warns you when it detects this.
Can I decode a JWT here?
You can decode its parts. Split the token on the dots and paste the first or second segment — both are URL-safe Base64 and will decode to JSON. What you cannot do here is verify the signature, which requires the secret or public key. Never trust an unverified token's contents.
Does the order of my options matter?
Slightly. Padding is stripped after encoding, and line wrapping is applied last. If you strip padding and wrap simultaneously, the wrap counts the shortened string. For MIME email use padding on and wrapping on; for JWTs use URL-safe on, padding off, wrapping off.
Is my data uploaded when I select a file?
No. The file is read with the browser's FileReader API, which operates entirely on your machine. No network request is made at any point. You can confirm this by watching your browser's network tab while selecting a file.

When Base64 is the wrong choice

The 33% size penalty is not free, and there are situations where it costs more than it saves.

SituationProblemBetter approach
Large images as data URIsCannot be cached separately, blocks HTML parsing, inflates every page loadNormal image request with cache headers; inline only under ~5 KB
Storing binary in a database33% more storage, plus encode/decode cost on every read and writeA native binary column type
Hiding a secretProvides no protection at allEncryption, or a secrets manager
Large file uploadsMemory pressure and needless CPU on both endsMultipart form data or a direct binary body
Compressing dataBase64 makes data larger, never smallergzip or brotli — and compress before encoding, never after

That last row matters more than it looks. Base64 output has high entropy relative to its alphabet and compresses poorly, so gzipping a Base64 string recovers far less than gzipping the original bytes and then encoding. The correct order is always compress, then encode.

Related variants worth knowing

Base64 is one of a family. Base32 uses a 32-character alphabet, is case-insensitive, and grows data by 60% — used where humans must transcribe strings by hand, such as TOTP authenticator seeds. Base58 drops the visually ambiguous characters (0, O, I, l) and is used in Bitcoin addresses for the same reason. Base16 is just hexadecimal, doubling the size but trivially readable, which is why hashes are printed that way.

The trade-off across all of them is identical: a smaller alphabet means safer, more transcribable output and more size overhead. Base64 sits at the point where the alphabet is still safe in most text channels while the penalty stays at a third.

Related tools