UUID Studio

Base64 Converter

Encode and decode UTF-8 text with standard Base64.

  • 🔒 No data stored or uploaded
  • âš¡ 100% client-side
  • 🆓 Free, no account

Need more than one tool at a time? Open the full Workbench - or press Ctrl+K to jump to any tool.

Hash, HMAC, AES-GCM/CBC + RSA-OAEP, codecs, JWT decoding, UUID v4, and secure random - all client-side. JWTs use Base64URL (three segments), not a single MIME Base64 block - use Decode JWT below, not raw Base64 decode.

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

  1. Paste text to encode, or a Base64 string to decode - the direction is detected from what you paste.
  2. Pick the variant if it matters: standard for most things, Base64URL for JWT segments, tokens and anything that travels in a URL.
  3. If decoding fails, check for - and _ characters (that is Base64URL) and for missing = padding.
  4. 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.

JavaScript - the correct UTF-8 round trip
// 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)));
Node.js
// 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.
Python
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)
Java
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.
Command line
# 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