Base64 Encoder & Decoder

Everything is encoded and decoded in your browser. No data is uploaded, logged, or stored.

What Base64 Actually Does

Base64 encodes arbitrary binary data as text using 64 printable characters. It exists because a great many systems — email headers, JSON documents, URLs, HTTP headers, XML attributes — are specified to carry text, and handing them raw bytes leads to corruption the moment a byte happens to look like a control character or a delimiter.

The mechanism is simple arithmetic. Three bytes are 24 bits; 24 bits split evenly into four 6-bit groups; each 6-bit group indexes one of 64 characters. Type Man into our binary translator and you get 01001101 01100001 01101110; regroup those 24 bits as 010011 010110 000101 101110 and you get indexes 19, 22, 5 and 46, which are T, W, F and u, so the Base64 output is TWFu. That three-to-four ratio is why Base64 output is always about 33% larger than its input, and why the encoded length is always a multiple of four once padding is applied. When the input length is not divisible by three, the final group is padded with = characters to complete the block.

Base64 is not encryption. It is an encoding, and it is trivially reversible by anyone — this page does it without a key. Encoding a password or an API key in Base64 provides no protection whatsoever; it only makes the value slightly less obvious to a casual reader. If something must stay secret, it needs to be encrypted.

Base64 vs Base64URL

Standard Base64 uses + and / as its final two characters. Both are problematic in URLs: / is a path separator and + is interpreted as a space in query strings. Base64URL, defined in RFC 4648 §5, substitutes - and _ instead, and usually drops the = padding because = also carries meaning in query strings.

AspectBase64Base64URL
Character 62+-
Character 63/_
Padding=, usually requiredUsually omitted
Safe in a URLNoYes
Typical useEmail, data URIs, HTTP Basic authJWTs, JWKs, URL parameters

This tool detects which alphabet your input uses when decoding, and tells you rather than silently normalising it. A string containing characters from both alphabets is rejected outright, because that is not valid in either variant and almost always means two encoded values were concatenated by mistake.

The UTF-8 Trap

This is the defect that separates a correct Base64 tool from a broken one. In JavaScript, the built-in btoa() function operates on "binary strings" — strings in which every character represents exactly one byte. Any character above U+00FF throws an exception. Pass it an emoji, a Chinese character, or even an accented Latin letter, and it fails.

The correct approach is to convert the text to UTF-8 bytes first, then Base64-encode those bytes. That is what this tool does, which is why Grüße and rocket emoji encode and decode without corruption. Many online encoders skip this step and either throw an error or, worse, silently mangle the text.

// Broken — throws on any non-ASCII input
btoa("Grüße");

// Correct — encode to UTF-8 bytes first
const bytes = new TextEncoder().encode("Grüße");
btoa(String.fromCharCode(...bytes));

The byte counts shown above the output make this visible. A rocket emoji is a single character to a human but four bytes in UTF-8, and it is the byte count that determines the encoded length.

Where You Will Meet Base64

The Base64 Alphabet

The 64 characters are not arbitrary — they were chosen because they survive every transport layer that mangles binary data. The full standard alphabet maps values 0–63 to A–Z, a–z, 0–9, +, and /. Base64URL replaces + with - and / with _ so the result is safe inside URLs, filenames, and XML attributes.

ValueCharValueCharValueCharValueChar
0A16Q32g48w
1B17R33h49x
2C18S34i50y
3D19T35j51z
4E20U36k520
5F21V37l531
6G22W38m542
7H23X39n553
8I24Y40o564
9J25Z41p575
10K26a42q586
11L27b43r597
12M28c44s608
13N29d45t619
14O30e46u62+ / -
15P31f47v63/ / _

Values 62 and 63 show both variants: standard / base64url. Every other character is the same in both alphabets.

How to Base64 Encode in Every Language

Every major language has Base64 built in, but the API names differ and the UTF-8 trap exists in most of them. Here are correct examples that handle Unicode text.

JavaScript / Node.js

// Browser
const encoded = btoa(String.fromCharCode(
  ...new TextEncoder().encode("Grüße 🚀")
));

// Node.js
const encoded = Buffer.from("Grüße 🚀").toString("base64");

Python

import base64
encoded = base64.b64encode("Grüße 🚀".encode("utf-8")).decode("ascii")
decoded = base64.b64decode(encoded).decode("utf-8")

Java

import java.util.Base64;
String encoded = Base64.getEncoder()
    .encodeToString("Grüße 🚀".getBytes("UTF-8"));
String decoded = new String(
    Base64.getDecoder().decode(encoded), "UTF-8");

Bash / Command Line

# Encode
echo -n "Grüße 🚀" | base64

# Decode
echo "R3LDvMOfZSDwn5qA" | base64 --decode

Go

import "encoding/base64"
encoded := base64.StdEncoding.EncodeToString(
    []byte("Grüße 🚀"))

Common Base64 Mistakes

These are the errors that cause real bugs in production. Each one has appeared in code reviews and incident reports.

Reading Padding

The = characters at the end are not decoration; they signal how many bytes the final group actually holds. One = means the last group decodes to two bytes, and two = means it decodes to one. Because that information is recoverable from the string length alone, many systems omit padding entirely — which is why base64url values in JWTs rarely have any.

This decoder accepts input with or without padding and restores it internally. It does reject a string whose length leaves a remainder of one when divided by four, because no valid Base64 string can have that length; encountering it means characters were lost or added in transit.

Base64 in Cron Jobs and Automation

Passing binary data or multi-line config through environment variables and shell scripts is fragile — a stray newline or special character breaks quoting. Base64 solves this cleanly: encode the value, pass the safe ASCII string, decode on the other side. This pattern is common in CI/CD pipelines, Docker entrypoints, and cron jobs that need to pass structured data to a script without worrying about shell escaping.

# Store a multi-line config as a single env var
export CONFIG_B64=$(echo '{"db":"prod","replicas":3}' | base64)

# In the script, decode it
echo "$CONFIG_B64" | base64 --decode | jq .

Decoding Binary Data

Not everything encoded in Base64 is text. Images, compressed archives, and cryptographic keys are all commonly Base64-encoded, and decoding them produces bytes that are not valid UTF-8. Rather than displaying replacement characters and pretending it worked, this tool detects that case, tells you the content is binary, and shows a hex dump of the bytes instead. The reported byte count is accurate either way.

Base64 Size Calculator

Because every 3 input bytes become 4 output characters, you can predict the encoded size before running the encoder. For an input of n bytes, the padded output is 4 × ⌈n / 3⌉ characters. Without padding, it is ⌈4n / 3⌉ characters. In practice, Base64 adds about 33-37% overhead depending on padding and line wrapping.

Input sizeEncoded size (padded)Overhead
1 byte4 chars+300%
3 bytes4 chars+33%
100 bytes136 chars+36%
1 KB1,368 chars+34%
1 MB1,398,104 chars+33%

This overhead matters when embedding images as data URIs in CSS or HTML. A 10 KB icon becomes about 13.3 KB as Base64 — acceptable for small assets, but impractical for large images where a separate HTTP request is cheaper. Converting between data formats? Try our YAML↔JSON converter or XML↔JSON converter for structured data instead.

Frequently Asked Questions

Is Base64 a form of encryption?
No. It is a reversible encoding with no key involved, and anyone can decode it instantly. Base64 protects data from corruption in text-only channels, not from being read. Never use it to conceal secrets.
Why is my encoded output longer than the input?
Base64 represents every 3 bytes as 4 characters, so output is about 33% larger, plus up to 2 padding characters. That overhead is the price of representing arbitrary bytes using only printable text.
What is the difference between Base64 and Base64URL?
They differ in two characters and in padding. Base64 uses "+" and "/", which have special meaning in URLs; Base64URL substitutes "-" and "_" and usually omits the "=" padding, making the result safe to place directly in a URL or an HTTP header.
Why do some tools fail on emoji or accented characters?
Because they pass the text straight to JavaScript's btoa(), which only accepts characters in the range U+0000 to U+00FF and throws on anything else. The correct approach encodes the text to UTF-8 bytes first, which is what this tool does.
Can I decode a Base64 string without padding?
Yes. Padding is recoverable from the string length, so this decoder restores it automatically. Unpadded input is normal for JWTs and other base64url values.
Is my data sent to a server?
No. Encoding and decoding happen entirely in your browser using built-in JavaScript functions. Nothing is transmitted or stored, and the page works offline once loaded.