Skip to content
DevPenh

Base64 Encoder & Decoder

Encode text or files to Base64, or decode Base64 back to text. Handles UTF-8 correctly, supports the URL-safe alphabet used in JWTs, and shows binary results as hex.

Direction
Alphabet

Text is encoded as UTF-8 first. URL-safe uses - and _ instead of + and /, as in JWTs.

File to Base64

Encode an image or any other file, for example to embed it as a data URI. The file is read in your browser and is not uploaded. The alphabet and padding settings above apply.

What Base64 is

Base64 (RFC 4648) writes any bytes using 64 safe characters: A–Z, a–z, 0–9, + and /. Every 3 bytes become 4 characters, so the result is about a third larger than the input. It is an encoding, not encryption: anyone can decode it, so never treat Base64 as a way to hide passwords or tokens.

Standard vs URL-safe, and padding

VariantCharacters 62 and 63PaddingUsed in
Standard+ /Usually =Email (MIME), data URIs, most APIs
URL-safe (Base64URL)- _Often omittedJWTs, URLs and file names

The bytes ??>> encode to Pz8+Pg== in standard Base64 and Pz8-Pg in unpadded Base64URL. The decoder here accepts both, with or without padding, and ignores line breaks.

Common mistakes

  • btoa is not UTF-8 aware. In JavaScript, btoa("café") returns Y2Fm6Q==, which is Latin-1, not UTF-8, and btoa("✓") throws InvalidCharacterError. Encode the text to UTF-8 bytes first (examples below). This tool always uses UTF-8: café ✓ becomes Y2Fmw6kg4pyT.
  • A trailing newline from echo. echo 'hello world' | base64 prints aGVsbG8gd29ybGQK, because echo adds a newline. Use printf to get aGVsbG8gd29ybGQ=.
  • Missing padding in Python. base64.urlsafe_b64decode("Pz8-Pg") raises binascii.Error: Incorrect padding. Add the padding back before decoding.
  • Decoding gives unreadable text. The data may be binary (an image, compressed or encrypted data) rather than text. This tool then shows the bytes as hex instead of garbled characters.

Base64 in code

Tested with Node.js 24, Python 3.9 and macOS's base64:

// Node.js
Buffer.from("café ✓").toString("base64");     // "Y2Fmw6kg4pyT"
Buffer.from("??>>").toString("base64url");     // "Pz8-Pg"
Buffer.from("Pz8-Pg", "base64url").toString(); // "??>>"

# Python
import base64
base64.b64encode("café ✓".encode()).decode()   # 'Y2Fmw6kg4pyT'
s = "Pz8-Pg"
base64.urlsafe_b64decode(s + "=" * (-len(s) % 4))  # b'??>>'

# Shell
printf 'hello world' | base64            # aGVsbG8gd29ybGQ=
echo 'aGVsbG8gd29ybGQ=' | base64 -d      # hello world

Files and data URIs

The file section encodes any file you choose and builds a data URI such as data:image/png;base64,…, which can be used in CSS or HTML for small icons. For anything larger than a few kilobytes a normal file is usually better, because Base64 makes it bigger and it cannot be cached separately.

To read a JWT, use the JWT decoder: it splits the token, decodes the Base64URL parts and explains the claims.