Help shape the future of JSON Workbench! We'd love to hear how you use it.
01

What Base64 actually is

Base64 is a way to write arbitrary bytes using only safe, printable characters — nothing more. The name comes from its alphabet: exactly 64 characters (A–Z, a–z, 0–9, + and /), plus the = sign reserved for padding. Because those characters survive every text-only channel — HTTP headers, JSON strings, XML, email bodies, URLs — Base64 lets bytes go places that would otherwise corrupt them.

Why 64 characters? Because 64 = 2⁶: each output character carries exactly 6 bits, so the mapping between bytes and characters is pure bit-shifting with no ambiguity. The cost is size. The encoder reads the input 3 bytes at a time (24 bits), splits them into four 6-bit groups, and emits one character per group:

M
'M' = 77
01001101
a
'a' = 97
01100001
n
'n' = 110
01101110
24 bits
010011010110000101101110→ 4 × 6 bits
T
010011 = 19
W
010110 = 22
F
000101 = 5
u
101110 = 46

Man → TWFu — Every Base64 string you will ever meet works exactly like this one — including the ones hiding in JWTs and data URIs.

+33% size. Every 3 input bytes become exactly 4 output characters, so Base64 output is about a third larger than the original. Padding = tops the length up to a multiple of 4 when the input isn't an even multiple of 3 bytes.
Trivially reversible. There is no key and no secret — the same alphabet table exists in every language and every decoder. Reversing it takes microseconds.
Not encryption. Base64 exists to make bytes transport-safe, not to hide them. Anyone who sees dXNlcjpwYXNz can read it. Never treat a Base64-encoded password or API key as protected.
02

Where you'll actually meet it

You rarely decide to use Base64 — you find it waiting in an API response, a header or a config file. Each card below is one of those moments: what you see, what to do on this page, and what you get.

Data URIs

You see

A URL like data:image/png;base64,iVBORw0KGgo… embedded in HTML, CSS or a webpack bundle.

Do this

Copy everything after base64,, paste it here, press Decode & Format.

You get

For text payloads (SVG source, JSON, CSV) you get readable content back. True binaries such as PNG come out as gibberish characters — see Gotchas below; this page decodes to text, not to files.

JWT tokens

You see

A token like eyJhbGciOiJIUzI1NiJ9.eyJzdWIiOiIxMjMifQ.sig — three dot-separated segments whose first two always start with eyJ, which is simply the opening of a JSON object after encoding.

Do this

Copy the middle segment between the dots, paste it here, press Decode & Format. Or open the whole token in the JWT Debugger.

You get

The claims payload pretty-printed as JSON in its own tab, ready for Tree/Table view. URL-safe - and _ characters are handled automatically.

Authorization headers

You see

An HTTP header like Authorization: Basic dXNlcjpwYXNz in a request dump or proxy log.

Do this

Copy just the part after Basic, paste it here, press Decode & Format.

You get

The credentials in cleartext — here user:pass. A useful reminder that Basic auth only protects anything because it rides inside HTTPS.

Email & MIME parts

You see

A wall of wrapped letters under Content-Transfer-Encoding: base64 when viewing an email's source or an .eml file.

Do this

Join the wrapped lines into one single-line string first (internal line breaks are not part of the alphabet), then paste and press Decode & Format.

You get

The message part's text content. Attachments that are real binaries decode to noise for the same reason PNG data URIs do.

Base64 inside JSON

You see

A field like "payload": "eyJ1c2VySWQiOjQyfQ==" inside an API response — some service stuffed encoded data where text was expected.

Do this

Copy the value, paste it here, press Decode & Format.

You get

A new numbered tab with the decoded content formatted as JSON — your original response stays untouched in the editor, and you can compare both side by side.

03

Encode ↔ Decode

Two directions, two buttons, zero configuration. Both run entirely in your browser — nothing is uploaded, nothing is logged.

Plain text → Base64

  1. 1Paste any text, JSON, XML or CSV into the empty editor (or use Paste).
  2. 2Press Encode — the editor content is replaced in place with its Base64 form. Encoding is UTF-8 aware, so emoji and non-Latin scripts round-trip correctly.
  3. 3Take the result with Copy or save it with Download. Output uses the standard alphabet (+ and /) with correct = padding.

Base64 → text or JSON

  1. 1Paste the Base64 string — standard or URL-safe, padded or missing its = padding.
  2. 2Press Decode & Format (pretty-printed) or Decode & Minify (single line). Input that isn't valid Base64 is rejected up front with an error toast instead of producing garbage.
  3. 3If the decoded text parses as JSON it opens in a new tab formatted and validated; anything else opens as plain text.
Which one do I need? Encode replaces what you typed with its encoded form; Decode keeps your original safe and opens the result alongside it. That asymmetry is deliberate — encodings are cheap to redo, originals sometimes aren't.
04

Tabs & compare

Single-box encoder sites make you work one string at a time. This page keeps a whole session:

Multi-tab sessions

Each decode opens a numbered tab — Base64 #1, Base64 #2, … — instead of overwriting your work. Your original Base64 lives in the root editor: the + button at the end of the tab bar returns to it, and switching tabs preserves every tab's content. Close tabs with the ✕ on hover; closing the last tab returns you to the encoder.

Tab-to-tab compare

Hover any tab and click the ⇄ icon, then click the ⇄ icon on a second tab. A hint bar confirms the selection, and both contents open side by side on the JSON compare page with their tab labels — perfect for spotting why two supposedly identical decoded payloads differ.

Decoded JSON gets full tooling

When a decode produces JSON, the toolbar switches to the full formatter set: Code / Tree / Table views, search, Format, Minify, Anonymize, Escape/Unescape, plus Copy, Paste, Upload and Download. Non-JSON decodes stay simple text.

Honest limits: tabs live in memory for this visit — they don't survive a reload. And since decoded non-JSON tabs are plain text, the Upload button only appears once content has been recognized as JSON.
05

Gotchas: symptom → cause → fix

Ninety percent of "my Base64 doesn't work" reports fall into five buckets:

SymptomCauseFix
Rejected with “Content is not a valid Base64 string.”The validator found a character outside the alphabet — usually a space, newline or quote copied along with the string — or the length leaves a leftover character after removing padding.Re-copy the exact string without surrounding quotes, join any wrapped lines, and check nothing was truncated at either end.
Works with this tool but fails elsewhere (or vice versa)Missing = padding. Many decoders require the length to be a multiple of 4; this page pads automatically, strict tools don't.Append = until the length divides by 4 before feeding a stricter decoder.
A JWT segment fails to decode somewhere elseJWTs use base64url: + becomes - and / becomes _, often with padding stripped entirely.Here it's automatic — both alphabets are accepted and normalized. Elsewhere, replace -/_ with +// and re-pad first.
Decoded output is gibberish like �PNGThe payload was real binary (an image, zip, font). Decoding produced the correct bytes; rendering them as UTF-8 text produces replacement characters.Nothing is corrupt — you just can't show bytes as text. For binaries use file-oriented tooling or serve them via a data URI instead.
Email-style Base64 won't validateMIME wraps output at 76 columns. Only outer whitespace is trimmed here; line breaks inside the string are illegal characters.Join the lines into one string (a quick find-and-replace of newlines does it) and decode again.
“It's Base64, so my API key is hidden, right?”No. Encoding adds zero secrecy — every decoder, including this one, reverses it instantly.Protect secrets with encryption or hashing on a server, keep them out of client code entirely, and rotate any key that has already shipped Base64-encoded.
06

Cheat sheet

The same operations away from this page — identical inputs give identical outputs:

Command / syntaxWhat it does
btoa('Man') // 'TWFu'Browser JS encode. Latin-1 only — throws on emoji or any character above U+00FF.
atob('TWFu') // 'Man'Browser JS decode.
btoa(String.fromCharCode(...new TextEncoder().encode(s)))Unicode-safe encode trick — the same approach this tool uses internally, chunked for large inputs.
echo -n 'Man' | base64 # TWFuCLI encode. The -n suppresses echo's newline — without it you encode Man\n and get TWFuCg==.
echo 'TWFu' | base64 -d # ManCLI decode (GNU coreutils). macOS uses --decode or -D; GNU also offers -w 0 to disable 76-column wrapping.
data:[mediatype][;base64],DATAData URI anatomy — e.g. data:text/plain;base64,SGVsbG8=. Everything after the comma is pure Base64.
header.payload.signatureJWT anatomy: three base64url segments. Header and payload decode to JSON; the signature decodes to raw bytes and shouldn't be readable.
07

Frequently asked questions

Is my data uploaded anywhere?

No. Encoding, decoding, validation and formatting all happen in your browser with JavaScript. There is no backend round-trip — after the page loads, the tools even keep working offline.

Can it decode the URL-safe Base64 used in JWTs?

Yes. URL-safe characters - and _ are normalized automatically, and missing padding is tolerated. Note that a whole dotted token is not itself valid Base64 — decode segments individually, or use the dedicated JWT Debugger which handles the anatomy for you.

Does Encode produce URL-safe Base64?

No — output always uses the standard alphabet (+, /, =). If a target system needs the URL-safe variant, swap +→-, /→_ and strip trailing = yourself.

Why does decoding open a new tab instead of replacing my text?

Deliberate design. Your original string stays in the root editor while each result gets its own numbered tab, so you can decode several payloads in a row, inspect each one, and hand any two of them to the compare page without re-pasting.

How large a string can it handle?

There is no artificial cap — the practical limit is your browser tab's memory. Multi-megabyte strings process comfortably on desktop; encoding runs through chunked conversion to avoid call-stack limits, so very long inputs don't crash the way naive one-shot btoa calls can.

Is it free? Do I need an account?

Completely free, no account, no usage limits, no watermarks. Like every tool on this site, it runs entirely on your device — your payloads are never sent to or stored on a server.

Working with tokens? The JWT Debugger decodes complete tokens — header, payload and signature checks included — which pairs naturally with this page's segment-by-segment decoding. To edit or inspect a decoded payload further, use the JSON Formatter; to diff two decoded results, the JSON Compare tool picks up right where tab-to-tab compare hands off.