Developer tools · JWT decoder
Base64 vs Base64url: Why a JWT Fails in a Standard Base64 Decoder
· How it works
jwt base64 encoding
Paste a JWT segment into an ordinary base64 decoder and it may complain about characters or padding. This post explains the base64url variant JWS mandates and how to convert between the two.
Invalid character, incorrect padding — the errors that appear when base64 meets base64url
An “invalid character” or “incorrect padding” message often means a JWT segment was given to a decoder that expects ordinary Base64. The token may be copied correctly. Its representation follows base64url conventions, while the receiving utility accepts a related but not identical alphabet or insists on explicit padding.
ToolAcre avoids that mismatch for the header and payload. Its byte decoder removes whitespace, translates URL-safe symbols, restores omitted padding when the length permits it, then converts bytes as strict UTF-8. Failure at any stage becomes an INVALID_JWT error rather than a raw browser exception.
Two alphabets — plus and slash versus hyphen and underscore, and why URLs forced the change
Standard Base64 uses plus and slash for its final two alphabet positions. Base64url assigns hyphen and underscore to those same positions. The underlying six-bit values do not change, so translating `-` to `+` and `_` to `/` preserves every decoded byte; only the transport-safe spelling changes.
Those substitutions matter in channels where plus or slash already has syntax. A URL-safe spelling reduces accidental interpretation by form or path processing. It does not add secrecy, integrity or authenticity. Anyone who receives a segment can reverse the substitutions and recover the same bytes without a cryptographic key.
Padding — why JWS strips the equals signs and how to restore them for a strict decoder
ToolAcre accepts omitted padding. After alphabet normalisation, it examines the segment length modulo four. A remainder of two needs two equals signs, and a remainder of three needs one. A remainder of one is impossible for a complete Base64 value and is rejected as a truncated string rather than guessed into shape.
Padding recovery is mechanical framing, not token repair. Adding equals signs cannot restore characters lost during copying, and successful byte decoding does not show that the bytes came from an issuer. The implementation merely reconstructs the canonical length required by the browser decoder before calling `atob`.
Decoding the whole token at once — the mistake of not splitting on the dots first
A compact signed token must be split on its dots before any segment is decoded. Passing `header.payload.signature` to a Base64 function introduces dots that belong to JWT serialization, not either Base64 alphabet. ToolAcre requires exactly three segments for this JWS-shaped input and reports the observed count when that structure is absent.
The five-part case receives a separate JWE message because encrypted compact serialization is not the same object. Two or four parts instead suggest truncation or the wrong input. This structural check comes before JSON interpretation, keeping a copy error distinct from malformed encoded text or malformed JSON.
Worked example — converting one segment from base64url to base64, padding it and decoding it to JSON
For a worked conversion, take `eyJhbGciOiJIUzI1NiJ9`. It contains no alphabet characters that differ between variants, but its missing padding still illustrates the pipeline. Its length permits padding restoration; decoding yields UTF-8 bytes for `{"alg":"HS256"}`, and JSON parsing produces an object with one `alg` property.
A segment containing hyphen or underscore follows the same sequence with the two symbol replacements first. ToolAcre performs these operations inside `base64ToBytes`, then `decodeSegment` parses the resulting text. The displayed algorithm is whatever the unverified header declares; it is not selected as a verification policy.
Unicode in claims — why the decoded bytes must be read as UTF-8 to display names correctly
Claims may contain accents, CJK characters or emoji. Base64 operates on bytes, so treating each decoded byte as an independent character corrupts multibyte text. The correct path is encoded symbols to bytes, then a UTF-8 decoder. ToolAcre constructs `TextDecoder` with fatal mode so invalid UTF-8 fails loudly.
The tests cover a payload containing `Zoë 世界 🙂` and expect the exact string after decoding. That result proves the byte-to-text pipeline preserved this test value. It still says nothing about whether the person named by the payload exists, whether the issuer approved the claim or whether the token was altered.
What this does not cover — the signature segment, which decodes to bytes rather than text and needs a key to mean anything
The signature segment is outside the JSON path. ToolAcre keeps its original encoded form and tries only to measure the decoded byte length. Invalid signature Base64 produces a warning but does not prevent header and payload inspection; an empty third segment produces a different warning that no signature bytes are present.
Neither outcome is a verification result. Meaningful signature validation needs trusted key material, a permitted algorithm chosen independently of attacker-controlled input, and application checks. A byte count is useful when diagnosing shape, but zero or thirty-two measured bytes cannot authorize a request or establish an issuer.
Takeaway: use a decoder that speaks base64url — the ToolAcre JWT decoder handles the alphabet and padding for the header and payload
Use a decoder that understands base64url when the immediate job is inspecting JSON. ToolAcre handles the alphabet, omitted padding, strict UTF-8 and object-only JSON for the first two segments. It also rejects impossible lengths and wraps parse failures in messages that identify whether header or payload failed.
Stop at that boundary. A clean decode means the string had recoverable bytes and suitable JSON objects. It does not mean its claims are trustworthy, authenticated, authorized or unmodified. Only a separately configured verifier can answer those questions, and this browser tool deliberately exposes no verification operation.