How to Decode a Base64 String (with Examples)

Practical recipes for decoding Base64 in every language and environment you're likely to encounter.

🔓🧩💻

TL;DR: Use atob() in browsers, Buffer.from(str, "base64") in Node.js, or base64.b64decode() in Python. Watch out for Unicode text — plain atob() can't handle it, so use TextDecoder instead.

Just Give Me the Code

Sometimes you don't want the backstory — you just want to decode a Base64 string and move on with your life. I respect that. Here's a cheat sheet for every popular language:

JavaScript (Browser)

// Simple ASCII decoding
const decoded = atob("SGVsbG8gV29ybGQ=");
console.log(decoded); // "Hello World"

// For Unicode strings (emojis, accented chars, etc.)
function decodeBase64Unicode(str) {
  const bytes = atob(str);
  const uint8 = new Uint8Array(bytes.length);
  for (let i = 0; i < bytes.length; i++) {
    uint8[i] = bytes.charCodeAt(i);
  }
  return new TextDecoder().decode(uint8);
}

Node.js

const decoded = Buffer.from("SGVsbG8gV29ybGQ=", "base64").toString("utf-8");
// "Hello World"

// URL-safe Base64
const urlSafe = Buffer.from("SGVsbG8_V29ybGQ", "base64url").toString("utf-8");

Python

import base64
decoded = base64.b64decode("SGVsbG8gV29ybGQ=").decode("utf-8")
# "Hello World"

Command Line

# macOS
echo "SGVsbG8gV29ybGQ=" | base64 -D

# Linux
echo "SGVsbG8gV29ybGQ=" | base64 -d
📋 Your Base64 decoding cheat sheet — bookmark this!
😄

Dev Joke: I told my friend I could decode Base64 in my head. He said "dGhhdCdzIG5vdCBpbXByZXNzaXZl". I said, "that's not impressive." Wait...

The Unicode Trap with atob()

Here's where things get spicy. The browser's atob() function has a well-known limitation: it only handles ASCII text. If the original data had emoji, accented characters, or any non-English text, atob() will either produce garbage or throw an error.

Why? Because atob() treats each byte as one character, but Unicode characters can be multiple bytes. It's like trying to read a Chinese novel one letter at a time — the individual pieces don't make sense without the full picture.

The fix is to decode the bytes first, then interpret them as UTF-8:

function base64ToText(base64) {
  const binaryString = atob(base64);
  const bytes = Uint8Array.from(binaryString, c => c.charCodeAt(0));
  return new TextDecoder("utf-8").decode(bytes);
}

// Now emojis work!
base64ToText("8J+agCBIZWxsbyBXb3JsZA==");
// "🚀 Hello World"
💡

Rule of thumb: If you're only dealing with English text and numbers, atob() is fine. The moment you have any chance of emoji, accented letters, or non-Latin characters, use the TextDecoder approach.

Decoding Base64 Images

Getting a Base64-encoded image from an API? Here's how to handle it:

Display in the Browser

// If you have a full data URL, just set it directly
const dataUrl = "data:image/png;base64,iVBORw0KGgoAAAANSUhEUg...";
document.getElementById("myImage").src = dataUrl;

// If you only have the raw Base64 string
const base64 = "iVBORw0KGgoAAAANSUhEUg...";
const img = document.createElement("img");
img.src = `data:image/png;base64,${base64}`;
document.body.appendChild(img);

Save to File in Node.js

const fs = require("fs");
const buffer = Buffer.from(base64Image, "base64");
fs.writeFileSync("output.png", buffer);

Convert to Blob for Uploading

function base64ToBlob(base64, mimeType) {
  const binaryString = atob(base64);
  const bytes = new Uint8Array(binaryString.length);
  for (let i = 0; i < binaryString.length; i++) {
    bytes[i] = binaryString.charCodeAt(i);
  }
  return new Blob([bytes], { type: mimeType });
}

const blob = base64ToBlob(imageData, "image/png");
const formData = new FormData();
formData.append("file", blob, "photo.png");
fetch("/upload", { method: "POST", body: formData });
🖼️ From mystery text to actual image — the magic of decoding

Dealing with URL-Safe Base64

You'll run into URL-safe Base64 a lot, especially in JWTs and query parameters. It swaps + for - and / for _, and often drops the = padding. The browser's atob() doesn't handle this natively, so you need to convert first:

function decodeUrlSafeBase64(str) {
  let base64 = str.replace(/-/g, "+").replace(/_/g, "/");
  const padding = base64.length % 4;
  if (padding === 2) base64 += "==";
  else if (padding === 3) base64 += "=";
  return atob(base64);
}

Is This String Even Base64?

There's no foolproof way to detect Base64 because any ASCII string could theoretically be valid. But you can do a reasonable check:

function isLikelyBase64(str) {
  if (!/^[A-Za-z0-9+/]*={0,2}$/.test(str)) return false;
  if (str.length % 4 !== 0) return false;
  try { atob(str); return true; }
  catch { return false; }
}

Common Errors and Quick Fixes

⚠️

Watch out: When decoding binary data (images, PDFs), never treat the result as a string at any point. Use Uint8Array or Buffer throughout the entire pipeline, or you'll get corrupted files.

Try It Yourself

Paste any Base64 string into our decoder to instantly see the original text. Supports standard and URL-safe variants, handles Unicode correctly, and runs entirely in your browser.

Open Base64 Decoder →