
You copy an API response and it returns a long string of letters and numbers ending in one or two equals signs. You check a JWT token and the header and payload sections look like garbled text. You look at a CSS file and find a url("data:image/png;base64,...") several hundred characters long. All of these are base64. Understanding what it does and why it exists clears up a large part of what looks mysterious in modern web development.
The base64 encoder and decoder converts any text or data to base64 and back in one step, with no setup needed. This guide explains how the encoding works, what the output means, and when to use it versus leaving data in its original format.
Why Does Base64 Exist?
Base64 was created to solve a specific problem: binary data does not travel safely through systems designed for text.
Early email systems, network protocols, and data formats were built around 7-bit ASCII text. They were not designed to handle arbitrary binary values. When binary data (images, audio files, executable files) needed to travel through these text-only channels, the bytes that represented binary values would be interpreted as control characters, line endings, or other protocol signals. The data would be corrupted in transit.
Base64 solves this by representing any binary value using only 64 printable ASCII characters that have no special meaning in text protocols. The name "base64" refers directly to this alphabet of 64 characters. Any binary data encoded to base64 can pass safely through systems that only handle text, because every character in the output is a standard printable character.
The 64 characters used are: uppercase A through Z (26 characters), lowercase a through z (26 characters), digits 0 through 9 (10 characters), plus sign (+), and forward slash (/). That is exactly 64, which is 2 to the power of 6. Each base64 character encodes exactly 6 bits of information.
How Base64 Encoding Works
The encoding process operates on 3-byte groups. Three bytes contain 24 bits. Split 24 bits into four groups of 6 bits each. Each 6-bit value maps to one of the 64 characters in the base64 alphabet.
An example with the three ASCII characters "Man":
- M = ASCII 77 = binary 01001101
- a = ASCII 97 = binary 01100001
- n = ASCII 110 = binary 01101110
Concatenated: 010011010110000101101110 (24 bits)
Split into four 6-bit groups: 010011 | 010110 | 000101 | 101110
Converted: 19 = T, 22 = W, 5 = F, 46 = u
Result: TWFu
This process repeats for every 3-byte group in the input. The output is always 4 characters per 3 input bytes, which produces the characteristic 4/3 size ratio.
What the Equals Sign Padding Means
Not all inputs divide evenly into groups of 3 bytes. When the last group has fewer than 3 bytes, padding equals signs are added to keep the output in valid 4-character groups.
One remaining byte (8 bits): Two 6-bit groups encode it (12 bits, with 4 unused bits padded to zero). Two equals signs are appended. The 4-character group contains 2 real characters and 2 padding characters.
Two remaining bytes (16 bits): Three 6-bit groups encode them (18 bits, with 2 unused bits padded to zero). One equals sign is appended. The 4-character group contains 3 real characters and 1 padding character.
Three bytes exactly: No padding needed. The 4-character group is complete.
Padding exists so decoders know how many bytes the final group represents. A decoder seeing == at the end knows the last group encoded 1 byte. A decoder seeing = at the end knows the last group encoded 2 bytes. Without this information, decoding the final group is ambiguous.
Some systems strip the trailing padding because the length of the base64 string can be used to infer it. The base64 encoder and decoder handles padded and unpadded input in both directions.
Standard Base64 Versus Base64url
Standard base64 uses + (plus) and / (slash) as its last two characters. Both of these have special meaning in URL contexts: plus is interpreted as a space in query strings, and slash is a path separator. Including them in a URL without encoding causes parsing errors.
Base64url is a variant that substitutes - (hyphen) for + and _ (underscore) for /. The result is a string safe to use directly in URLs and filenames without percent-encoding.
JSON Web Tokens (JWTs) use base64url. A JWT consists of three base64url-encoded sections separated by dots: the header, the payload, and the signature. If you decode the header section of any JWT, you get a JSON object with the token type and signing algorithm. If you decode the payload, you get the claims (user ID, expiration time, permissions, and any other data the server encoded). The signature section validates that the header and payload have not been tampered with and cannot be decoded to readable content without the secret key.
This is the reason why base64-encoded data is not encrypted: the header and payload of a JWT are fully readable to anyone who decodes them. Only the signature provides security. Never put sensitive data in a JWT payload unless the token itself is also encrypted (JWE, not JWS). UUIDs are commonly used as user ID and session ID values inside JWT payloads — the what is a UUID guide explains the UUID format and how versions 1 through 5 differ.

Common Uses in Web Development
Data URIs for images: CSS and HTML allow embedding image data directly in the source using a data URI: url("data:image/png;base64,iVBORw0KGo..."). This eliminates one HTTP request per image. The tradeoff is that base64-encoded images are 33% larger than the original file and cannot be cached separately from the document that contains them. Data URIs are practical for very small images like icons (under 1–2 KB) where the request overhead exceeds the size penalty. For larger images, a standard URL reference is more efficient.
Email attachments: The MIME standard (Multipurpose Internet Mail Extensions) uses base64 to encode binary attachments so they can pass through email servers built for ASCII text. When you attach a PDF to an email, your email client encodes the PDF as base64 before including it in the message body. The recipient's email client decodes it on arrival. This process is transparent to the user but is why email attachments increase the message size by roughly a third compared to the raw file.
JSON and configuration files: JSON is a text format. Storing binary data (encryption keys, certificates, file content) in a JSON field requires encoding it as a string. Base64 is the standard choice because it produces a clean string with no characters that need escaping in JSON.
API responses: REST APIs frequently return binary content (images, audio, documents) as base64 strings in JSON responses when the caller expects a JSON body rather than a binary stream. The client decodes the base64 to reconstruct the original file.
When Should You Avoid Base64?
Base64 is the right tool for a specific problem: binary data in a text channel. When the channel already handles binary, base64 adds overhead without benefit.
Serving images from a web server to a browser: browsers are fully capable of receiving binary image files over HTTP. Encoding an image to base64 and serving it as a data URI instead of a file URL increases the payload by 33% and removes the ability to cache the image independently. Use base64 in CSS only for very small images.
Storing passwords: base64 is not a security measure. A base64-encoded password is trivially decoded by anyone. Passwords must be hashed (ideally with bcrypt, scrypt, or Argon2) before storage. If you see base64 used for password storage, it is a security error, not a feature. The how to create a strong password guide covers the distinction between encoding and hashing and why only one of them is suitable for protecting credentials.
Sending large binary files: base64 adds 33% overhead. A 10 MB file becomes 13.7 MB when base64 encoded. For transferring large files, use multipart form data or chunked binary transfer instead of base64 encoding in a JSON body.
The difference between encoding and encryption is worth stating plainly: base64 is reversible by anyone with a decoder. For protection of data in transit, use HTTPS (TLS). For protection of data at rest, use AES or similar symmetric encryption. The hash generator is the right tool when you need a one-way fingerprint of data rather than a reversible encoding.
How to Encode and Decode Base64
In the browser: Open the base64 encoder and decoder, paste any text or data into the input field, and click Encode. The base64 output appears immediately. To decode, paste a base64 string and click Decode.
On Linux and Mac command line:
echo -n "hello" | base64
Output: aGVsbG8=
To decode:
echo "aGVsbG8=" | base64 --decode
Output: hello
On Windows PowerShell:
[Convert]::ToBase64String([Text.Encoding]::UTF8.GetBytes("hello"))
Output: aGVsbG8=
To decode:
[Text.Encoding]::UTF8.GetString([Convert]::FromBase64String("aGVsbG8="))
Output: hello
In JavaScript:
btoa("hello") // Encode: "aGVsbG8="
atob("aGVsbG8=") // Decode: "hello"
Note: the browser's btoa and atob functions handle only Latin-1 characters. For Unicode strings, encode the string as UTF-8 bytes first before passing to btoa.
In Python:
import base64
base64.b64encode(b"hello") # b'aGVsbG8='
base64.b64decode("aGVsbG8=") # b'hello'
Checking Whether a String Is Base64
Base64 strings have identifiable characteristics. A valid base64 string contains only A-Z, a-z, 0-9, +, and /. It ends with 0, 1, or 2 equals signs. Its length is always a multiple of 4 characters (including padding). A base64url string uses - and _ instead of + and /.
These properties are not sufficient to confirm that something IS base64, only that it COULD be. Many random strings meet these criteria without being valid base64 encodings. To confirm, decode the string and check whether the output makes sense for the expected data type.
The developer tools section has the base64 encoder and decoder alongside the hash generator, URL encoder and decoder, and password generator, all in one place for common development tasks.

