Base64 Encoding Explained: Unicode, URL-Safe Variants, and Size Increase
What Is Base64 Encoding
Base64 is a way to turn binary data into plain text. It maps any sequence of bytes onto a set of 64 printable ASCII characters, which means the output can travel safely through systems that only handle text. The format was born in the MIME email standard, where binary attachments had to survive mail servers that stripped non-text bytes. To encode or decode data right now, try our Base64 encoder/decoder — it handles Unicode and URL-safe variants.
The 64-character alphabet is fixed:
| Value | Characters | Count |
|---|---|---|
| 0-25 | A-Z | 26 |
| 26-51 | a-z | 26 |
| 52-61 | 0-9 | 10 |
| 62 | + | 1 |
| 63 | / | 1 |
A 65th character, =, shows up only at the end as padding.
How the Encoding Works
Base64 reads input bytes in groups of three (24 bits total) and splits them into four 6-bit chunks. Each chunk maps to one character in the alphabet, so three bytes become four characters.
Take the string Man:
Input bytes: M(77) a(97) n(110)
Binary: 01001101 01100001 01101110
6-bit groups: 010011 010110 000101 101110
Decimal: 19 22 5 46
Alphabet: T W F u
The result is TWFu.
When the input length is not a multiple of three, padding kicks in:
- One leftover byte produces two characters plus
== - Two leftover bytes produce three characters plus
=
That is why Base64 strings often end with one or two equals signs. It's normal, not a bug.
Handling Unicode, Chinese, and Emoji
Base64 operates on bytes, not characters. Chinese characters, emoji, and other non-ASCII symbols occupy multiple bytes under UTF-8. A Chinese character typically takes three bytes, and an emoji can take four.
The correct approach is to encode the string into a UTF-8 byte sequence first, then run Base64 over those bytes. Tools that skip this step and treat each character as a single byte end up mangling Chinese text or turning it into \uXXXX escape sequences.
On a UTF-8 terminal, the round trip works cleanly:
echo -n "你好" | base64
# 5ZG95ZG9
echo "5ZG95ZG9" | base64 -d
# 你好
ToolVault's Base64 tool follows the UTF-8 byte path, so Chinese, Japanese, and emoji all survive a full encode-decode round trip without corruption.
URL-Safe Base64
Standard Base64 includes + and /, which collide with URL syntax and file naming rules. The URL-safe variant (also called Base64url) swaps two characters and drops padding:
-replaces+_replaces/- The trailing
=padding is removed
| Standard | URL-Safe |
|---|---|
a+b/c= | a-b_c |
You will find this variant inside JWT tokens, in Data URLs, and in short-link systems. Anywhere your encoded string lands inside a URL, switch to the URL-safe alphabet to avoid parsing headaches.
A common edge case: HTTP headers or JSON payloads where = padding is stripped by proxies, or + is mistaken for a space. When "works locally, fails in production" appears, check whether both ends use the URL-safe variant and whether padding survives the transport.
JWT segments and PEM are not “just Base64”
Three dialects collide in everyday debugging:
| You pasted… | Dialect | Prefer |
|---|---|---|
aaaa.bbbb.cccc (two dots) | Base64URL × 3 | JWT decoder |
-----BEGIN CERTIFICATE----- | Standard Base64 + 64-col wraps | Certificate decoder |
Alphabet with - / _, no dots | Base64URL blob | URL-safe mode on this Base64 tool |
JWT header/payload decode to JSON; the signature is opaque bytes. PEM bodies use the standard alphabet and expect line breaks — “cleaning” newlines often breaks strict parsers. For alphabet tables, padding math, and a decision tree, see Base64 vs Base64URL: JWT and PEM. After claims are visible, clock issues belong in JWT exp/nbf clock skew; chain trust belongs in incomplete certificate chain.
Big integers and precision traps
Base64-decoded bytes sometimes contain 19-digit snowflake IDs. JSON.parse applies IEEE754 double precision, silently rounding the tail. That is not a Base64 bug — it is "lossless at the encoding layer, lossy at the decode layer". When handling large integer IDs:
- Immediately after decode, use
parseLosslessor aJSON.parsereviver to turn big numbers into strings; - Or have the backend serialize IDs as strings so the frontend never relies on special parsing.
This site's JSON formatter ships with lossless parsing; the JWT decoder uses the same path for large-integer claims.
Implementer's note
The on-site Base64 tool converts between characters and UTF-8 bytes via TextEncoder/TextDecoder, then Base64-encodes the bytes — that is why Chinese and emoji round-trip correctly. For file drag-and-drop, the ArrayBuffer is converted to bytes first, then encoded in chunks to avoid one giant string memory spike. The URL-safe toggle only swaps the alphabet and handles padding; it does not change encoding semantics.
Using the Online Tool
The Base64 encoder and decoder in ToolVault keeps things simple:
- Open the tool page
- Paste your text into the input box
- Pick Encode or Decode
- Read the result from the output area, and copy it with one click
Everything runs locally in your browser. Nothing leaves your device, which makes the tool safe for strings that carry tokens or credentials.
The size math, once and for all
Base64 inflation is 4/3 exactly — but the practical numbers are what people need: 1 MB becomes 1.37 MB with padding; a 6-character string becomes 8 characters (padding included); JSON API payloads embedding base64 fields grow a third at the transport layer even when gzip claws some back (base64's low entropy compresses poorly — expect gzip to recover only ~10-15% of the inflation). The boundary decisions that follow: URL length limits (~2KB safe) cap how much base64 belongs in a query string; localStorage quotas (~5MB) fill a third faster with encoded blobs; and any base64 field in a database index is a design smell — index the identifier, not the payload.
FAQ
Is Base64 encryption?
No. Base64 is encoding, not encryption. Anyone can reverse it. It solves a transport problem, not a secrecy one. For confidentiality, reach for AES or another real cipher.
Why does Base64 size increase by ~33%?
Base64 packs every 3 input bytes into 4 printable characters (6 bits each). Overhead = (4 − 3) / 3 ≈ 33.3%. Short strings can grow more because of padding (=). Formula: encoded length ≈ 4 × ceil(n / 3). For worked examples (Hi, Hello, 1 MB file), see Why Base64 Makes Files 33% Larger. Measure your own payload with the Base64 encoder/decoder.
Why does my Chinese text turn into garbage after encoding?
The tool you used probably skipped the UTF-8 byte conversion step. Switch to a Unicode-aware encoder and the round trip will work. A quick test: encode "你好", decode it back, and check whether the original characters return intact.
Can I store images as Base64?
You can. Embedding image bytes as a Base64 Data URL inside HTML or CSS saves an HTTP request. Keep in mind the payload grows by a third, so this trick works best for small icons and sprites, not large photos.
Why did a JWT segment fail in a normal Base64 decoder?
JWT uses Base64URL: -/_ instead of +/, and padding is usually omitted. Toggle URL-safe mode, or open the JWT decoder. Details: Base64 vs Base64URL.
Related reading
- Base64 vs Base64URL: JWT segments and PEM
- Base64 Chinese garbled / mojibake
- Base32/Base58 encoder: alphabets and checksums
- JWT explained: structure and security
- Certificate decoder guide
Article by ToolVault. Visit our homepage for more developer tools.
Related Tools
Related Articles
PDF to JPG: How to Pick the Right Resolution (DPI Guide + 3 Ways)
A complete guide to converting PDF pages to JPG: how DPI maps to sharpness, two-page and batch conversion, three approaches compared (in-browser local, command line, desktop software), plus a quality settings cheat sheet.
PDF Too Large for Email? How to Choose the Right Compression Quality (3 Local Levels)
How PDF compression works: lossy rasterization vs. lossless structure optimization, which of the three quality levels fits which use, and how to compare sizes before and after — entirely in your browser.
How to Split a PDF and Extract Pages: Range Syntax, Common Cases, and a Local Workflow
A complete guide to splitting PDFs by page range: the 1-3,5 range syntax, page-by-page extraction, and split-then-merge workflows — all in your browser, nothing uploaded.