Paste Base64 to decode it immediately. If you call it “Base64 decrypt”, this tool decodes the data; Base64 is encoding, not encryption. Copy the text or download the exact bytes, locally in your browser.
Paste a string below. No account or upload is needed.
Also known as base64decode, b64 decode, base 64 converter or 64 decode. These names share this one tool, not separate decoders.
Verified October 24, 2026 with Python 3.13.15 (base64.b64decode(validate=True)), Node.js v24.19.0 (Buffer.from(input, 'base64')) and this page's decoder. Cells show decoded hexadecimal bytes, not text. These are different parsing policies; a permissive result does not certify valid input.
| Input (escaped whitespace) | This tool | Python, validate=True | Node Buffer |
|---|---|---|---|
Zg== | 66 | 66 | 66 |
Zh== | 66 (non-zero pad bits) | 66 | 66 |
Zg | 66 | REJECT | 66 |
SGVsbG8= | 48656c6c6f | 48656c6c6f | 48656c6c6f |
/w== | ff | ff | ff |
SGVsbG8_ | 48656c6c6f3f | REJECT | 48656c6c6f3f |
Z=== | REJECT | REJECT | (empty) |
A | REJECT | REJECT | (empty) |
SG Vs\nbG8= | 48656c6c6f | REJECT | 48656c6c6f |
Short input is not automatically invalid. A is rejected because a one-character Base64 body cannot encode a complete byte, not because this tool requires five characters. NQ== has only four characters and decodes here to 5 (byte 35 in hexadecimal). In an r/shortcuts thread opened July 19, 2026, a July 20 comment described a “5 character minimum” while discussing a failed Shortcuts decoding path. That is a user-reported app behavior, not a Base64 requirement; this site has not independently reproduced that Shortcuts issue.
Zg== and Zh== both decode to byte 66. The latter has non-zero unused pad bits. This tool accepts that alias and flags it; it does not silently claim the spelling is canonical. A byte hash also matches for both inputs, so use a spelling check separately when exact canonical tokens matter.
/w== produces byte ff, which is not valid UTF-8 text. The text result stays empty with an error, but Download decoded bytes still saves the original byte. SHA-256 is calculated over those bytes, before any character-set interpretation. Compare the displayed digest with your downloaded file, for example python -c "import hashlib; print(hashlib.sha256(open('decoded.bin','rb').read()).hexdigest())".
Get the scripts and decoder cores from the public GitHub repository. Download the Python regression runner and decoder core into one folder, then run python base64-decode-regression.py base64-decoder-core.js. Python and Node.js are required; no package installation or network call is used. The recorded results with versions and byte hashes let you compare the output. Future runtime versions may behave differently.
The tool accepts ASCII whitespace, omitted padding and URL-safe - _. It rejects misplaced/excess padding, illegal characters and impossible lengths. Non-zero unused pad bits are reported but accepted. These are explicit tool policies, not a claim that all decoders must behave alike.
These names use the same decoder above. Paste SGVsbG8= to get Hello. The spacing in “base 64” does not change the format.
Decode bytes first, then interpret them as text. For /w==, the byte is ff; it is not valid UTF-8 text. Use the byte download instead of replacing the original bytes with a question mark.
Switch the same tool to Encode for the opposite direction: Hello becomes SGVsbG8=. Use Base64url when the receiving protocol requires that alphabet. For Base32 input, use the Base32 decoder.
Base64 does not encode text — it encodes bytes. The character set decides what those bytes are, so the same visible text can produce different Base64. This readout shows the choice being made.
| Character | Code point | Bytes in this charset | Kind |
|---|
+ and / break itStandard Base64 uses + and /. Both are meaningful characters in a URL, so the moment the value travels in a link or a query string, the meaning can change. This is the step almost every Base64 tool skips.

———+ is read as a space in a query string?token=SGVsbG8+A==SGVsbG8 A== — the + became a space%2B for the plus, or switch to URL-safe Base64/ splits a path segmenthttps://api.example.com/get/Pj4/Pyc=Pj4 and Pyc= — not one value%2F for the slash, or URL-safe Base64= padding gets trimmed or misread?id=SGVsbG8==, and inside a query value it also collides with the key=value separator%3D, or use unpadded URL-safe Base64 (what JWTs do)state, or an AWS S3 presigned signature+ and / are not in the URL-safe alphabet, so the receiver fails or decodes to the wrong bytes+ → -, / → _%2B → %252B — the receiver decodes it back to the literal text %2B, not a plusatob() expects standard Base64, not URL-safeatob('Pj4_Pyc-Pg') throws — - and _ are not valid to it-→+, _→/, then re-add padding before calling atob()Use the URL-safe alphabet (- and _, usually with padding dropped) whenever the Base64 value travels somewhere with URL or identifier rules:
· anywhere inside a URL — a path segment, a query parameter, a fragment
· JWT / JWS / JWK segments, OAuth state and PKCE code_verifier
· AWS S3 presigned URLs and other signatures that are specified as base64url
· filenames, headers, or anything that must avoid + and /
Stay on standard Base64 when the consumer expects it — MIME email attachments, PEM, most plain-text Base64 blobs, and default decoders such as atob(), Buffer.from(s,'base64'), base64.b64decode(). When in doubt, check what the receiving side specifies, and encode once with that alphabet.
No login · Unlimited use · No watermark · Runs only in your browser. This tool encodes bytes exactly once, with the character set and alphabet you choose, and shows you both while it works.
See why standard Base64 uses URL-troublesome characters and how Base64URL changes the alphabet for safe transport.
Every tool on this site runs entirely in your browser. Pick the encoding problem you have: