Base64 Decoder_

Paste Base64 in whatever shape it arrived — standard or URL-safe alphabet, missing padding, wrapped across lines, even a whole data: URI — and get the payload presented as what it actually is: text, JSON, a JWT, an image preview, or a hex dump of raw bytes. Invalid input gets the exact character and position, not a shrug.

Decoding runs entirely in this tab. Base64 strings routinely carry session cookies, Basic-auth credentials, and API keys — and the most-used decoder sites process your paste on their servers by default. This page cannot make that request, and it keeps working offline.

toolkit.codes/base64-decode
Paste Base64 to decode it
UTF-8
Ready
100% LOCAL
Input
A Base64 or Base64URL string, padded or not. Whitespace and line breaks are stripped, missing = padding is restored, and a data:*;base64, prefix is recognised and reported rather than choking the decode.
Output
UTF-8 text when the bytes are text. When they are not, a hex dump instead of mojibake — and for a recognised PNG, JPEG, GIF, WebP, BMP, ICO or SVG payload, an inline preview and a typed download.
Processing
Decoded in this tab. Tokens, secrets and Kubernetes values you paste here are never transmitted, which is the entire reason to prefer a local decoder for them.
Limits
No account and no size quota. Mixed-alphabet input is refused rather than silently mangled, and an invalid character is named with its exact position.
Not encryption
Base64 is an encoding, not a cipher: anyone who has the string has the data. Decoding one is reading, not breaking — and nothing you paste here needs a key because there is none.

A Base64 decoder built for strings from the real world

What Base64 decoding actually does

Base64 represents arbitrary bytes using 64 printable characters, so binary data can travel through channels built for text — email bodies, JSON strings, URLs, HTTP headers. Each character carries six bits, so four characters reconstruct exactly three bytes; decoding is that reverse mapping and nothing more. It is an encoding, not encryption: there is no key, no secret, and anything Base64-"protected" is readable by anyone who pastes it into a page like this one — worth internalizing, because credentials and tokens are exactly what Base64 most often wraps.

Real-world cleanup, done for you and reported

Base64 copied out of the wild is rarely pristine. MIME wraps it at 76 columns, YAML indents it, JWTs strip the = padding, and browsers hand you data:image/png;base64, prefixes. This decoder strips whitespace, restores missing padding, removes data-URI prefixes, and auto-detects the standard (+ /) versus URL-safe (- _) alphabet — every fix reported in the notices row. Failures name the offending character and its position, with a caret pointing at it. And when the decoded bytes are not valid UTF-8, the page refuses to guess: instead of printing replacement characters — mojibake that silently destroys data — it switches to a hex dump, offers a Latin-1 view for single-byte legacy text, and lets you download the untouched bytes.

Why decoding in the browser matters more here than almost anywhere

Think about what people decode: Authorization: Basic headers, session cookies, SAML assertions, Kubernetes Secrets, API keys from config files. The market-leading decoder site sends your input to its servers unless you find and enable its opt-in "live mode" — the default path for millions of decoded credentials is someone else's infrastructure and logs. This page is local by construction: its security policy forbids tool code from making network requests, the test suite asserts none happen during decoding, and it works with your connection unplugged. Nothing to trust — only something you can verify.

Decoding Base64 in the terminal, Python, and JavaScript

On Linux, base64 -d file.txt (or --decode) writes decoded bytes to stdout; older macOS builds spell it base64 -D, and Windows has certutil -decode in.txt out.bin. In Python, base64.b64decode(s) returns bytes — pass validate=True to reject junk characters, and use base64.urlsafe_b64decode for -/_ input. In JavaScript, atob() yields a byte-per-character string (pair it with TextDecoder for UTF-8); Node.js uses Buffer.from(s, 'base64'), which tolerates both alphabets. What none of those tell you is what you decoded — which is the point of this page.

Paste the string, read the bytes it hides

  1. 01Paste the Base64 string — or Upload a file containing one, or press Sample. Decoding is live: both alphabets are auto-detected, and whitespace, missing padding, and data: URI prefixes are cleaned up and reported in the notices row.
  2. 02Read the result in the right view: Text for valid UTF-8, Hex for raw bytes, Latin-1 for single-byte legacy encodings. If the payload is an image, a preview renders below the status line and Download saves the file with the correct extension.
  3. 03Follow the hints: decoded JSON links to the JSON formatter, JWT-shaped input points at the JWT decoder, and output that still looks like Base64 gets a Decode again button — the double-encoding escape hatch.
  4. 04Copy the active view, or Download the decoded bytes as a file. Both always carry the complete payload, even when a very large result is truncated on screen to keep the tab responsive.

Four payloads people actually decode

Basic auth header

A request is authenticating as somebody — the Basic header says who, if you decode it. This is RFC 7617's own example credential.

Input
QWxhZGRpbjpvcGVuIHNlc2FtZQ==
Output
Aladdin:open sesame

Image hiding in a data: URI

Paste the entire URI — no need to trim the prefix by hand. The MIME type is read from it, the bytes are verified against magic numbers, and Download saves a real file.

Input
data:image/png;base64,iVBORw0KGgoAAAANSUhEUgAAAAEAAAAB…
Result
✓ data: URI prefix removed (image/png)
PNG detected — preview shown, Download saves decoded.png

Secret in a config file

Kubernetes Secrets and plenty of .env pipelines store values Base64-encoded. Decoding is the only way to confirm what is actually deployed.

Input
cG9zdGdyZXM6Ly9hZG1pbjpodW50ZXIyQGRiOjU0MzI=
Output
postgres://admin:hunter2@db:5432

Line-wrapped MIME chunk

Email attachments arrive wrapped at 76 columns. Paste the block as-is — the line breaks are stripped, and the notices row says so.

Input
QXR0YWNobWVudCBjaHVu
a3MgYXJyaXZlIHdyYXBw
ZWQgYXQgNzYgY29sdW1u
cy4=
Output
Attachment chunks arrive wrapped at 76 columns.
· Whitespace removed before decoding.

The Base64 alphabet — standard vs URL-safe

CharactersValuesNotes
A–Z0–25Uppercase letters take the first 26 values
a–z26–51Lowercase letters take the next 26
0–952–61Digits
+ /62, 63Standard alphabet (RFC 4648 §4) — breaks in URLs, where + means space and / is a separator
- _62, 63URL-safe alphabet, a.k.a. base64url (RFC 4648 §5) — used by JWTs and web tokens
=paddingFills the final group to four characters; carries no data and is often omitted

Six bits per character: 2⁶ = 64. The alphabets differ only in the last two characters — this decoder detects which one a paste uses and rejects mixtures.

Size math: 4 characters ↔ 3 bytes

Decoded bytesEncoded charactersPadding
3 (full group)4none
2 left over4one =
1 left over4two ==
3 MB file4,000,000 charsBase64 inflates data by ~33% on the wire
n chars of Base64≈ n × ¾ bytesdecoded output is 25% smaller than the string

Corollary: no valid Base64 string is 4k+1 characters long after cleanup — one leftover character holds six bits, too few for a byte. That is what the “invalid length” error means.

Decoding strings that came from somewhere else

  • Paste straight from wherever the string lives — HTTP headers, PEM blocks, YAML, email source. Line wraps, tabs, and missing padding are cleaned automatically, and every cleanup is reported.
  • A data: URI can go in whole; the prefix is stripped and its MIME type reported. If the URI has no ;base64 flag, the payload is percent-encoded rather than Base64 — that is the URL decoder’s job, and the error says so.
  • Prefer Download over Copy for binary payloads: the file gets a correct extension from its magic bytes, and raw bytes survive intact where clipboard round-trips can mangle them.
  • The Latin-1 view is for pre-Unicode legacy exports, where every byte maps to one character. For anything modern, trust the UTF-8 verdict — if validation failed, the payload is probably not text at all.
  • If the output still looks like Base64, it probably is — double encoding happens whenever code encodes an already-encoded value. The hint plus the Decode again button unwraps one layer at a time.
  • A JWT is not one Base64 string — it is three URL-safe segments joined by dots. Paste a single segment here to inspect it, or the whole token into the JWT decoder.

Decoding is not decryption, and the traps that follow

Base64 is not encryption

There is no key and no secrecy — decoding takes one paste. Credentials that are merely Base64-encoded in a config file or a header are plaintext with extra steps. If confidentiality matters, encrypt; encoding only changes the representation.

URL-safe tokens fail in strict standard decoders

A decoder expecting only + and / throws on - and _ (Python’s b64decode with validate=True rejects them outright). The fix in code is the urlsafe variant of your library; the fix here is automatic — the alphabet is detected per paste.

Missing padding breaks strict decoders

JWT segments and many web tokens drop the trailing = by design, and strict decoders answer with “incorrect padding”. Re-pad to a multiple of four characters, or use a tolerant decoder — this page adds the padding back and tells you it did.

Decoded bytes are not always text

Base64 mostly wraps binary: images, gzip blobs, protobuf, ciphertext. Forcing those bytes through a text decoder produces mojibake or hides data loss behind U+FFFD replacement characters. This page validates UTF-8 fatally and falls back to hex — corruption is refused, not displayed.

Double encoding

Encode an already-encoded value and you get Base64-of-Base64 — decoding “succeeds” and hands you more Base64, the classic symptom of two serialization layers each doing their job. The heuristic here spots the shape and offers Decode again rather than guessing for you.

Server-side decoders see your tokens

The strings people decode are exactly the ones that should never travel: session cookies, Basic credentials, SAML assertions, signing keys. The biggest decoder site round-trips input to its servers unless you enable its opt-in live mode. Decode locally — this page cannot phone home, and works offline to prove it.

Alphabets, padding and payload detection

Alphabets
Standard (RFC 4648 §4) and URL-safe/base64url (§5), auto-detected per input; mixed-alphabet input is rejected with a message naming both character sets
Input cleanup
Whitespace stripped, missing padding restored, data:*;base64, prefixes removed with the MIME type recorded — each fix reported in the notices row, never silent
Error reporting
First invalid character named with its exact position plus a caret excerpt; misplaced =, impossible lengths, and Base64-less data: URIs get specific messages
Text handling
UTF-8 decoded with fatal validation — invalid sequences switch the view to a hex dump instead of emitting U+FFFD replacement characters; a Latin-1 view covers single-byte legacy data
Payload detection
PNG, JPEG, GIF, WebP, BMP, ICO via magic bytes and SVG via markup → inline preview and typed download; JSON and JWT shapes → links to the matching tools
Large inputs
Decoding is native. Past 300k characters the text views truncate on screen and the hex view shows the first 4,096 bytes. Copy and Download are unaffected and always carry the complete result.
File handling
Uploads are read inside the page with the browser File API and are never transmitted; Download writes out what is already in the tab. The extension comes from the detected type — .png, .json, .txt or .bin.
Network
None from tool code. A test sweep calls every function this page uses with fetch and XMLHttpRequest replaced by stubs that throw, so a stray request fails the build instead of shipping. Disconnect from the network and the page still works.

Questions about decoding Base64

Is it safe to decode tokens and secrets here?

Yes. The work is JavaScript running in this tab. Every function it calls is covered by a test that stubs fetch and XMLHttpRequest to throw, so a request that slipped in would break the build rather than reach a server — and you can confirm it for yourself by disconnecting and carrying on. Not every decoder can say that: the most popular one processes input server-side unless you switch on its live mode, so the credential you were only trying to read has already been handed over.

How do I decode URL-safe Base64?

Here, nothing special — the - and _ characters are detected and the alphabet label tells you what was used. In code, use your library’s urlsafe variant (Python’s base64.urlsafe_b64decode), and expect to re-add the stripped = padding.

Why does my JWT fail to decode?

A JWT is three separate Base64url segments joined by dots — the dot is not a Base64 character, so a whole token is not one decodable string. Paste one segment here, or use the JWT decoder to read header, payload, and signature together.

What does “Not valid UTF-8” mean?

The Base64 was valid and the bytes decoded fine, but they are not UTF-8 text — usually the payload is binary (an image, an archive, ciphertext) or a legacy single-byte encoding. Check the hex view for magic bytes, try the Latin-1 view, or Download the bytes and open them in the right program.

Can it decode Base64 to an image or a file?

Yes. Image formats are recognized by their magic bytes (PNG, JPEG, GIF, WebP, BMP, ICO, SVG) and previewed inline; Download saves the decoded bytes with the correct extension. Whole data: URIs are accepted as-is — the prefix is stripped and reported.

How do I decode Base64 in Python, JavaScript, or the terminal?

Python: base64.b64decode(s), with validate=True for strictness or urlsafe_b64decode for token alphabets. JavaScript: atob(s) in the browser (wrap with TextDecoder for UTF-8) or Buffer.from(s, "base64") in Node. Terminal: base64 -d on Linux, base64 -D on older macOS, certutil -decode on Windows.