Axonix Tools
Base64 Encoding Explained: What It Is, When You Need It, and When It'll Bite You
Back to Insights
Base64Developer ToolsEncoding

Base64 Encoding Explained: What It Is, When You Need It, and When It'll Bite You

7 min read
Reviewed:

Stop copy-pasting into random websites. Here's what Base64 encoding actually does, where it's used in real systems, and a free tool to encode and decode instantly.

That time I broke email attachments for a week

I'm going to admit something embarrassing. In 2022, I shipped code that corrupted every PDF attachment our system sent. For six days. Nobody noticed until a client asked why their invoices looked like abstract art.

The fix was one line. Buffer.from(file).toString('base64'). I'd been sending raw binary through a JSON API. JSON doesn't handle binary data. The binary bytes got mangled by the JSON serializer and came out the other side as garbage.

I'd been coding for six years at that point. Still made this mistake. So let's talk about what Base64 actually is, because clearly I needed this explained to me too.

What Base64 actually does

Base64 takes any data, text, images, binary files, in current usage, and turns it into a string of boring, safe characters. Letters, numbers, plus signs, slashes, and equals signs for padding. That's it.

Why bother? Because the internet was built by people in the 1980s who didn't anticipate us sending cat GIFs through email. Old systems choke on binary data. They see a byte that looks like a control character and stop processing. Base64 translates your binary into alphabet soup that won't break anything.

The tradeoff is that your data gets about thirty-three percent bigger. Three bytes become four characters. That's the math of it. You're trading size for safety.

How the encoding works

Base64 works by taking three bytes of input (24 bits) and splitting them into four groups of six bits each. Each six-bit group maps to one of sixty-four characters: A through Z, a through z, zero through nine, plus, and slash.

If your input isn't divisible by three, padding characters (equals signs) fill the gap. That's why Base64 strings often end with one or two equals signs.

Input:  "Hi"
Bytes:  [72, 105]  (only 2 bytes, not 3)
Output: "SGk="     (padding with one =)

The equals sign tells the decoder that the last group was incomplete. Without it, the decoder wouldn't know how to reconstruct the original data.

Where you'll actually encounter Base64

Embedding images in CSS. You've seen this:

background: url(data:image/png;base64,iVBORw0KGgoAAAANSUhEUg...);

That's a whole image, inline, inside your CSS file. No extra HTTP request. Useful for tiny icons. Terrible for anything bigger than about two kilobytes because your CSS file becomes enormous.

Sending files through APIs. JSON doesn't do binary. If you need to POST a file in a JSON body, Base64 is usually how. You encode the file to a Base64 string, send it as a regular JSON string field, and the server decodes it back to binary.

JWT tokens. That eyJhbGciOiJIUzI1NiIsInR5cCI6... string you see in authentication headers? Base64-encoded JSON. Three chunks separated by dots. The header, the payload, and the signature. Not encrypted. Anyone can decode it and read the contents. Don't put secrets in JWT payloads.

Basic auth headers. Authorization: Basic dXNlcjpwYXNz is just user:pass encoded. Again, not encrypted. If you're not on HTTPS, you're sending credentials in plaintext with extra steps.

Data URIs in HTML. You can embed any file type directly in HTML using the data: URI scheme. The file content is Base64-encoded and placed directly in the src attribute. This eliminates an HTTP request but increases the HTML file size.

Email attachments. MIME encoding for email attachments uses Base64. When you attach a file to an email, it gets Base64-encoded so it can travel through email systems that only handle text.

The tool

Half the Base64 tools online look like they haven't been updated since 2004. Some of them might be logging your input. I got paranoid enough to build one that runs entirely in your browser.

The Base64 Encoder/Decoder lets you paste text, click encode, get the result. Paste encoded text, click decode, get the original. No server. No logging. I use it almost daily.

Stuff that'll trip you up

Here's where I've watched junior devs, and myself, mess up.

It's not encryption. I've reviewed pull requests where someone secured passwords by Base64 encoding them before storing. Please don't. Anyone with a free online tool can decode it in two seconds. It's encoding, not encryption. Different words, different meanings. Encoding is about format conversion. Encryption is about secrecy.

URL-safe Base64 exists. Regular Base64 uses plus and forward slash, which break URLs. There's a variant that swaps those for hyphen and underscore. If your encoded string is going into a query parameter, you need the URL-safe version. Otherwise the plus gets interpreted as a space and the forward slash breaks the URL path.

Whitespace will ruin your day. Some encoders add line breaks every 76 characters. This is an old email standard called MIME line length. Some decoders can't handle line breaks. If your decoder is failing mysteriously, check for stray newlines in the encoded string. I've lost hours to this.

UTF-8 matters. The string "Hello" in UTF-8 produces different Base64 than "Hello" in UTF-16. If you're decoding something and getting garbage, check your character encoding first. Most web systems use UTF-8, but not all of them.

The padding equals signs are important. Some systems strip the padding. If you're decoding a Base64 string that's missing its equals signs, you might need to add them back. The number of missing characters tells you how many equals signs to add.

Base64 in different languages

JavaScript:

// Encode
const encoded = btoa('Hello, world!');
// "SGVsbG8sIHdvcmxkIQ=="

// Decode
const decoded = atob('SGVsbG8sIHdvcmxkIQ==');
// "Hello, world!"

For non-ASCII text, you need to handle UTF-8 encoding first:

const encoded = btoa(unescape(encodeURIComponent('Hello, δΈ–η•Œ!')));

Python:

import base64

encoded = base64.b64encode(b'Hello, world!').decode('utf-8')
# 'SGVsbG8sIHdvcmxkIQ=='

decoded = base64.b64decode('SGVsbG8sIHdvcmxkIQ==').decode('utf-8')
# 'Hello, world!'

Node.js:

const encoded = Buffer.from('Hello, world!').toString('base64');
// 'SGVsbG8sIHdvcmxkIQ=='

const decoded = Buffer.from('SGVsbG8sIHdvcmxkIQ==', 'base64').toString('utf-8');
// 'Hello, world!'

Quick cheat sheet

| Input | Output | Notes | |-------|--------|-------| | Hi | SGk= | Two bytes, one padding character | | Hello | SGVsbG8= | Five bytes, one padding character | | Hello, world! | SGVsbG8sIHdvcmxkIQ== | Thirteen bytes, two padding characters | | πŸ”₯ | 8J+UpQ== | Emoji is four bytes in UTF-8 |

When not to use Base64

Storing passwords. Use a proper hashing algorithm like bcrypt, argon2, or scrypt. Base64 is reversible. Password hashing should not be.

Compressing data. Base64 makes data bigger, not smaller. If you need to reduce size, use actual compression like gzip or zstd.

Hiding sensitive data. Base64 provides zero security. It's a format conversion, not a security measure. Anyone can decode it.

Replacing proper binary protocols. If you're building a system that needs to transfer binary data efficiently, use a binary protocol like Protocol Buffers or MessagePack instead of encoding binary as text.

Frequently asked questions

Why is Base64 output longer than the input?

Base64 converts three bytes into four characters. That's a thirty-three percent increase. The encoding trades size for compatibility with text-only systems.

Can Base64 encode any type of file?

Yes. Base64 works on bytes, not on text. You can encode images, PDFs, audio files, executables, anything. The output is always a string of safe ASCII characters.

Is Base64 the same as Base64URL?

No. Base64URL is a variant that replaces plus with hyphen and forward slash with underscore. It also typically omits padding. Use Base64URL when the encoded string goes into a URL or filename.

How do I decode a Base64 string without a tool?

You can use your browser's console. atob('your-string-here') decodes Base64. btoa('your-text-here') encodes to Base64. For non-ASCII text, you'll need to handle encoding separately.

Why do some Base64 strings end with equals signs?

The equals signs are padding. Base64 works in groups of three bytes. If your input isn't divisible by three, the encoder adds padding to complete the last group. One equals sign means two bytes of input. Two equals signs means one byte of input.

Final note

Base64 is one of those things that seems trivial until it breaks your application at 2 AM. The rules are simple: encode binary data before putting it in text formats, decode it before using it, and never confuse encoding with encryption.

If you need to encode or decode something quickly, the Base64 Encoder/Decoder runs in your browser. Paste, click, done.

Written by Axonix Team

Axonix Team - Technical Writer @ Axonix

Share this article

Discover More

View all articles

Need a tool for this workflow?

Axonix provides 100+ browser-based tools for practical development, design, file, and productivity tasks.

Explore Our Tools