How to Encode and Decode Base64 Without Guessing

Base64 shows up when you least want a new problem. An API wants a basic auth header. An email attachment looks like alphabet soup. A data URL starts with data:image/png;base64, and you need the actual image. A JWT middle section is Base64url, which is almost Base64 and enough different to waste twenty minutes.

You do not need to love encoding theory. You need to encode bytes to text without corruption, and decode text back to bytes without silently getting garbage. Nicxro’s Base64 tool is for that conversion when you are not writing a script yet, or when you want a second pair of eyes on a string that “should work.”

What Base64 is for

Computers like bytes. A lot of systems like text: headers, XML, JSON strings, copy-paste into a ticket.

Base64 turns bytes into a limited set of characters: A–Z, a–z, 0–9, plus + and /, with = for padding. The result is about a third larger than the original. You pay size to get safe text.

That is why you see it in:

  • HTTP Basic authentication: Authorization: Basic plus Base64 of user:password
  • Data URLs for small images and fonts
  • Email MIME attachments
  • Embedding binary in JSON when the API designer gave up on multipart
  • The parts of a JWT (with a URL-safe variant)

Base64 is not encryption. Anyone can decode it. Hiding a password in Base64 in frontend code is the same as putting the password in frontend code. Encode for transport and embedding. Encrypt if the point is secrecy.

Encode when you have bytes, not when you have “a string” in the abstract

The usual confusion is character encoding.

If you Base64-encode the text café, you must decide whether those letters are UTF-8 bytes, UTF-16 bytes, or something else. UTF-8 is the default you want almost always. If one side encodes as UTF-8 and the other decodes as Latin-1, you get mojibake, not a Base64 failure. The Base64 layer was fine. The text layer was not.

When you encode a file, you encode file bytes. Do not open a PNG in a text editor, copy “the characters,” and encode that. You will encode a corrupted interpretation of binary. Use a file-aware tool or a script that reads bytes.

When you encode a password for Basic auth, you encode username:password as UTF-8, then Base64. If the password contains Unicode, UTF-8 still applies. If an old server expects ISO-8859-1, you will get 401s that look mysterious. Match the server.

Decode when the alphabet looks right

A valid Base64 string uses the alphabet above. Whitespace is sometimes allowed by decoders and sometimes not. Line breaks every 76 characters appear in MIME. A decoder that is MIME-aware will ignore them. A strict decoder will fail.

If decode fails, check:

  • Missing padding = at the end. Some systems omit padding. Some decoders require it.
  • URL-safe alphabet: - and _ instead of + and /. JWTs use this. A standard decoder will choke. Convert or use a Base64url mode.
  • Extra quotes. You copied "eyJhbGciOi..." including the JSON quotes.
  • A data URL prefix. Strip data:image/png;base64, before decoding the payload, or use a tool that understands data URLs.
  • The string is hex, not Base64. Hex looks like 4a 3f. Base64 looks like Sj8=.

Garbage-in decode can “succeed” and give you nonsense bytes. If you expected a JSON object and got random binary, you decoded the wrong layer or the wrong variant.

Basic auth, done carefully

You have a user ada and a password s3cret. The string to encode is ada:s3cret. The header is Authorization: Basic plus a space plus the Base64 output.

Do not encode ada and s3cret separately. Do not include the word Basic inside the encoded part. Do not leak this header in screenshots. Decoding Basic auth is trivial, which is why Basic auth over HTTP is a bad idea. Use HTTPS.

When an integration fails, decode the header you actually sent. You will often find a newline, a BOM, or ada: s3cret with a space after the colon. Decode is the fastest way to see what you really encoded.

Use Nicxro to encode a test credential you do not care about, then compare with what your HTTP client produced. Production passwords should not live in a blog tab longer than they must. Prefer environment variables and a local command when the secret is real.

Data URLs and images

Small icons as data URLs reduce requests. Large photos as data URLs bloat HTML and defeat caching.

If you need to inspect a data URL, split on the comma. The left side is metadata. The right side is Base64. Decode the right side and save as a file with the type from the metadata. If the image is corrupt, the Base64 may have been truncated in CSS, or HTML entity-encoded, or split across lines in a way your decoder did not ignore.

When encoding an image for a data URL, encode the raw file bytes, then prefix data:image/png;base64, or the correct MIME type. Wrong MIME plus correct bytes still confuses some browsers.

If the goal is a smaller page, compress the image first on Nicxro, then encode. Base64 makes files bigger. Starting from a huge PNG makes the HTML worse.

JSON, XML, and “just paste it in the field”

APIs sometimes want a file as a Base64 string in JSON. That string can be huge. Some JSON parsers have size limits. Some databases hate 20MB text fields.

When debugging, decode a prefix of the string, not necessarily the whole thing, to see if it starts with PNG’s magic bytes (iVBORw0KGgo is a common PNG Base64 start) or { for JSON. If you expected a PDF and the decoded bytes start with PK, you have a zip. That is already useful.

Watch JSON escaping. A Base64 string in JSON should not contain raw newlines unless the spec allows JSON whitespace in strings, which it does not in the middle of a string. If your encoder wrapped lines, the JSON is invalid until you strip whitespace or disable wrapping.

JWT is Base64url, not textbook Base64

A JWT has three parts: header, payload, signature, separated by dots. Header and payload are Base64url-encoded JSON, usually without padding.

If you paste a full JWT into a standard Base64 decoder, it will fail because of the dots. Split on . and decode the first two parts with URL-safe rules. Nicxro’s JWT decoder is the better tool for that job. Use generic Base64 when you are dealing with generic Base64.

If you “fix” a JWT by replacing - with + and still fail, add padding until the length is a multiple of 4. Or use a tool that does that for you.

Padding, length, and the off-by-one feeling

Base64 output length is a multiple of 4. If someone trimmed = padding to save bytes, restore it before a strict decode. One character missing in the middle will scramble everything after it. If the start of a decoded file looks right and the end is trash, you likely lost the tail of the string in copy-paste.

Copy from a terminal that wrapped lines with extra spaces. Copy from Slack that converted + or mangled underscores. Decode, check the byte length, compare to the original file size if you have it. Base64 length should match 4 * ceil(bytes / 3).

Security and privacy, said plainly

Decoded Base64 can be a private key, a session token, or an ID card scan. Treat the clipboard as sensitive.

Do not post encoded secrets in tickets thinking they are unreadable. They are readable by anyone who knows the trick, which is everyone on your team and every bot that scrapes the ticket.

Do not use Base64 as a checksum. Use a hash if you need integrity. Base64 does not detect tampering. It does not even detect a typo unless the typo leaves the alphabet.

A simple encode/decode loop

  1. Know whether you have text or file bytes.
  2. For text, agree on UTF-8.
  3. Encode on Nicxro. Compare length to the expected size.
  4. Decode immediately as a round trip. You should get the same text or the same file.
  5. Only then paste the encoded value into the header, JSON field, or data URL.

If the round trip fails, stop integrating. The rest of the stack cannot save a bad encoding.

Base64 is a boring tool when you use it on purpose. It becomes a mystery when you treat it as encryption, as compression, or as “that long string APIs want.” Encode bytes to text. Decode text to bytes. Check the round trip. Move on.

Leave a Comment