Calculators Converters Generators Developer Tools Finance Tools Writing Tools SEO Tools
Blog About Contact

Base64 Encoding Explained: How It Works and When to Use It

💡 Quick Answer
Base64 converts binary data into **64 printable ASCII characters** so it can pass through systems built for text. It increases size by about **33%**. It is an encoding, **not encryption**: anyone can reverse it instantly, so it provides no security whatsoever.
Base64 Encoding Explained: How It Works and When to Use It

You open an API response and one field is a wall of letters and numbers ending in two equals signs. Or an email header contains a paragraph that is clearly not English. Or a config file has a certificate that looks like someone leaned on the keyboard.

That is base64, and it is doing something specific: carrying data that is not text through a channel that only handles text.

It shows up constantly once you know what it looks like, and it is regularly misunderstood in one important way. Here is how it works, why the padding characters appear, and the single mistake worth never making with it.

The problem base64 solves

Computers store everything as bytes, and a byte can hold any of 256 values. Text protocols were not built for that.

Email was designed to carry seven-bit ASCII. Many older systems treat certain byte values as control signals rather than data: a byte that happens to be 0x00 can terminate a string, 0x0D and 0x0A can be rewritten as line endings, and values above 127 may be stripped or mangled entirely.

Send a JPEG through a channel like that and it arrives corrupted. Not because anything failed, but because the channel did exactly what it was designed to do to bytes it considered special.

Base64 sidesteps this by restricting the output to 64 characters that every system agrees are safe: A to Z, a to z, 0 to 9, plus two symbols. Nothing in that set can be mistaken for a control character or altered in transit.

The cost is size. Base64 output is roughly 33% larger than the input, which is the price of using six bits of information per eight-bit character.

How the conversion actually works

Base64 reads your data three bytes at a time. Three bytes is 24 bits, and 24 divides evenly into four groups of six. Each six-bit group becomes one output character, so every three input bytes produce four output characters.

Six bits can express 64 values, hence the name and the 64-character alphabet:

A-Z = 0-25 a-z = 26-51 0-9 = 52-61 + = 62 / = 63

Work through the word Man:

1
The three characters have byte values 77, 97, 110.
2
Written in binary, that is 01001101 01100001 01101110.
3
Ignore the byte boundaries and regroup into six-bit chunks: 010011 010110 000101 101110.
4
In decimal those are 19, 22, 5, 46.
5
Look each up in the alphabet: 19 is T, 22 is W, 5 is F, 46 is u.

Man encodes to TWFu. Three bytes in, four characters out, and each output character carries six bits where the input carried eight. That ratio is exactly where the 33% size increase comes from: 900 bytes of input produce 1,200 characters of output.

→ Use our free Base64 Encoder at GlobalUtilityHub to encode or decode any string instantly. No sign-up needed.

Padding, and why you see equals signs

The three-byte grouping is clean when your data divides by three. Most data does not.

When the final group has only one or two bytes, base64 pads the bits out to a full six-bit boundary with zeros, then appends equals signs so the decoder knows how many bytes were really there.

InputBytesOutputPadding
`Man`3`TWFu`none
`Ma`2`TWE=`one `=`
`M`1`TQ==`two `=`

The rule is simple. One equals sign means the last group held two bytes. Two equals signs mean it held one. You will never see three, because a group of three bytes needs no padding at all.

This is why base64 output length is always a multiple of four, and why SGVsbG8sIFdvcmxkIQ== ends the way it does: "Hello, World!" is 13 bytes, which is four groups of three with one byte left over.

Some systems strip the padding, on the grounds that a decoder can work out the original length from the number of characters. That is true, but not every decoder implements it. If you are getting an "invalid length" error on a base64 string, missing padding is the first thing to check.

base64 and base64url are not the same

Two characters in the standard alphabet cause trouble on the web: + and /.

In a URL query string, + conventionally means a space. And / is a path separator. A base64 string containing either will be mangled by anything that parses the URL, silently and without an error.

RFC 4648 defines a variant that fixes this. Everything is identical except two substitutions:

Standard base64base64url
`+``-`
`/``_`
padding keptpadding usually dropped

The difference is easy to see with data that produces both problem characters. Three specific bytes that encode to +/++ in standard base64 encode to -_-- in base64url. Same data, same 24 bits, different characters on the wire.

This matters because JSON Web Tokens use base64url, not base64. If you paste a JWT segment into a standard base64 decoder it may fail or return garbage, and the reason is almost always one of those two characters. Our guide on how to decode and debug a JWT covers where this bites in practice.

Where base64 belongs, and where it does not

Good uses:

Email attachments. MIME has used base64 since the early 1990s, and it remains the reason you can send a photograph through a protocol designed for plain text.

Data URIs. Embedding a small icon directly in CSS as data:image/png;base64,... removes an HTTP request. Worth it for small assets, not for large ones, because the 33% size penalty applies and the data cannot be cached separately.

JWTs and API tokens. The header and payload segments are base64url encoded so the token can travel in a URL or an HTTP header without escaping.

Binary in JSON. JSON has no binary type, so a file being sent inside a JSON body has to be encoded as a string somehow, and base64 is the convention.

Poor uses:

Storing images in a database. The 33% overhead applies to every row, indexes get larger, and you lose the ability to serve the file directly. Store a path and keep the file on disk or in object storage.

Anything you want kept private. This is the one that matters, and it deserves its own section.

Base64 is not encryption

This is the most common and most consequential misunderstanding about base64.

Encryption requires a key. Without the key, the original data cannot be recovered. Base64 has no key. The algorithm is public, the alphabet is fixed, and reversing it is a mechanical lookup that any decoder performs in microseconds.

A base64 string is not obscured. It is simply written in a different alphabet, in the same way that Morse code is not a secret language.

Every so often a credentials leak turns out to be a password that someone base64 encoded and considered handled. It was never handled. Anyone who obtains the string obtains the password immediately, with no effort and no tools beyond a browser console.

The related trap is HTTP Basic authentication. It transmits credentials as base64, which looks reassuringly opaque and is not. Basic auth is only safe over TLS, because TLS is doing all the actual protecting. The base64 is there to make the credentials safe to transmit as text, not safe from being read.

If you need data kept private, use encryption. If you need to detect tampering, use a signature or an HMAC. Base64 does neither and was never intended to.

How to decode base64 in practice

You rarely need to implement base64 yourself. Every mainstream environment has it built in, and knowing the one-liner for whichever you are in saves a trip to a website.

Command line, macOS and Linux

echo -n "Man" | base64 # TWFu echo "TWFu" | base64 --decode # Man

The -n on the encode side matters. Without it, echo appends a newline, that newline becomes part of the input, and you get TWFuCg== instead of TWFu. This is a common source of confusion when a manually generated token does not match one produced by an application.

JavaScript, browser and Node

btoa("Man") // "TWFu" atob("TWFu") // "Man"

These two only handle Latin-1 characters, so anything outside that range throws an error. For arbitrary text, encode to UTF-8 bytes first with TextEncoder. In Node, Buffer.from(str).toString("base64") handles this correctly without the extra step.

Python

import base64 base64.b64encode(b"Man") # b'TWFu' base64.b64decode("TWFu") # b'Man' base64.urlsafe_b64encode(data) # the base64url variant

Python operates on bytes rather than strings, so .encode() your text going in and .decode() the result coming out. The urlsafe_ variants handle the - and _ substitution automatically.

PHP

base64_encode("Man"); // TWFu base64_decode("TWFu"); // Man

Java

Base64.getEncoder().encodeToString("Man".getBytes()); new String(Base64.getDecoder().decode("TWFu")); Base64.getUrlEncoder().withoutPadding(); // base64url, no padding

A caution about online decoders. Pasting a value into a website sends it to that website's server. That is fine for debugging a public API response and a genuine mistake for anything containing credentials, personal data, or a production token. Use a local command or a tool that runs entirely in your browser. If you cannot tell which a given site is, assume the worst.

The bottom line

Base64 solves a transport problem: getting arbitrary bytes through channels that only handle text. It does that job reliably, at a predictable 33% cost in size, using an alphabet every system agrees on.

Remember three things. The equals signs are padding that tells the decoder how many real bytes the last group held. The URL-safe variant swaps two characters and is what JWTs use. And base64 offers no security at all, so nothing sensitive should ever rely on it for protection.

Our Base64 Encoder handles both directions in under 30 seconds. Try it free at globalutilityhub.com/dev-tools/base64-encoder/

Written by Sandesh Dhulekar

Sandesh Dhulekar is the founder of GlobalUtilityHub. He designs and codes all tools on the site himself, tracing every calculation to published formulas and public datasets.

Last updated 20 July 2026
Ready to try it yourself?

Use our free Base64 Encoder to apply what you have learned.

Open Base64 Encoder

Frequently Asked Questions

No. Encryption requires a key, and without that key the original data cannot be recovered. Base64 uses a fixed public alphabet and reverses mechanically, so anyone can decode it instantly. It offers no confidentiality whatsoever. Never use it to protect passwords, tokens, or personal data.
Those are padding. Base64 processes three bytes at a time, and when the final group has fewer than three, it pads the output to a multiple of four characters. One equals sign means the last group held two bytes, two equals signs mean it held one. You will never see three equals signs.
Base64 stores six bits of data in each eight-bit character, so output is about 33% larger than input. Every three bytes become four characters. A 900 byte file produces 1,200 base64 characters. This overhead is inherent to the format and is the cost of restricting output to safe printable characters.
Standard base64 uses + and / as its final two characters. Both cause problems in URLs, where + can mean a space and / is a path separator. The URL-safe variant defined in RFC 4648 replaces them with - and _ and usually drops the padding. JSON Web Tokens use base64url.
Almost always because JWTs use base64url rather than standard base64. A standard decoder encountering - or _ may error or return corrupted output. JWT segments also typically have their padding stripped, which some decoders reject as an invalid length. Use a decoder that handles base64url.
You can, but it is usually a poor choice. The 33% size increase applies to every row, backups and indexes grow accordingly, and you lose the ability to serve the file directly or cache it separately. Storing a file path or object storage key and keeping the binary outside the database is generally better.
No, and the difference is direction. Base64 is reversible by design: encode and decode return you to exactly where you started. A hash is one-way, producing a fixed-length fingerprint that cannot be reversed to recover the input. They solve completely different problems and are not interchangeable.
Standard base64 uses A to Z, a to z, 0 to 9, plus + and /, with = reserved for padding. That is 64 data characters and one padding character. The URL-safe variant substitutes - for + and _ for /. Any other character in a supposed base64 string means it is either a different encoding or has been corrupted.