Padded Base64 ends with = or == because it encodes 3 bytes at a time into 4 characters, and when the input runs out partway through a group of 3, the encoder pads the last group with = so the output is still a multiple of 4 characters. One leftover byte gives two characters plus ==, two leftover bytes give three characters plus =, and an input that divides evenly by 3 has no padding at all. To check this on your own strings without pasting them into a website, PrismKit’s offline Base64 encoder and decoder runs from a hotkey on your Windows PC.
The rules below come from RFC 4648, the standard that defines Base64, and RFC 7515, which defines JSON Web Signature, both checked on 28 October 2026.
Encode and decode Base64 offline from a hotkey.
Get it fromMicrosoft
How does Base64 turn bytes into characters?
Base64 takes the input 24 bits at a time, which is 3 bytes, and splits those 24 bits into four 6-bit groups. Each 6-bit group is one of 64 characters: A to Z, a to z, 0 to 9, + and /. So every 3 bytes in become exactly 4 characters out.
| Input | Bits | Output characters |
|---|---|---|
| 3 bytes | 24 | 4 |
| 6 bytes | 48 | 8 |
| 300 bytes | 2,400 | 400 |
That is also why long Base64 output is about a third larger than the input. To get the padded output length without line breaks, divide the input byte count by 3, round up to a whole group, then multiply by 4. One byte needs 4 characters, not 1.33. Count encoded bytes, not text characters; a Unicode character can occupy several UTF-8 bytes.
When does the encoder add = and ==?
When the input length is not a multiple of 3 bytes, the last group is short. RFC 4648 section 4 lists the only three cases that can arise:
| Bytes left in the final group | Output for that group | Padding |
|---|---|---|
| 3, a full group | 4 characters | None |
| 1 | 2 characters | == |
| 2 | 3 characters | = |
Canonical RFC 4648 Base64 uses at most two = characters, only at the end. A permissive decoder may accept extra padding under a referring specification’s rules, but that does not make === a normal encoder output.
What do the RFC test vectors show?
RFC 4648 section 10 gives test vectors that make the pattern easy to see:
| Input | Length in bytes | Base64 |
|---|---|---|
f | 1 | Zg== |
fo | 2 | Zm8= |
foo | 3 | Zm9v |
foob | 4 | Zm9vYg== |
fooba | 5 | Zm9vYmE= |
foobar | 6 | Zm9vYmFy |
Each time the length passes a multiple of 3, padding disappears; one byte later, == appears again. A quick way to read padding: == means the input length divided by 3 leaves 1, and = means it leaves 2.
What does a worked example look like?
Take the two-letter text Ma. In ASCII, M is the byte 0x4D and a is the byte 0x61. Written out in binary, that is 16 bits, which is one byte short of a full 3-byte group:
01001101 01100001
The encoder splits the bits into 6-bit groups. Sixteen bits do not divide evenly by 6, so it adds zero bits on the right to complete the last group, giving three groups of 6 bits:
010011 010110 000100
Those values are 19, 22 and 4, which map to the characters T, W and E in the Base64 alphabet. Because the final group held only 2 bytes instead of 3, the encoder appends one =, and the result is TWE=. Encode just M and you get TQ==, with two padding characters, because the final group held only one byte.
The extra zero bits add no payload bytes, and = marks the final group’s length rather than encoding a byte of its own. RFC 4648 section 3.5 requires encoders to set unused pad bits to zero; decoders may reject nonzero pad bits. Padding is not a checksum and does not prove that the input is intact.
Is padding required?
In standard Base64, yes, unless a specification says otherwise. RFC 4648 section 3.2 says implementations MUST include appropriate pad characters at the end of encoded data unless the specification referring to it explicitly states otherwise. It explains that padding is required to yield correct decoded data when assumptions about the size of transported data cannot be made.
RFC 4648 also says implementations MUST NOT add line feeds to base-encoded data unless the referring specification says to, which is another source of strings that look correct but fail to decode.
Check a Base64 string locally instead of in a browser tab.
Get it fromMicrosoft
Why do some Base64 strings have no padding?
Because some formats drop it on purpose. RFC 4648 section 5 defines a URL and filename safe variant, often called base64url, which uses - instead of + and _ instead of /. It notes that = is typically percent-encoded when used in a URI, as %3D, but if the data length is known implicitly, this can be avoided by skipping the padding.
Signed JSON Web Tokens are a common example. RFC 7515 defines base64url encoding for JWS with all trailing = characters omitted. A compact JWS header or payload therefore has no = at the end, even when its length is not a multiple of 4. Merely switching to the URL-safe alphabet does not universally make padding optional; the surrounding protocol defines that rule.
| Variant | Alphabet ends with | Padding |
|---|---|---|
| Standard Base64 | + and / | Required unless a spec says otherwise |
| base64url | - and _ | Follow the protocol; JWS requires omission |
How do you fix “incorrect padding” or “invalid length” errors?
The cause may be a variant mismatch, truncation or characters added during transport. Do not repair an arbitrary string by adding = until it decodes.
- Identify the format. For a compact signed JWT, inspect the header or payload separately, not the entire dotted token. Decoding is not signature verification, and an encrypted JWT payload is not readable JSON just because it is base64url-decoded.
- Check for transport changes. RFC 4648 decoders reject non-alphabet characters unless the surrounding specification allows them; MIME permits line wrapping, but JWS does not permit whitespace. A
+changed into a space by form decoding is data corruption, not harmless whitespace to delete. Recopy or fix the transport when uncertain. - Use the right alphabet. Prefer a base64url decoder for base64url. When adapting known base64url to a standard Base64 decoder, replace
-with+and_with/. - Restore padding only for known, complete unpadded input. RFC 7515 Appendix C gives the length rule below. It is not a way to recover missing payload characters.
- Reject malformed data. Check the alphabet, padding placement and unused pad bits as well as length. A length remainder of 1 is invalid, but other remainders do not prove the data is complete.
| Known unpadded input length divided by 4 leaves | Padding for a standard decoder |
|---|---|
| 0 | None |
| 2 | Add == |
| 3 | Add = |
| 1 | Invalid input; recover the original rather than guessing |
Our guide to decoding a JWT offline on Windows walks through the token case, and the Base64, URL and JSON encoding page covers the related encodings side by side.
Is Base64 the same as URL encoding?
No. Base64 turns bytes into a 64-character alphabet. URL encoding, also called percent-encoding, replaces unsafe characters in a URL with % and two hex digits. They often meet because standard Base64 contains +, / and =, which have meanings in URLs. Our article on URL encoding of spaces, %20 vs + explains why + is especially confusing.
How does PrismKit help?
PrismKit is Automata Labs’ keyboard-first developer utility for Windows. Its free core includes local Base64 and URL tools and JWT inspection, accessible through its command palette. You can inspect strings without uploading them to an online decoder. Base64 is encoding, not encryption: decoded credentials and customer data are still sensitive, so follow your organization’s handling rules, including for clipboard history and saved output.
Frequently asked questions
Can Base64 end with three = signs?
Not in canonical RFC 4648 output: it has no padding, = or ==. A permissive decoder may tolerate excess padding, which is different from a conforming encoder producing it.
Can I remove the = from Base64?
Only when the receiving format permits or requires omission and its decoder supports that form, as JWS does. Otherwise preserve the required padding.
Why does my JWT have no = at the end?
RFC 7515 specifies base64url with all trailing = characters omitted.
Does padding carry any data?
No. It only marks how many bytes the final group held.
Does PrismKit send my strings anywhere?
The Base64 workflow runs locally without a cloud dependency; no online decoder is needed. Treat copied strings and exported results as sensitive regardless of the tool.
Try PrismKit
PrismKit is free in the Microsoft Store, with optional one-time expansion packs. The listing shows the system requirements. The Base64, URL and JWT tools are part of the free core. More detail is on the PrismKit product page.
Keep Base64, URL and JWT tools one hotkey away, offline.
Get it fromMicrosoft
Last updated 28 October 2026. Published by Automata Labs, a software company in Canada.