Skip to content
LocalOnly
Developer Utilities

Decode Base64 in the Terminal, JavaScript and Python

Decoding Base64 is one call in every language, and each call has a trap: atob garbles accents, Buffer accepts junk, and Python rejects missing padding. Here is the correct version of each.

Updated October 18, 20262 min readTool runs in your browser

To decode Base64 on the command line, in JavaScript or in Python, you need one call, but each one has a trap that produces wrong output without an error. The Base64 Decode tool decodes in the browser and its page explains how to recognise Base64 and why decoded bytes are not always text. This guide covers decoding in your own terminal and code.

Decode Base64 on the command line

echo 'w6k=' | base64 -d          # macOS and Linux
echo 'w6k=' | openssl base64 -d -A
base64 -d secret.b64 > secret.bin  # decode a file

Both commands print é. -A tells openssl that the input is one line, which matters for long Base64 strings without line breaks. Redirect binary output to a file instead of printing it, because raw bytes can garble the terminal.

Decode Base64 in JavaScript

atob is built into browsers and Node, but it returns a binary string: one character per byte. For anything outside ASCII, that gives the wrong text:

atob("w6k=");
// "é"   wrong: the two UTF-8 bytes of é shown as two characters

new TextDecoder().decode(Uint8Array.from(atob("w6k="), (c) => c.charCodeAt(0)));
// "é"    correct in browsers and Node

Buffer.from("w6k=", "base64").toString("utf8");
// "é"    correct in Node

Buffer.from(token, "base64url").toString("utf8");
// Node also decodes the URL-safe alphabet directly

atob tolerates spaces, line breaks and missing padding, but rejects the URL-safe characters - and _ with an InvalidCharacterError. Replace them with + and / first. Buffer goes the other way and accepts almost anything: invalid characters are skipped silently, so Buffer.from("w6k-!!", "base64") decoded to é> without complaint. Validate input you did not produce yourself.

Decode Base64 in Python

import base64

base64.b64decode("w6k=").decode("utf-8")        # 'é'

def b64url_decode(text):
    return base64.urlsafe_b64decode(text + "=" * (-len(text) % 4))

b64url_decode("eyJzdWIiOiJ1XzQyIn0")            # b'{"sub":"u_42"}'

base64.b64decode(text, validate=True)           # reject anything outside the alphabet
  • Python insists on padding. JWT segments and other URL-safe values usually drop the =, and decoding them directly fails with Incorrect padding. The helper above adds the missing padding.
  • By default b64decode skips characters outside the alphabet. validate=True raises Only base64 data is allowed instead, which is what you want for input from outside your system.
  • The result is bytes. Call .decode("utf-8") only when you know the content is text.

Frequently asked questions

Command Palette

Search for a tool or command