Base64 explained: padding, base64url, size and common mistakes

What Base64 does to your bytes, where it shows up in day-to-day work, and the errors that make a decode fail. Try every example in the live Base64 Encoder & Decoder.

Updated · By Alexander Braz

What Base64 is for

Base64 represents arbitrary bytes using only 64 printable ASCII characters, so binary data can travel through channels built for text: JSON fields, email bodies, HTML attributes, environment variables, HTTP headers. It is defined in RFC 4648. The alphabet is A to Z, a to z, 0 to 9, + and /, with = used for padding.

Base64 is an encoding, not encryption. Anyone can reverse it without a key. If a configuration file stores a password in Base64, the password is stored in plain text with one extra step. Treat Base64 strings with the same care as whatever they decode to.

How the encoding works

The encoder reads the input three bytes at a time. Three bytes are 24 bits, which it splits into four groups of 6 bits. Each 6-bit group is a number from 0 to 63, and that number picks one character from the alphabet. Three bytes in, four characters out.

When the input length is not a multiple of three, the last group is short. RFC 4648 fills it with zero bits and adds padding so the output length stays a multiple of four. One leftover byte produces two characters plus ==, and two leftover bytes produce three characters plus =. The test vectors in the RFC show the pattern clearly, and Fieldkit's encoder reproduces them exactly:

f      → Zg==
fo     → Zm8=
foo    → Zm9v
foob   → Zm9vYg==
fooba  → Zm9vYmE=
foobar → Zm9vYmFy

The size cost

Because every 3 bytes become 4 characters, Base64 output is about a third larger than the input. The exact length is 4 × ceil(n / 3) characters for n bytes: 10 bytes become 16 characters, 100 become 136, and 1,000 become 1,336. That is why embedding large images as Base64 data URLs in CSS or HTML makes pages heavier, and why a file uploaded inside a JSON body takes more bandwidth than a multipart upload of the same file.

Text has to become bytes first

Base64 works on bytes, not on characters. Before text can be encoded, it has to be turned into bytes with some character encoding, and the result depends on which one. Fieldkit always uses UTF-8. The euro sign € is three bytes in UTF-8 (E2 82 AC) and encodes to 4oKs. A tool that encoded it as Windows-1252 would produce something else. When a decoded string shows odd characters such as é instead of é, the bytes are usually fine and the two sides simply disagree about the text encoding.

The browser's built-in btoa() only accepts characters in the Latin-1 range, so btoa("€") throws an error. That is why the tool converts the text to UTF-8 bytes with TextEncoder before encoding.

base64url: the URL-safe variant

+ and / have special meanings in URLs and file paths. Section 5 of RFC 4648 defines a second alphabet, usually called base64url, that replaces them with - and _. The RFC notes that padding can be left off when the length is known from context, and many formats do exactly that.

The difference is easy to see with a short input. hi? encodes to aGk/ in standard Base64 and to aGk_ in base64url. JSON Web Tokens, many OAuth parameters, and signed URLs use base64url without padding. A standard decoder will reject the - and _ characters, which brings us to the most common real-world use of a Base64 decoder.

Worked example: reading a JWT payload

A JWT has three base64url parts separated by dots: header, payload, signature. Suppose an API returns a token whose middle part is:

eyJzdWIiOiJ1c2VyLTg4NDEiLCJuYW1lIjoiWm_DqyIsInNjb3BlIjoicmVhZDpyZXBvcnRzIiwiZXhwIjoxNzkxNDc1MjAwfQ
  1. Paste it into the tool and click Decode. Status shows the "Invalid Base64" error. The decoder follows the standard alphabet, and this string contains an underscore in Wm_D.
  2. Replace every - with + and every _ with /. Here that changes Wm_D to Wm/D. You do not need to add the missing =; the browser's decoder accepts unpadded input.
  3. Decode again. The output is {"sub":"user-8841","name":"Zoë","scope":"read:reports","exp":1791475200}. The ë comes back correctly because the payload is UTF-8 and the tool decodes it as UTF-8.
  4. To check the expiry, paste 1791475200 into the Timestamp Converter: 2026-10-08T16:00:00.000Z.

Decoding a JWT tells you what it claims. It does not tell you whether to trust it. Only verifying the signature with the right key does that, and that belongs in your server code, not in a browser tab. Also keep in mind that a token is a credential while it is valid, so avoid pasting live production tokens into any website you do not control.

Line breaks, whitespace and padding errors

MIME email wraps Base64 at 76 characters per line, and PEM files (certificates, keys) wrap at 64. RFC 4648 itself says encoders must not add line breaks unless the specification that uses them asks for it, so a plain Base64 string should be one line. Fieldkit's decoder strips spaces and line breaks before decoding, so you can paste a wrapped block straight from a PEM file or an email source.

Errors you are likely to meet:

  • Wrong length. After whitespace is removed, a valid string never has a length that leaves a remainder of 1 when divided by 4. abcde fails for that reason. It usually means the value was truncated when it was copied.
  • Padding in the middle. Zg==Zg== is two encoded values glued together, not one. Decode them separately.
  • Binary output shown as text. Decoding a PNG header such as iVBORw0KGgo= gives you bytes that are not valid UTF-8, so the output contains replacement characters (�) mixed with fragments like PNG. The decode worked; the result simply is not text. This tool is for text, so decode binary data with a script or command-line tool that writes bytes to a file.

Where you will meet Base64

  • HTTP Basic authentication (RFC 7617) sends user:password in Base64. The example in the RFC, Aladdin:open sesame, encodes to QWxhZGRpbjpvcGVuIHNlc2FtZQ==. This is why Basic auth is only safe over HTTPS.
  • Data URLs (RFC 2397) embed small files in HTML and CSS as data:image/png;base64,....
  • Kubernetes Secrets store values in Base64 in their data field. Again, that is encoding, not protection.
  • Email attachments use the MIME Base64 transfer encoding with wrapped lines.

When not to use it

Do not use Base64 to hide secrets, to "sanitize" input, or as a compression step; it makes data bigger. If a binary file needs to move between two systems that can both handle binary, send the bytes directly. Use Base64 when a text-only channel is the only option, and use base64url when the result has to live inside a URL.

Open the live tool

Open Base64 Encoder & Decoder Related reading: all guides · FAQ.