Encoding

How to Decode Base64: Strings, Images, Files, and JWT Tokens

2026-05-25 · 9 min read · Decode Base64 free →

You are looking at a string that starts with iVBORw0KGgoAAAANSUhEUg or SGVsbG8sIFdvcmxkIQ== or eyJhbGciOiJIUzI1NiJ9. It might be in an API response, a database column, an email source, a configuration file, or a log entry. It is Base64-encoded data — and decoding it reveals what it actually contains. This guide shows you how to decode any Base64 string in under a minute, whether it is a string, an image, a file, or a JWT token.

How to Decode a Base64 String Online (Fastest Method)

For any text-based Base64 string, use ToolPry's Base64 Decoder. Paste the Base64 string into the input field, click Decode, and the decoded output appears immediately. It handles UTF-8 text, URL-safe Base64 (with - and _ instead of + and /), and automatically adds missing padding if the string length is not a multiple of 4. All processing happens in your browser — the string never leaves your device.

If your string ends with = or ==, those are padding characters — include them in the input. If the decoded output is unreadable gibberish (random bytes), the encoded data is binary (an image, PDF, or other file) rather than text — follow the image or file decoding instructions below.

How to Decode a Base64 Image

Base64 images are common in API responses, HTML files with embedded images, and CSS with data URL backgrounds. They look like long strings starting with iVBORw0KGgo (PNG) or /9j/4AAQSkZJRgAB (JPEG) or PHN2Zy (SVG). To view the image, you need to render it, not just decode the text.

Method 1: Data URL in your browser (fastest)

Open a new browser tab and paste the following into the address bar, replacing [BASE64] with your encoded string:

data:image/png;base64,[BASE64]

Press Enter. The browser renders the image directly. Change image/png to image/jpeg, image/gif, or image/webp depending on the image type. If you do not know the type, try PNG first — it is the most common for embedded images in APIs.

Method 2: HTML file

<!-- Save as image.html and open in browser -->
<img src="data:image/png;base64,iVBORw0KGgoAAAANSUhEUgAAAAEAAAABCAYAAAAfFcSJAAAADUlEQVR42mNk+M9QDwADhgGAWjR9awAAAABJRU5ErkJggg==" alt="Decoded image">

Method 3: JavaScript (save to file)

// Paste in browser console to download the decoded image
function b64toBlob(b64, mimeType) {
  const bytes = atob(b64);
  const arr = new Uint8Array(bytes.length);
  for (let i = 0; i < bytes.length; i++) arr[i] = bytes.charCodeAt(i);
  return new Blob([arr], { type: mimeType });
}

const b64 = 'iVBORw0KGgoAAAA...'; // your base64 string
const blob = b64toBlob(b64, 'image/png');
const url = URL.createObjectURL(blob);
const a = document.createElement('a');
a.href = url; a.download = 'image.png'; a.click();

Method 4: Python (save to file)

import base64

b64_string = "iVBORw0KGgoAAAANSUhEUg..."  # your base64 string
image_data = base64.b64decode(b64_string)

with open("output.png", "wb") as f:
    f.write(image_data)

print("Image saved to output.png")

How to Decode a Base64 JWT Token

JWT (JSON Web Token) tokens have three Base64URL-encoded sections separated by dots: header.payload.signature. You can decode the header and payload to read their contents without any library — the payload contains the user claims (user ID, email, roles, expiry time).

Fastest method: browser console one-liner

// Paste in browser console — replace TOKEN with your JWT
const token = 'eyJhbGciOiJIUzI1NiIsInR5cCI6IkpXVCJ9.eyJzdWIiOiJ1c2VyXzEyMyIsImVtYWlsIjoibWFyaWFAZXhhbXBsZS5jb20iLCJleHAiOjE3NDYwODY0MDB9.SflKxwRJSMeKKF';

// Decode header (part 1)
JSON.parse(atob(token.split('.')[0]));
// {alg: "HS256", typ: "JWT"}

// Decode payload (part 2) — has the actual data
const payload = JSON.parse(atob(token.split('.')[1].replace(/-/g, '+').replace(/_/g, '/')));
console.log(payload);
// {sub: "user_123", email: "maria@example.com", exp: 1746086400}

// Check expiry
console.log('Expires:', new Date(payload.exp * 1000).toLocaleString());
console.log('Expired:', payload.exp < Date.now() / 1000);

Understanding the JWT payload fields

FieldMeaningHow to read it
expExpiry timeUnix timestamp (seconds) — convert with Timestamp Converter
iatIssued atUnix timestamp when token was created
subSubjectUsually the user ID
issIssuerThe authentication server that created the token
audAudienceThe API or service this token is for

How to Decode Base64 in Different Languages

JavaScript (Browser)

// Standard Base64 → string
const decoded = atob('SGVsbG8sIFdvcmxkIQ==');
// "Hello, World!"

// URL-safe Base64 (JWTs use this variant)
const urlSafe = 'SGVsbG8sIFdvcmxkIQ';  // may be missing padding
const standard = urlSafe.replace(/-/g, '+').replace(/_/g, '/');
const padded = standard + '=='.slice((standard.length + 3) % 4);
const decoded2 = atob(padded);
// "Hello, World!"

// Base64 to Uint8Array (for binary data)
function b64ToBytes(b64) {
  return Uint8Array.from(atob(b64), c => c.charCodeAt(0));
}

Node.js

// Standard text decoding
const decoded = Buffer.from('SGVsbG8sIFdvcmxkIQ==', 'base64').toString('utf8');
// "Hello, World!"

// Binary file decoding
const fs = require('fs');
const b64 = fs.readFileSync('encoded.txt', 'utf8').trim();
const binary = Buffer.from(b64, 'base64');
fs.writeFileSync('output.bin', binary);

// URL-safe Base64
const urlSafe = 'SGVsbG8sIFdvcmxkIQ';
const decoded2 = Buffer.from(urlSafe, 'base64url').toString('utf8');

Python

import base64

# Standard Base64 → string
encoded = b'SGVsbG8sIFdvcmxkIQ=='
decoded = base64.b64decode(encoded).decode('utf-8')
print(decoded)  # "Hello, World!"

# URL-safe Base64 (JWTs, URLs)
url_safe = 'SGVsbG8sIFdvcmxkIQ'
# Add padding if missing
padded = url_safe + '==' * ((-len(url_safe)) % 4 or 0)  # simpler: url_safe + '=='
decoded2 = base64.urlsafe_b64decode(padded).decode('utf-8')

# Decode Base64 file (image, PDF, etc.)
with open('encoded.txt') as f:
    b64_string = f.read().strip()
binary_data = base64.b64decode(b64_string)
with open('output.png', 'wb') as f:
    f.write(binary_data)

Command line (Linux/Mac)

## Decode a Base64 string
echo "SGVsbG8sIFdvcmxkIQ==" | base64 --decode
# Hello, World!

## Decode a Base64 file to binary
base64 --decode encoded.txt > output.png

## Decode URL-safe Base64 (replace - with + and _ with /)
echo "SGVsbG8sIFdvcmxkIQ" | tr -- '-_' '+/' | base64 --decode

Common Base64 Decoding Errors and Fixes

Invalid character in Base64 string

Standard Base64 uses A–Z, a–z, 0–9, +, and /. URL-safe Base64 uses - and _ instead. If your string contains - or _ and decoding fails, convert them: replace - with + and _ with / before decoding with the standard decoder. If your string contains spaces or newlines (common in MIME email attachments), strip them first.

Incorrect padding

Base64 strings must have a length divisible by 4. If the string length mod 4 is not 0, add = padding characters until it is. A string of length 22 needs 2 padding characters (==). A string of length 23 needs 1 (=). Most decoders handle this automatically, but some strict implementations reject incorrectly padded strings.

Decoded output is binary garbage

The encoded data is binary (an image, PDF, compressed file, or other non-text format), not a text string. Do not try to decode it to a string — decode it to raw bytes and save as a file. Use the image decoding method above if you think it is an image, or save with a generic extension like .bin and check the file type with a hex editor or file output.bin on Linux.

Frequently Asked Questions

Is Base64 decoding safe? Can it contain viruses?

Decoding Base64 itself is safe — it is just a format conversion. The decoded data could contain anything, including malicious executable files. Never execute decoded binary data from untrusted sources. If you decode a Base64 string and save it as a file, treat it with the same caution as any downloaded file from the internet.

How do I know if a string is Base64 encoded?

Base64 strings only contain letters, digits, +, /, and = (or - and _ for URL-safe). They typically end with one or two = padding characters. Their length is always a multiple of 4 (or would be with padding). They look like random text with no spaces or punctuation besides the characters above. If a string matches these patterns, it is likely Base64 — try decoding it with ToolPry's Base64 Decoder to confirm.

What is the difference between Base64 and Base64URL?

Base64URL replaces + with - and / with _, and omits = padding. It is used in JWTs, OAuth tokens, and anywhere the Base64 string appears in a URL. Standard Base64 uses + and /, which have special meanings in URLs. If you are decoding a JWT or any token from a URL, use URL-safe Base64 decoding.

Base64 in API Responses: What to Do When You Receive Encoded Data

Modern APIs frequently return Base64-encoded data in JSON responses when they need to transmit binary content like images, documents, or cryptographic material. Understanding how to handle this data in your code — not just in online tools — is an essential skill for API integration work.

When an API returns a Base64-encoded image in a JSON field, you typically need to decode it and either display it, save it to disk, or re-transmit it to another service. The pattern is the same in every language: extract the Base64 string from the JSON, decode to bytes, use the bytes appropriately.

// JavaScript — decode Base64 image from API response and display
const response = await fetch('/api/user/avatar');
const data = await response.json();
// data.avatar = "iVBORw0KGgoAAAANSUhEUg..."

// Display as image
const imgElement = document.createElement('img');
imgElement.src = `data:image/png;base64,${data.avatar}`;
document.body.appendChild(imgElement);

// Save as downloadable file
function downloadBase64File(b64, filename, mimeType) {
  const bytes = Uint8Array.from(atob(b64), c => c.charCodeAt(0));
  const blob = new Blob([bytes], { type: mimeType });
  const url = URL.createObjectURL(blob);
  const a = document.createElement('a');
  a.href = url;
  a.download = filename;
  a.click();
  URL.revokeObjectURL(url);
}

downloadBase64File(data.avatar, 'avatar.png', 'image/png');
// Python — decode Base64 from API response
import requests
import base64

response = requests.get('https://api.example.com/user/avatar')
data = response.json()
b64_image = data['avatar']

# Save to file
image_bytes = base64.b64decode(b64_image)
with open('avatar.png', 'wb') as f:
    f.write(image_bytes)
print(f"Saved {len(image_bytes)} bytes")

# Display metadata without saving
import struct
# For PNG: first 8 bytes are magic number, then IHDR chunk
if image_bytes[:8] == b'\x89PNG\r\n\x1a\n':
    width = struct.unpack('>I', image_bytes[16:20])[0]
    height = struct.unpack('>I', image_bytes[20:24])[0]
    print(f"PNG image: {width}x{height} pixels")

Identifying the Type of Base64-Encoded Data

When you receive a Base64 string without being told what it contains, the first 20–30 bytes of the decoded data reveal the file type. This is called the magic number or file signature — a specific sequence of bytes at the start of every file format.

File typeFirst bytes after decodingBase64 prefix
PNG image\x89PNG\r\n\x1a\niVBORw0KGgo
JPEG image\xff\xd8\xff/9j/
GIF imageGIF87a or GIF89aR0lGOD
PDF document%PDFJVBER
ZIP archivePK\x03\x04UEsDB
JSON text{ or [ey or Ww
JWT token{"alg":eyJhbGci

Frequently Asked Questions

What is the maximum size of data I can Base64 encode?

There is no hard limit in the Base64 specification, but practical limits depend on your environment. Browser atob() and btoa() can handle strings up to roughly 500MB before memory becomes an issue. For large files, process in chunks or use a streaming encoder. For APIs, check the endpoint's maximum request body size — most APIs have limits of 1–100MB. Base64 increases file size by 33%, so a 10MB file becomes ~13.3MB encoded.

How do I tell if a string is Base64 or just random text?

A few reliable indicators: the string contains only the characters A-Z a-z 0-9 + / = (standard) or A-Z a-z 0-9 - _ = (URL-safe). Its length is a multiple of 4, or would be with 1–2 padding characters added. It often ends with = or ==. And decoded, it produces either coherent text or identifiable binary data. Try decoding with ToolPry's Base64 Decoder — if the output is coherent text or shows a file type magic number, it was Base64.

Why does my decoded Base64 show question marks or diamond shapes?

Your decoder is assuming the wrong character encoding. The original data was encoded in a non-UTF-8 encoding (Latin-1, Windows-1252, or another encoding) and is being decoded as UTF-8, causing characters above the ASCII range to display incorrectly. Try different character encodings in your decoder. ToolPry's Base64 Decoder allows you to specify the output encoding to handle non-UTF-8 data correctly.

Base64 in Email: Decoding MIME Attachments

Email attachments are Base64-encoded in the MIME format. If you have ever viewed the raw source of an email, you have seen walls of Base64 — that is your PDF attachment or image, encoded for safe transmission through email servers that only handle 7-bit ASCII text. Understanding this helps when you need to extract attachments programmatically.

A MIME-encoded email attachment looks like:

Content-Type: image/png; name="photo.png"
Content-Transfer-Encoding: base64
Content-Disposition: attachment; filename="photo.png"

iVBORw0KGgoAAAANSUhEUgAAAAEAAAABCAYAAAAfFcSJAAAADUlEQVR42mNk+M9QDwAD
hgGAWjR9awAAAABJRU5ErkJggg==

The Base64 data in MIME emails is line-wrapped at 76 characters — this is a MIME requirement, not a Base64 requirement. When decoding MIME attachment data manually, strip all newlines before decoding. Most Base64 libraries handle this automatically, but some strict decoders reject line breaks in the input.

Base64 for Web Performance: When to Use Data URLs

Embedding small images as Base64 data URLs in HTML or CSS eliminates HTTP requests for those assets. This can improve performance for small icons and logos — but becomes a performance penalty for images over ~10KB due to the 33% size overhead and the fact that data URLs cannot be cached separately by the browser.

/* CSS — inline small icon as data URL (good for icons under 5KB) */
.icon-search {
  background-image: url('data:image/svg+xml;base64,PHN2ZyB4bWxucz0iaHR0cDovL3d3dy53My5vcmcvMjAwMC9zdmciIHZpZXdCb3g9IjAgMCAyNCAyNCI+PHBhdGggZD0iTTIxIDIxbC00LjM1LTQuMzVNMTcgMTFhNiA2IDAgMTEtMTIgMCA2IDYgMCAwMTEyIDB6Ii8+PC9zdmc+');
  background-repeat: no-repeat;
  background-size: 16px 16px;
}

Rules for deciding whether to use a data URL: use for SVG icons under 2KB, PNGs under 5KB used on every page, and images that cannot be cached effectively (personalised images, frequently changing content). Do not use for images over 10KB, images used on only some pages, or any image that benefits from browser caching. Use ToolPry's Base64 Encoder to encode images for data URLs — drag and drop the image file to get the complete data URL ready to paste into your CSS or HTML.

Frequently Asked Questions

How do I decode Base64 in a Google Sheets formula?

Google Sheets does not have a native Base64 decode function. Use Google Apps Script instead: open Extensions → Apps Script, create a function, and use JavaScript's built-in Utilities.base64Decode() method which returns a byte array. Convert to a string with Utilities.newBlob(Utilities.base64Decode(encoded)).getDataAsString(). Alternatively, paste the Base64 strings into ToolPry's Base64 Decoder and copy the decoded results back into your spreadsheet.

Can I encode and decode Base64 directly in the browser without any tool?

Yes. Open your browser's DevTools console (F12 → Console) and use: btoa('Hello World') to encode and atob('SGVsbG8gV29ybGQ=') to decode. This works for ASCII text — for Unicode text you need the slightly more complex approach shown earlier in this article (encoding to UTF-8 first). For file encoding/decoding in the browser, ToolPry's Base64 tool handles both text and file inputs without needing to write any code.

Is there a file size limit for Base64 encoding?

The Base64 specification has no size limit. Practical limits depend on your environment: browser memory (large files may freeze the page), API request body limits (typically 1–100MB), and email attachment limits (typically 10–25MB for the encoded data). For files larger than a few megabytes, use dedicated file upload APIs rather than Base64 embedding — multipart form data uploads are significantly more efficient for large binary files than Base64 encoding in JSON.