About Base64 Converter
Base64 turns arbitrary bytes into 64 printable ASCII characters, so binary data can travel through channels that only reliably carry text - JSON string values, HTTP headers, email bodies, data: URLs. It takes three bytes at a time and emits four characters, which is why the output is always about 33% larger than the input.
It is not encryption and offers no confidentiality whatsoever. Anyone can decode it in one step, with no key. If you have found Base64 in a place where a secret should be, what you have found is a bug, not protection.
The variant matters more than anything else on this page. Standard Base64 (RFC 4648 §4) uses + and / for its last two characters and pads with =. Base64URL (§5) replaces those with - and _ and usually drops the padding, because +, / and = all have meaning in URLs and would need percent-encoding. JWTs, JWKs and most modern token formats use Base64URL, which is why pasting a JWT segment into a standard Base64 decoder so often fails.
Padding is the other common snag. Standard Base64 pads to a multiple of four characters with one or two = signs; Base64URL usually omits them. Strict decoders reject unpadded input, so if you are decoding a JWT segment by hand you may have to add the padding back yourself.
In the browser, btoa and atob predate Unicode and operate on single-byte values, so btoa('café') throws. Text has to be encoded to UTF-8 bytes first - the snippet below shows the correct round trip. Everything here runs locally and nothing is uploaded.
How to use the Base64 Converter
- Paste text to encode, or a Base64 string to decode - the direction is detected from what you paste.
- Pick the variant if it matters: standard for most things, Base64URL for JWT segments, tokens and anything that travels in a URL.
- If decoding fails, check for - and _ characters (that is Base64URL) and for missing = padding.
- Copy the result. Remember that decoded binary may not be printable text - a decoded PNG will look like noise, and that is correct.
Examples
-
Text to encode
Hello, developers! -
Base64 to decode
SGVsbG8sIGRldmVsb3BlcnMh
Base64 Converter in code
The same operation this tool performs, in the languages you are most likely to need it.
// btoa/atob are byte-oriented: btoa("café") throws.
const toBase64 = (str) =>
btoa(String.fromCharCode(...new TextEncoder().encode(str)));
const fromBase64 = (b64) =>
new TextDecoder().decode(
Uint8Array.from(atob(b64), (c) => c.charCodeAt(0))
);
// Base64URL <-> Base64
const toUrl = (b64) => b64.replace(/\+/g, "-").replace(/\//g, "_").replace(/=+$/, "");
const fromUrl = (u) => {
const b64 = u.replace(/-/g, "+").replace(/_/g, "/");
return b64.padEnd(b64.length + ((4 - (b64.length % 4)) % 4), "=");
};
console.log(fromBase64(fromUrl(jwtSegment)));
// Standard
const b64 = Buffer.from("hello world", "utf8").toString("base64");
const back = Buffer.from(b64, "base64").toString("utf8");
// Base64URL is a first-class encoding since Node 16
const url = Buffer.from("hello world").toString("base64url");
// Buffer's base64 decoder is lenient: it accepts Base64URL characters
// and missing padding, which is convenient but means it will NOT tell
// you that your input was the wrong variant.
import base64
b64 = base64.b64encode(b"hello world").decode()
raw = base64.b64decode(b64)
# Base64URL - note urlsafe_b64decode still REQUIRES padding
url = base64.urlsafe_b64encode(b"hello world").decode().rstrip("=")
def decode_b64url(s: str) -> bytes:
return base64.urlsafe_b64decode(s + "=" * (-len(s) % 4))
# validate=True makes b64decode reject non-alphabet characters
# instead of silently discarding them - use it on untrusted input.
base64.b64decode(b64, validate=True)
import java.util.Base64;
import java.nio.charset.StandardCharsets;
String b64 = Base64.getEncoder()
.encodeToString("hello world".getBytes(StandardCharsets.UTF_8));
byte[] raw = Base64.getDecoder().decode(b64);
// Base64URL, no padding - what JWT libraries use
String url = Base64.getUrlEncoder().withoutPadding()
.encodeToString("hello world".getBytes(StandardCharsets.UTF_8));
// getUrlDecoder() accepts unpadded input; getDecoder() does not
// accept - and _ at all.
# Encode without the line wrapping that base64 adds by default
printf '%s' "hello world" | base64 -w0 # GNU
printf '%s' "hello world" | base64 # macOS (no wrapping)
# Decode
echo "aGVsbG8gd29ybGQ=" | base64 -d
# Base64URL -> standard before decoding
echo "$SEGMENT" | tr '_-' '/+' | base64 -d 2>/dev/null
# The -w0 matters: wrapped output has newlines, and strict
# decoders elsewhere will reject it.
When you need this
- Decoding a JWT header or payload segment by hand.
- Reading a Base64 value out of a Kubernetes secret, a config file or an environment variable.
- Encoding a small image or font as a data: URL.
- Building an HTTP Basic Authorization header from user:password.
- Checking whether a $binary value from a MongoDB export decodes to the bytes you expect.
Common problems and what causes them
- btoa throws 'InvalidCharacterError' / 'string contains characters outside of the Latin1 range'
- btoa takes bytes, not text, so any character above U+00FF fails. Encode to UTF-8 first with TextEncoder - see the snippet above. The same applies in reverse: atob returns bytes and needs TextDecoder to become text again.
- Decoding fails on a JWT segment
- JWT segments are Base64URL: - and _ instead of + and /, with padding stripped. Translate the two characters and re-add = padding to a multiple of four before using a standard decoder.
- "Invalid base64" from a strict decoder
- Usually missing padding, or newlines from a wrapped command-line encode. GNU base64 wraps at 76 characters unless you pass -w0. Strip whitespace and pad to a multiple of four.
- Double-encoded values
- A string that decodes to something that still looks like Base64 was probably encoded twice - a common result of two layers of code each helpfully encoding. Decode again and see whether you get real bytes.
- Treating Base64 as a security measure
- It is a transport encoding with no key and no secrecy. Base64 in a config file, a cookie or a URL protects nothing - Kubernetes secrets, notably, are Base64-encoded and not encrypted at rest by default.
- Assuming decoded output is text
- Base64 carries arbitrary bytes. Decoding an encoded PNG, protobuf or encrypted blob gives binary that will render as replacement characters. That is the data being binary, not a decoding failure.
- Size growth in an unexpected place
- Base64 adds about 33%, so a 6 MB image becomes an 8 MB data: URL and a Base64 field in a database row is a third larger than the bytes. It also compresses worse than the original binary.
FAQ
- Is Base64 encryption?
- No. It is a reversible encoding with no key, decodable by anyone in one step. It provides zero confidentiality - if something secret is only Base64-encoded, it is effectively in plain text.
- What is the difference between Base64 and Base64URL?
- The last two characters of the alphabet and the padding. Standard Base64 uses + and / and pads with =; Base64URL uses - and _ and usually omits padding, because +, / and = are all significant in URLs. JWTs use Base64URL, which is why they fail in standard decoders.
- Why does my Base64 string end in one or two equals signs?
- That is padding. Base64 encodes three bytes into four characters, so an input length that is not a multiple of three leaves a remainder, padded to keep the output a multiple of four. One = means one leftover byte pair, two = means one leftover byte.
- Why does btoa fail on my string?
- Because it operates on bytes in the Latin-1 range and any character above U+00FF throws. Convert the text to UTF-8 bytes with TextEncoder first, then Base64 those bytes.
- How much larger does Base64 make data?
- About 33% - four output characters for every three input bytes, plus up to two padding characters. It also compresses less well than the original binary, so Base64 inside a gzipped response is bigger than the binary would have been.
- Is my data sent anywhere?
- No. Encoding and decoding happen in your browser with no network request, so pasting a real secret or token does not transmit it. The page works offline once loaded.
- URL-safe Base64?
- Use the UUID converter tab for URL-safe variants, or JWT decoder for token segments.
Related reading
- What is Base64 encoding?
- Base64URL vs Base64
- Encoding is not encryption
- Common encoding problems in APIs
- JWT decoder decodes all three segments
- Hex converter the other common encoding