Recognising It Before You Decode It
You're reading a log, an API response, or a database field, and there's a long string of letters, digits, plus signs and slashes. Is it Base64? And if so, what's inside?
Base64 is recognisable, and its first few characters often tell you what the encoded content is before you decode anything. That's because common file formats begin with fixed byte sequences — magic numbers — and those bytes always encode to the same Base64 prefix.
Prefixes Worth Knowing
iVBORw0KGgo PNG image
/9j/ JPEG image
R0lGOD GIF image
UklGR WebP (RIFF container)
JVBERi0 PDF document
UEsDB ZIP archive — also DOCX, XLSX, PPTX, JAR, APK
H4sI gzip-compressed data
eyJ JSON object — starts with {"
PD94bWwg XML declaration — <?xml
PHN2Zy SVG — <svg
TVqQ Windows executable (MZ header)
f0VMR Linux ELF executable
eyJ is the one you'll see most. It's {" encoded, which means a JSON object. It's why every JWT starts with eyJ — the header is a JSON object beginning {"alg":....
UEsDB catches people out because modern Office documents are ZIP archives, so a Base64-encoded Word document looks like a Base64-encoded ZIP. It is one.
TVqQ or f0VMR in unexpected places — an email attachment, an upload field, a pasted blob — means an executable. Worth noticing.
The Base64 Encoder/Decoder handles conversion in both directions:
- Paste the encoded or plain content.
- Choose encode or decode.
- Copy the result.
For binary content, decoding produces bytes rather than readable text — the prefix tells you what those bytes are before you try.
Is It Actually Base64?
Characteristics that suggest a string is Base64:
Character set. Only A–Z, a–z, 0–9, +, /, and possibly = at the end. The URL-safe variant substitutes - and _ for + and /.
Length a multiple of 4, when padding is present.
Padding at the end only. Zero, one or two = characters, never more, never in the middle.
No spaces, except possibly line breaks at regular intervals.
Characteristics that suggest it isn't:
- A length not divisible by 4 with padding present
=characters in the middle- Three or more trailing
= - Characters outside the alphabet
Beware false positives. Many ordinary strings happen to consist only of Base64-valid characters — a hex hash, a random identifier, a word like Hello. Being decodable doesn't mean something was encoded. A hex string decodes to meaningless bytes; the fact that it decoded tells you nothing.
Decoding Errors and What They Mean
"Invalid character." Something outside the alphabet is present. Common causes:
- URL-safe Base64 (
-and_) passed to a standard decoder - A space where a
+was, because the value passed through URL decoding which converted+to a space - A line break that the decoder doesn't expect
- Surrounding quotes or whitespace from copy-paste
The +-becomes-space problem is especially common. Base64 passed through a URL query string without encoding has its + characters converted to spaces by form decoding. The fix is either to URL-encode the Base64 value, or to use the URL-safe variant, which has no + at all.
"Incorrect padding." The length isn't a multiple of 4. Common causes:
- Padding was stripped, which is normal for URL-safe Base64 and for JWTs
- The value was truncated
Many decoders require padding. Adding = until the length is a multiple of 4 resolves stripped padding:
padding needed = (4 − length mod 4) mod 4
Truncation is different — adding padding to a truncated value produces a decode that looks successful and yields corrupt data. If the source is a log line or a database column with a length limit, check whether the value was cut.
Decodes but produces garbage. Several possibilities:
- It's binary content, not text — check the prefix
- It's been encoded twice — decode again and see whether the result is also Base64
- It's compressed — a
H4sIprefix means gzip, which needs decompressing after decoding - It's encrypted — decoding reveals ciphertext, which is indistinguishable from random bytes
- The text encoding is wrong — the bytes are UTF-16 being read as UTF-8, or similar
Double Encoding
Base64-encoding something already Base64-encoded is a common mistake, and it has a signature.
Original: hello
Once encoded: aGVsbG8=
Twice encoded: YUdWc2JHOD0=
Decode once. If the result is itself a plausible Base64 string, it was encoded twice.
The characteristic sign is a decoded value consisting entirely of Base64 characters, often with = padding at the end, where you expected readable content.
Fix it at the source, not by decoding twice at the consumer. Some serialisation layer is encoding a value that was already encoded.
Line Wrapping
MIME-encoded Base64 — used in email — wraps lines at 76 characters. PEM-encoded certificates and keys wrap at 64.
-----BEGIN CERTIFICATE-----
MIIDdzCCAl+gAwIBAgIEAgAAuTANBgkqhkiG9w0BAQUFADBaMQswCQYDVQQGEwJJ
RTESMBAGA1UEChMJQmFsdGltb3JlMRMwEQYDVQQLEwpDeWJlclRydXN0MSIwIAYD
...
-----END CERTIFICATE-----
Some decoders handle embedded line breaks, some don't. Stripping whitespace before decoding resolves this reliably — line breaks are never meaningful inside Base64 data.
The reverse matters too: Base64 destined for a JSON field, a URL, or an HTTP header must not contain line breaks. Some encoders wrap by default. Check the output of any encoding library you haven't used before.
What Base64 Doesn't Do
Because Base64-encoded data looks unreadable, it's routinely mistaken for protection.
It isn't encryption. Anyone can decode it instantly. No key is involved.
It isn't obfuscation in any meaningful sense. The prefixes above mean the content type is often visible at a glance.
It isn't compression. It makes data about 33% larger.
It isn't a hash. It's fully reversible.
Specific cases where this misunderstanding causes problems:
HTTP Basic authentication sends username:password Base64-encoded in a header. Without TLS, it's effectively plaintext. Decoding it takes no effort.
Credentials in configuration stored as Base64 — including Kubernetes Secrets, which are Base64-encoded rather than encrypted by default. Anyone with read access to the object can decode them.
"Encoded" API keys in client-side code. Encoding them first doesn't hide them from anyone who looks.
JWT payloads are Base64url-encoded, not encrypted. Anyone holding the token can read every claim. Never put secrets in a JWT payload.
When You Encounter Unexpected Base64
A short sequence for identifying unfamiliar encoded content:
1. Check the prefix against the table above.
2. Check for the URL-safe alphabet — - and _ — and use the matching decoder.
3. Strip whitespace and line breaks.
4. Fix padding if the length isn't a multiple of 4 and truncation isn't suspected.
5. Decode.
6. Inspect the result: readable text, recognisable binary format, another layer of Base64, or apparently random bytes.
7. If random, it's probably encrypted or compressed. Check for a gzip header or other compression signature.
Treat decoded content from untrusted sources carefully. An executable signature in an unexpected place is worth investigating, and decoded data should never be executed or rendered without the same validation you'd apply to any untrusted input.
Practical Tips
Learn eyJ, iVBOR, JVBER and UEsDB. They cover most of what you'll encounter.
Use the URL-safe variant for anything going into a URL, filename or header.
Strip whitespace before decoding.
Check for double encoding when decoded output looks like more Base64.
Never treat Base64 as protection for credentials or sensitive data.
Don't assume decodability means encoding. Many strings happen to be valid Base64.
Watch for truncation before adding padding.
FAQ
Why do JWTs always start with eyJ?
The header is a JSON object beginning with {", which encodes to eyJ in Base64.
Why does my Base64 fail with "invalid character"?
Most often URL-safe characters passed to a standard decoder, or + converted to a space during URL decoding.
How do I fix "incorrect padding"?
Add = characters until the length is a multiple of 4 — unless the value was truncated, in which case padding produces corrupt output.
Is Base64 encryption? No. It's reversible without any key. It provides no confidentiality.
How can I tell what's inside a Base64 string?
Check the first few characters. Common file formats produce characteristic prefixes — iVBOR for PNG, JVBER for PDF, eyJ for JSON.
Why is my decoded output more Base64? It was encoded twice. Decode again, and fix the double encoding at its source.
The Takeaway
Base64 is readable if you know what to look for: the prefix identifies the content, the alphabet identifies the variant, and the padding tells you whether it was truncated. Most decoding failures resolve at one of those three checks — and none of them involve any secrecy, because there isn't any.
Encode and decode Base64 free with the Base64 Encoder/Decoder at sadiqbd.com — no sign-up, instant results.