Code snippets · 7 min read

Decoding Base64 in every major language.

Working, copy-paste snippets for JavaScript, Python, PHP, Java, Go, and Bash — including the UTF-8 handling and URL-safe variants that most snippets get wrong.

JavaScript (browser and Node)

Modern browsers and Node ship with atob() and btoa() for ASCII strings, and the Buffer or TextDecoder APIs for binary and UTF-8.

ASCII-only, simple cases:

const encoded = btoa("Hello, world!");           // "SGVsbG8sIHdvcmxkIQ=="
const decoded = atob("SGVsbG8sIHdvcmxkIQ==");    // "Hello, world!"

UTF-8 strings (the right way):

// Encode
const encoded = btoa(new TextEncoder()
  .encode("café ☕")
  .reduce((s, b) => s + String.fromCharCode(b), ""));

// Decode
const bytes = Uint8Array.from(atob(encoded), c => c.charCodeAt(0));
const decoded = new TextDecoder().decode(bytes);  // "café ☕"

Node.js (preferred):

const encoded = Buffer.from("café ☕", "utf-8").toString("base64");
const decoded = Buffer.from(encoded, "base64").toString("utf-8");

Python 3

The base64 module in the standard library covers every variant.

import base64

# Standard Base64
encoded = base64.b64encode("café ☕".encode("utf-8")).decode("ascii")
# 'Y2Fmw6kg4piV'

decoded = base64.b64decode(encoded).decode("utf-8")
# 'café ☕'

# URL-safe variant
encoded_urlsafe = base64.urlsafe_b64encode(b"\xff\xee\xdd").decode("ascii")
# '/-7d' becomes '_-7d' in URL-safe form

# Decode forgiving missing padding (common with JWTs):
def b64decode_padded(s):
    return base64.urlsafe_b64decode(s + "=" * (-len(s) % 4))

A common stumble in Python: b64encode() returns bytes, not str. The .decode("ascii") tail converts the result to a regular string for use in JSON or logs.

PHP

<?php
$encoded = base64_encode("café ☕");
// "Y2Fmw6kg4piV"

$decoded = base64_decode($encoded);
// "café ☕"

// Strict mode (returns false on invalid input):
$decoded = base64_decode($encoded, true);
if ($decoded === false) {
    throw new Exception("Invalid Base64");
}

// URL-safe — PHP doesn't have a built-in, so do it manually:
function base64url_encode($data) {
    return rtrim(strtr(base64_encode($data), '+/', '-_'), '=');
}
function base64url_decode($data) {
    return base64_decode(strtr($data, '-_', '+/'));
}

Java

Use java.util.Base64 (added in Java 8).

import java.util.Base64;
import java.nio.charset.StandardCharsets;

String encoded = Base64.getEncoder()
    .encodeToString("café ☕".getBytes(StandardCharsets.UTF_8));
// "Y2Fmw6kg4piV"

String decoded = new String(
    Base64.getDecoder().decode(encoded),
    StandardCharsets.UTF_8
);
// "café ☕"

// URL-safe variant
String urlSafe = Base64.getUrlEncoder()
    .withoutPadding()
    .encodeToString(bytes);

byte[] back = Base64.getUrlDecoder().decode(urlSafe);

Go

import "encoding/base64"

encoded := base64.StdEncoding.EncodeToString([]byte("café ☕"))
decoded, _ := base64.StdEncoding.DecodeString(encoded)

// URL-safe
encodedURL := base64.URLEncoding.EncodeToString(bytes)
// Without padding (for JWTs etc.)
encodedRaw := base64.RawURLEncoding.EncodeToString(bytes)

Bash / shell

# Encode
echo -n "café ☕" | base64
# Y2Fmw6kg4piV

# Decode
echo "Y2Fmw6kg4piV" | base64 -d
# café ☕

# URL-safe variant (BSD base64 doesn't support -w 0 or URL-safe directly,
# so post-process with tr):
echo -n "$data" | base64 | tr '+/' '-_' | tr -d '='
Cross-language gotcha

The single biggest portability problem: text encoding. "café" is one string in your source code, but it's different bytes in UTF-8 (5 bytes) vs Latin-1 (4 bytes). Always specify UTF-8 explicitly when encoding strings — otherwise different runtimes will produce different Base64.

When to skip the library and use this tool

If you just need to decode a single string once — a JWT you're debugging, a config value, an email attachment header — opening the decoder is faster than writing the code, importing the library, and running it. Use the library when the decoding needs to happen in production; use the tool when you're investigating.


Published May 2026 · Last reviewed May 2026. Spot an error? Email contactus@base64decode.tools.

Run it yourself

Try the decoder.