About the Base64 Decoder
Base64 decode a string and read the result as UTF-8 text, or save it as a file when it turns out to be an image, a PDF or a ZIP. Paste standard Base64, Base64URL, a value with its = padding missing, or a whole data: URL; the decoder tidies the input before decoding it.
Base64 strings turn up all over a developer's day: the data values in kubectl get secret -o yaml, an Authorization: Basic header in a request log, the middle part of a JWT, a Content-Transfer-Encoding: base64 block in raw email, or an API field that carries a PDF. When the decoded bytes aren't text, you see a hex preview and can download the file with the right extension.
- Paste the string into Base64 to decode. Load sample decodes a short greeting with accents, Chinese characters and an emoji.
- Text appears under Decoded text, with the byte count below it. The count is bytes, not characters, so
你好adds 6, not 2. - If the bytes aren't valid UTF-8, you get This looks like binary data with the size, and a Hex preview of up to the first 4,096 bytes. The first few bytes tell you the file type; the Guide tab lists the common ones.
- Click Download file to save binary data. PNG, JPEG, GIF, PDF, ZIP and gzip are recognized from their first bytes and get the right extension. Anything else is saved as
decoded.bin. - A red Error box means the string has characters Base64 doesn't use, or the wrong length. The Guide tab lists the usual causes and how to fix each one.
InputcG9zdGdyZXM6Ly9hcHA6czNjcjN0QGRiLmludGVybmFsOjU0MzIvc2hvcA==Outputpostgres://app:s3cr3t@db.internal:5432/shop43 bytes decoded (UTF-8). kubectl shows Secret data values in Base64, and decoding gives you the real connection string, password included.
InputeyJhbGciOiJIUzI1NiIsInR5cCI6IkpXVCJ9Output{"alg":"HS256","typ":"JWT"}JWT parts are Base64URL with no = at the end, and they decode here as they are. For the whole token with its claims explained, use the JWT Decoder.
Inputdata:image/png;base64,iVBORw0KGgo=OutputThis looks like binary data, 8 bytes
Hex preview:
89 50 4e 47 0d 0a 1a 0aThe data:image/png;base64, prefix is removed first. 89 50 4e 47 is how every PNG file starts, so Download file saves it as decoded.png.
What the decoder cleans up
Base64 copied out of real systems is rarely clean. Before decoding, the input is tidied up:
- A
data:...;base64,prefix is removed, along with spaces at the start and end. - Line breaks and tabs are dropped, so MIME email bodies (76 characters per line) decode as one value. For a PEM certificate, paste only the lines between BEGIN and END.
-and_from Base64URL are read as+and/, and missing=padding is added back.- A space inside the string is read as
+. A+in a URL query often becomes a space on the way, so this repairs Base64 copied out of a link.
Why a Base64 string won't decode
Anything outside the Base64 alphabet stops the decoder with an error. These are the usual culprits:
- Quotes copied with the value, as in
"SGVsbG8="from a JSON file. Remove them. - A full JWT. Its dots aren't Base64 characters, so decode one part at a time, or paste the token into the JWT Decoder.
- Leftover URL encoding such as
%2B,%2For%3D. Run the string through the URL Decoder first. - A value cut off while copying. Valid Base64 never has a length of
4n + 1characters, so the error says the length is wrong. Copy it again in full.
Is it text or a file? Read the first characters
The decoder tries strict UTF-8 first and shows hex when that fails, instead of garbled characters. You can often tell what a Base64 string holds before decoding it, from how it starts:
eyJ: almost always a JSON object starting with{". JWT headers and payloads start like this.iVBORw0KGgo: a PNG image (bytes89 50 4E 47 0D 0A 1A 0A)./9j/: a JPEG image (FF D8 FF).R0lGOD: a GIF image (GIF8).JVBERi0: a PDF document (%PDF-).UEsDBA: a ZIP archive (PK)..docx,.xlsxand.jarfiles are ZIP archives too.H4sI: gzip data (1F 8B 08). Helm stores releases in Kubernetes Secrets this way, so reading one by hand takes two Base64 decodes and a gunzip.
Text in an old encoding
Text saved in Latin-1 or Windows-1252 also lands in the binary view. Y2Fm6Q== is café in Latin-1: its last byte, e9, is not valid UTF-8, so the hex preview shows 63 61 66 e9. Decode it in code with the right charset, for example .decode("latin-1") in Python.
Base64 decode in code
JavaScript's atob() returns one character per byte, which garbles UTF-8: atob("Q2Fmw6kg8J+Riw==") gives Café ð and some control characters instead of Café 👋. Pass the bytes through TextDecoder.
const bytes = Uint8Array.from(atob("Q2Fmw6kg8J+Riw=="), (c) => c.charCodeAt(0));
new TextDecoder().decode(bytes);
// 'Café 👋'
// Current browsers also have Uint8Array.fromBase64():
new TextDecoder().decode(Uint8Array.fromBase64("eyJhbGciOiJIUzI1NiJ9", { alphabet: "base64url" }));
// '{"alg":"HS256"}'Buffer.from("Q2Fmw6kg8J+Riw==", "base64").toString("utf8");
// 'Café 👋'
// Careful: Buffer.from skips characters it doesn't know instead of throwing.
Buffer.from("SGVs!!bG8=", "base64").toString(); // 'Hello'import base64
base64.b64decode("Q2Fmw6kg8J+Riw==", validate=True).decode("utf-8")
# 'Café 👋'
# b64decode needs the padding. For Base64URL without it:
s = "eyJhbGciOiJIUzI1NiJ9"
base64.urlsafe_b64decode(s + "=" * (-len(s) % 4))
# b'{"alg":"HS256"}'b, err := base64.StdEncoding.DecodeString("Q2Fmw6kg8J+Riw==")
// Base64URL without padding:
b, err = base64.RawURLEncoding.DecodeString("eyJhbGciOiJIUzI1NiJ9")new String(Base64.getDecoder().decode(s), StandardCharsets.UTF_8);
// Base64URL:
Base64.getUrlDecoder().decode(s);Encoding.UTF8.GetString(Convert.FromBase64String(s));base64_decode($s, true); // strict mode: returns false on invalid charactersprintf '%s' 'SGVsbG8sIHdvcmxkIQ==' | base64 --decode
# Hello, world!
# One value from a Kubernetes Secret:
kubectl get secret db -o jsonpath='{.data.url}' | base64 --decode[Text.Encoding]::UTF8.GetString([Convert]::FromBase64String($s))How do I decode Base64 to an image or a file?
Paste the Base64 or the whole data: URL, then click Download file under the hex preview. The extension comes from the file's first bytes: .png, .jpg, .gif, .pdf, .zip or .gz, and .bin when the type isn't recognized.
Why does my decoded text show é instead of é?
UTF-8 bytes were read as Latin-1, one byte per character, which is exactly what JavaScript's atob() does. This decoder reads UTF-8 properly. In your own code, decode the bytes with an explicit UTF-8 charset or TextDecoder.
Can I decode Base64URL or Base64 without padding?
Yes. - and _ are mapped back to + and / and the missing = is added, so JWT parts, PKCE values and other Base64URL strings decode without any editing.
How can I tell if a string is Base64?
It uses only A-Z, a-z, 0-9, + and / (or - and _), ends with at most two =, and its padded length is a multiple of 4. That only shows it could be Base64, since a word like abcd passes too. Decoding it and checking that the result makes sense is the real test.
Why does decoding fail with an error about the length?
A Base64 string can't be 4n + 1 characters long, so one character is missing or extra. Usually the value was cut off while copying, for example by a log line limit or a terminal window. Copy it again in full.
Do I need a key or password to decode Base64?
No, there's no key. That's why Authorization: Basic dXNlcjpwYXNz in a log exposes the password: it decodes to user:pass for anyone who reads the log. To protect data, encrypt it; Base64 only makes it safe to carry as text.
Is it safe to paste a Kubernetes Secret or a Basic auth header here?
The string is decoded by JavaScript in this tab and never uploaded, so the decoder doesn't expose it. The decoded value is the real credential, though, so keep it out of tickets, chat messages and screenshots.