Free tool

Base64 decode and encode

Paste Base64 to decode it, or type text to encode it. The direction is picked for you, UTF-8 and emoji work, Base64URL is accepted as is, and decoded files are recognised and downloadable.

Free · no sign-up · runs in your browser, nothing is uploaded

Text input
Base64

Base64 appears here as you type.

Drop any file here (or click) to encode it to Base64. It is read in your browser and never uploaded.

How Base64 works

Base64 writes any bytes using 64 safe characters, so binary data can travel through systems built for text: email, JSON, HTML, HTTP headers. It takes the input 3 bytes (24 bits) at a time and splits them into four 6-bit numbers. Each number from 0 to 63 picks one character from the alphabet.

ValuesCharactersNotes
0-25A-Z
26-51a-z
52-610-9
62+- in Base64URL
63/_ in Base64URL
padding=fills the last group to 4 characters

Example: the text Man is the bytes 4D 61 6E, or the bits 010011 010110 000101 101110. Those are 19, 22, 5 and 46, which are T W F u, so Man encodes to TWFu. With one byte left over at the end you get two characters and ==; with two, three characters and =.

The output is always about a third larger than the input. Base64 is not compression and not encryption: it is fully reversible by anyone.

Base64 vs Base64URL

Standard Base64 uses + and /, which mean something in URLs (+ becomes a space in a query string, / splits the path). RFC 4648 section 5 defines a URL- and filename-safe alphabet that swaps just those two characters.

Base64Base64URL
Characters 62 and 63+ /- _
PaddingRequired by most decodersUsually left out
Used inEmail (MIME), data URIs, PEM keys, Basic authJWTs, URL parameters, filenames, WebAuthn
Node.jsBuffer#toString('base64')Buffer#toString('base64url')

The decoder above accepts both alphabets and missing padding, so you can paste the middle part of a JWT straight in. To read a whole token with its expiry times, use the JWT decoder.

Decode and encode Base64 in code

Browser JavaScript. btoa() and atob() work on strings where each character is one byte, so text with emoji or accents needs a trip through UTF-8 bytes first:

// Text → Base64 (UTF-8 safe)
const bytes = new TextEncoder().encode('Grüße 👋');
const b64 = btoa(String.fromCharCode(...bytes)); // fine for small inputs

// Base64 → text
const back = new TextDecoder().decode(Uint8Array.from(atob(b64), c => c.charCodeAt(0)));

// Newer browsers (Baseline 2025): built-in, with Base64URL and padding options
new TextEncoder().encode('hi').toBase64({ alphabet: 'base64url', omitPadding: true });
Uint8Array.fromBase64('aGk=');

Node.js

Buffer.from('Grüße 👋').toString('base64');          // encode
Buffer.from('R3LDvMOfZSDwn5GL', 'base64').toString(); // decode
Buffer.from(data).toString('base64url');                // URL-safe, no padding

Python

import base64
base64.b64encode('Grüße 👋'.encode()).decode()     # 'R3LDvMOfZSDwn5GL'
base64.b64decode('R3LDvMOfZSDwn5GL').decode()      # 'Grüße 👋'
base64.urlsafe_b64encode(b'\xfb\xff')               # b'-_8='

Go

s := base64.StdEncoding.EncodeToString([]byte("hello"))   // aGVsbG8=
b, err := base64.StdEncoding.DecodeString(s)
jwtPart := base64.RawURLEncoding.EncodeToString(b)          // URL-safe, no padding

Terminal

echo -n 'hello' | base64            # aGVsbG8=   (-n: no trailing newline)
echo 'aGVsbG8=' | base64 -d          # hello
base64 -w 0 file.bin > file.b64      # GNU: one line (default wraps at 76)
base64 -i file.bin -o file.b64       # macOS

Common Base64 errors and how to fix them

Error or symptomCauseFix
InvalidCharacterErrorbtoa() got a character above U+00FF (emoji, accents in some text, CJK).Encode the text to UTF-8 bytes with TextEncoder first.
Incorrect paddingPython got Base64 with the = padding stripped, usually Base64URL from a JWT.Add = until the length is a multiple of 4, or use a lenient decoder.
Decoded text looks like é or ðUTF-8 bytes were read as Latin-1 (or the other way round).Pick the right charset above; most text today is UTF-8.
Spaces where + should beBase64 was sent in a URL query string unescaped, and + was read as a space.Use Base64URL, or URL-encode the value (+ becomes %2B).
%2BThe string is URL-encoded (%2B is +, %3D is =).Run it through the URL decoder first.
aGVsbG8K instead of aGVsbG8=echo added a newline, so hello\n was encoded.Use echo -n or printf.

Where you meet Base64

  • HTTP Basic auth: Authorization: Basic dXNlcjpwYXNz is just user:pass in Base64 (RFC 7617). Decoding it shows the password, which is why Basic auth needs HTTPS.
  • Data URIs: data:image/png;base64,iVBORw0KGgo… puts a whole file inside HTML or CSS. Convert pictures with the image to Base64 converter.
  • JWTs: the header and payload are Base64URL-encoded JSON. Decode either part here and tick Format JSON.
  • Email attachments: MIME encodes attachments in Base64 with lines of at most 76 characters (RFC 2045). Choose 76 under Line length to match.
  • PEM keys and certificates: the text between -----BEGIN …----- lines is Base64 of DER bytes, wrapped at 64 characters (RFC 7468).
  • Kubernetes Secrets: values under data: are Base64-encoded, not encrypted. Decode one here to check it, and use a hash when you need a one-way fingerprint instead.

Looking for more than a free tool? Browse security tools on DevHunt or API tools.

FAQ

How do I decode a Base64 string?+

Paste it into the box above. The tool sees that it is Base64 and shows the decoded text right away; if the bytes are a file (an image, a PDF, a ZIP), it names the type and gives you a download. In code: atob() or Uint8Array.fromBase64() in the browser, Buffer.from(s, "base64") in Node, base64.b64decode() in Python, and base64 -d in a terminal.

Is Base64 encryption?+

No. Base64 is an encoding: a fixed, public way to write bytes as text. Anyone can decode it without a key. Do not use it to hide passwords or tokens; a Basic auth header or a Kubernetes Secret written in Base64 is readable by anyone who sees it.

Why does Base64 end with = or ==?+

Base64 turns every 3 bytes into 4 characters. When the input length is not a multiple of 3, the last group is short: one leftover byte gives 2 characters plus ==, two leftover bytes give 3 characters plus =. The = signs are padding so the output length is a multiple of 4. Base64URL usually drops them.

How much bigger does Base64 make data?+

Four output characters for every three input bytes, so about 33% bigger, plus up to two padding characters. If the output is wrapped into lines (76 characters for MIME email, 64 for PEM), the line breaks add a little more.

What is the difference between Base64 and Base64URL?+

Base64URL (RFC 4648 section 5) replaces + with - and / with _, so the result can go in a URL or a filename without escaping. It usually leaves out the = padding. JWTs use Base64URL without padding. This decoder accepts both alphabets, so you never have to convert first.

Why does btoa() fail with "characters outside of the Latin1 range"?+

btoa() takes a string where every character is one byte (code points 0 to 255). Emoji, Chinese, Cyrillic and many other characters are larger, so it throws. Turn the text into UTF-8 bytes first with TextEncoder, then encode the bytes; the snippets on this page show how.

How can I tell if a string is Base64?+

Base64 uses only A-Z, a-z, 0-9, + and / (or - and _ for Base64URL), with at most two = at the end, and its length without padding is never 4k+1. That still matches plenty of plain words, so the real test is to decode it: this tool switches to decoding only when the result is readable UTF-8 text or a known file type.

Is it safe to paste secrets here?+

The encoding and decoding run in your browser with JavaScript; nothing you type or drop is sent to DevHunt or anyone else. Your input is not put in the page URL either, unless you click "link with input" to share it.

Sources: RFC 4648 (Base64 and Base64URL) · RFC 2045 (MIME, 76-character lines) · RFC 7468 (PEM, 64-character lines) · RFC 7617 (HTTP Basic auth) · MDN: btoa() · MDN: Uint8Array.toBase64() · Python base64 · Go encoding/base64 · WHATWG MIME Sniffing. Checked 2026-10-29.