Base64 vs Base64URL: Padding, JWT Segments, and PEM Line Wraps
Symptom: “looks like Base64” but every decoder disagrees
You paste a JWT segment into a generic Base64 box and get garbage, or a PEM blob fails after someone “cleaned” the newlines. The bytes were never wrong — the dialect was. Standard Base64 (RFC 4648 §4), Base64URL (RFC 4648 §5 / JWT), and PEM (RFC 7468) all speak Base64-shaped text, but they disagree on two characters, on = padding, and on whether whitespace is allowed.
Use the on-site Base64 encoder/decoder with the URL-safe toggle when you need a round-trip, the JWT decoder when the string has two dots, and the certificate decoder when you see BEGIN CERTIFICATE.
Alphabet and padding in one table
| Rule | Standard Base64 | Base64URL (JWT) | PEM body |
|---|---|---|---|
| Char 62 / 63 | + / / | - / _ | + / / |
Trailing = | Usually present | Usually stripped | Present as needed |
| Whitespace | Often rejected or ignored | Not part of the token | Required as 64-char lines |
| Typical home | MIME, data URIs, APIs | header.payload.signature | Certificates / keys |
Conversion is mechanical:
- Standard → URL-safe:
+→-,/→_, drop= - URL-safe → standard: reverse the two characters, then pad length to a multiple of 4 with
=
Length after decode depends on the byte length, not on whether padding characters were written. Missing = is not corruption if the alphabet and length math still line up; it is a transport preference.
Why JWT refuses +, /, and =
A compact JWT is three Base64URL segments joined by .:
base64url(header) + "." + base64url(payload) + "." + base64url(signature)
Putting that string into a query parameter or Authorization header must not introduce characters that URL parsers treat specially. + can become a space in application/x-www-form-urlencoded. / splits path segments. = starts query values. Base64URL removes those landmines so the token travels as one opaque string.
Important consequences for debugging:
- Decode one segment at a time with a Base64URL-aware tool — or toggle URL-safe on the Base64 page. Feeding the whole
a.b.cstring into a MIME Base64 decoder will fail because of the dots. - Header and payload decode to JSON text. Signature bytes are opaque binary; expecting readable JSON there is a category error.
- JWT is not encryption. Base64URL only hides structure from casual eyeballing. Anyone with the token can read claims. See the JWT decode guide and exp/nbf clock skew for claim semantics after you can see the JSON.
Padding traps that look like “invalid token”
Libraries disagree on whether to re-add = before calling atob / b64decode. Patterns that burn hours:
- Proxy stripped
=from a standard Base64 field in a header. Local curl still had padding; the gateway did not. - One side URL-safe, the other standard. Signature verification fails even when the secret is correct — the signing input string no longer matches. Related: JWT signature invalid.
- Manual “fix” that adds
==to a Base64URL segment that already decoded fine. Extra padding of the wrong length throws; correct padding is'','=', or'=='so thatlen % 4 === 0.
Quick check: for a URL-safe segment s, compute pad = (4 - (s.length % 4)) % 4, append that many =, map -_ back to +/, then decode. If that works and the JSON looks sane, the original token was fine — your first decoder was not Base64URL-aware.
PEM: same alphabet as standard Base64, different packaging
PEM wraps DER (binary ASN.1) as:
-----BEGIN CERTIFICATE-----
<Base64 lines, typically 64 columns>
-----END CERTIFICATE-----
Compared with JWT:
| Concern | JWT segment | PEM body |
|---|---|---|
| Alphabet | Base64URL | Standard Base64 |
| Line breaks | Forbidden inside a segment | Expected every ~64 chars |
| Framing | Dots between three parts | BEGIN/END labels |
| After decode | JSON or raw sig bytes | DER certificate / key |
Common PEM failures that are not crypto bugs:
- Someone joined all lines into one mega-line and a strict consumer still accepts it — another rejects it. Prefer keeping RFC-style wrapping when pasting into configs.
- Copy/paste introduced a UTF-8 BOM or smart quotes around the labels.
- Only the leaf was pasted when the server needs leaf + intermediates (a chain problem, not a Base64 problem). Walk incomplete chain troubleshooting and the certificate decoder guide.
OpenSSL’s mental model stays useful: decode PEM → DER bytes → parse fields. The on-site certificate tool answers “what does this PEM say?”; it does not replace openssl verify for trust.
Decision tree: which tool first?
- String has two dots and three chunks → JWT decoder. Do not MIME-decode the whole token.
- String has
BEGIN …/END …→ certificate decoder (or key tooling). Preserve newlines. - Alphabet contains
-or_and no PEM labels → treat as Base64URL; use URL-safe mode on Base64. - Alphabet is
+/with optional=→ standard Base64 (API fields, data URIs, many crypto libraries). - Output looks like Chinese mojibake after a successful decode → charset mismatch (UTF-8 vs GBK), not alphabet mismatch. See Base64 Chinese garbled.
Implementer's note
ToolVault’s Base64 page maps UTF-8 text through TextEncoder / TextDecoder, then applies the selected alphabet and padding rules. URL-safe mode only remaps characters and padding — it does not change Unicode handling. JWT decoding is a separate path: split on ., Base64URL-decode each segment, lossless-parse JSON claims (large integers stay readable). Certificate decoding strips PEM labels, ignores internal whitespace, Base64-decodes to DER, then walks a browser-side ASN.1 subset. None of these paths upload your material.
Five-minute checklist
- Count dots: zero (blob), two (JWT), or PEM labels?
- Inspect characters 62/63:
+/or-_? - Is
=missing on purpose (JWT) or stripped by a proxy (bug)? - For PEM: are line breaks and BEGIN/END labels intact?
- After bytes decode cleanly, is the remaining failure JSON claims, signature crypto, or TLS trust?
Related reading
- Base64 encoding explained
- JWT explained: structure and security
- JWT exp/nbf clock skew
- Certificate decoder guide
- Incomplete certificate chain
This article is brought to you by ToolVault. More developer tools at the homepage.
Related Tools
Related Articles
JWT exp/nbf Clock Skew: Seconds vs Milliseconds, Leeway, and “Expired on Issue”
When JWT verification says Token expired or used before issued, check NumericDate units (seconds vs ms), NTP, and 30–60s leeway. Use the on-site decoder timeline and alg=none warning — and separate TLS cert failures from app-token 401s.
Image Formats Explained: JPG, PNG, WebP, HEIC, and SVG — Which One, When, and How to Convert
A practical guide to choosing image formats: what JPG, PNG, WebP, HEIC and SVG are actually good at, when compression hurts, why transparency changes everything, and how to convert between formats without losing quality.
Online Base64 to Image Converter: Decode Base64 Strings to Image Files
Learn how to convert Base64 encoded strings back to image files. Understand Base64 decoding principles, common image MIME types, and real-world Web development use cases.