DD
DevDash
encodingbase64javascriptpython

Base64 Encoding and Decoding: The Complete Guide

Base64 is one of those things you use constantly but might never have properly learned. You've seen it in data URIs, API authentication, email attachments, and JWT tokens. Let's understand what it actually does, when to use it, and how to work with it in every common language.

What is Base64?

Base64 is a binary-to-text encoding scheme. It takes binary data (bytes) and converts it into a string using only 64 "safe" ASCII characters: A-Z, a-z, 0-9, +, /, and = for padding.

Why does this exist? Many systems (email, URLs, JSON, XML) were designed to handle text, not binary data. If you try to shove raw bytes into a JSON string, you'll get corruption or errors. Base64 lets you represent any binary data as plain ASCII text that can travel safely through text-based systems.

The tradeoff: Base64 encoding increases the size of the data by about 33%. Three bytes of input become four characters of output. This is why you shouldn't Base64-encode large files unless you have no other choice.

When to use Base64

Good uses:

  • Embedding small images in HTML/CSS (data:image/png;base64,...)
  • Sending binary data in JSON payloads
  • HTTP Basic Authentication (Authorization: Basic base64(user:pass))
  • Email attachments (MIME encoding)
  • Storing binary blobs in text-only fields

Bad uses:

  • Encryption (Base64 is NOT encryption -- it's trivially reversible)
  • Compressing data (it makes data bigger, not smaller)
  • Obfuscating secrets (anyone can decode it instantly)
  • Large files (use proper binary transfer instead)

Code examples

JavaScript (Browser)

// Encode
const encoded = btoa('Hello, World!');
console.log(encoded); // "SGVsbG8sIFdvcmxkIQ=="

// Decode
const decoded = atob('SGVsbG8sIFdvcmxkIQ==');
console.log(decoded); // "Hello, World!"

Watch out: btoa() only works with ASCII strings. For Unicode:

// Encode Unicode string
function encodeUnicode(str) {
  return btoa(encodeURIComponent(str).replace(
    /%([0-9A-F]{2})/g,
    (_, p1) => String.fromCharCode(parseInt(p1, 16))
  ));
}

// Or the modern way (Node.js / modern browsers)
const encoded = btoa(String.fromCodePoint(
  ...new TextEncoder().encode('Hello ')
));

JavaScript (Node.js)

// Encode
const encoded = Buffer.from('Hello, World!').toString('base64');

// Decode
const decoded = Buffer.from(encoded, 'base64').toString('utf-8');

// Encode a file
const fs = require('fs');
const fileBase64 = fs.readFileSync('image.png').toString('base64');

Python

import base64

# Encode
encoded = base64.b64encode(b'Hello, World!').decode('utf-8')
print(encoded)  # "SGVsbG8sIFdvcmxkIQ=="

# Decode
decoded = base64.b64decode('SGVsbG8sIFdvcmxkIQ==').decode('utf-8')
print(decoded)  # "Hello, World!"

# Encode a file
with open('image.png', 'rb') as f:
    file_base64 = base64.b64encode(f.read()).decode('utf-8')

Command line (Bash)

# Encode
echo -n 'Hello, World!' | base64
# SGVsbG8sIFdvcmxkIQ==

# Decode
echo 'SGVsbG8sIFdvcmxkIQ==' | base64 -d
# Hello, World!

# Encode a file
base64 image.png > image.b64

# Decode a file
base64 -d image.b64 > image_restored.png

Important: Use echo -n (no newline) when encoding. Without -n, you'll encode the newline character too, giving you a different result.

Go

import "encoding/base64"

// Encode
encoded := base64.StdEncoding.EncodeToString([]byte("Hello, World!"))

// Decode
decoded, err := base64.StdEncoding.DecodeString(encoded)

URL-safe Base64

Standard Base64 uses + and /, which have special meanings in URLs. URL-safe Base64 replaces them:

StandardURL-safe
+-
/_
= (padding)Often omitted

This variant is used in JWTs, data URLs in some contexts, and anywhere Base64 data appears in a URL.

import base64

# URL-safe encode
encoded = base64.urlsafe_b64encode(b'Hello!').decode('utf-8')
# "SGVsbG8h"

# URL-safe decode
decoded = base64.urlsafe_b64decode('SGVsbG8h').decode('utf-8')

// Node.js URL-safe encoding
const encoded = Buffer.from('Hello!')
  .toString('base64')
  .replace(/\+/g, '-')
  .replace(/\//g, '_')
  .replace(/=+$/, '');

Common mistakes

1. Thinking Base64 is encryption

This comes up constantly. Someone Base64-encodes an API key and thinks it's "hidden." It's not. Base64 is a reversible encoding, not encryption. Anyone can decode it instantly. If you need to protect data, use actual encryption (AES, RSA, etc.).

2. Forgetting about the 33% size increase

A 1MB image becomes approximately 1.33MB when Base64-encoded. For small images (icons, logos under 10KB), this is fine and even desirable for reducing HTTP requests. For large files, it's wasteful.

3. Double-encoding

If you encode something that's already Base64-encoded, you get a valid but wrong result. The decoded output will be the Base64 string, not the original data. Always know whether your input is raw or already encoded.

4. Newline handling

Some Base64 implementations insert newlines every 76 characters (per the MIME spec). Others don't. If you're comparing Base64 strings, strip newlines first:

clean = encoded.replace('\n', '').replace('\r', '')

5. Padding confusion

Base64 output length must be a multiple of 4. If the encoded string doesn't divide evenly, = padding characters are added. Some implementations strip this padding. If you get decode errors, try adding the padding back:

function addPadding(base64) {
  const pad = base64.length % 4;
  if (pad) return base64 + '='.repeat(4 - pad);
  return base64;
}

Quick encode/decode without code

If you need to quickly encode or decode a Base64 string and don't want to open a terminal, textshifter.com/tools/base64 handles both standard and URL-safe variants in the browser.

How Base64 works internally

The encoding process:

  1. Take the input bytes and concatenate their binary representations
  2. Split into groups of 6 bits (since 2^6 = 64)
  3. Map each 6-bit value to a character in the Base64 alphabet
  4. Add = padding if the last group has fewer than 6 bits

Example with "Hi":

'H'        'i'
01001000   01101001

Split into 6-bit groups:
010010  000110  1001xx

Map to Base64 alphabet:
S       G       k=

Result: "SGk="

The = indicates one byte of padding was needed to complete the last 6-bit group.

Summary

Base64 is a simple encoding that converts binary data to text-safe ASCII. Use it for embedding small binaries in text formats, not for security. Remember the 33% overhead, use URL-safe variants when the data goes in URLs, and never confuse encoding with encryption.

Related Tools

Want API access + no ads? Pro coming soon.