Base64 Encoder
Turn text or small files into Base64 for data URIs, APIs, or safe transport—preview and copy in one click.
File Upload
About Base64 Encoding
What is Base64?
Base64 is a group of binary-to-text encoding schemes that represent binary data in an ASCII string format.
Common Uses
- • Embedding images in HTML/CSS
- • Storing binary data in JSON
- • Email attachments
- • API data transmission
Turn bytes into an ASCII-safe string. The mapping itself is mechanical — three bytes become four characters — but the decisions around it are not: which of the two alphabets, whether to pad, whether to wrap, and whether the payload belongs inline at all. This page covers the encoding-side choices.
Three bytes in, four characters out
Base64 reads the input as a bit stream and regroups it: 24 bits at a time become four 6-bit indices into a 64-character alphabet. The ordering is A–Z for 0–25, a–z for 26–51, 0–9 for 52–61, then + at 62 and / at 63.
Output length is exactly 4 × ceil(n / 3) characters for n input bytes, so growth is 33.3% before any line breaks are added. A 1 MiB file — 1,048,576 bytes — encodes to 1,398,104 characters. That figure is worth carrying around, because it is what decides whether a payload still fits inside a database column, a message-queue limit, or a request-body cap.
Padding exists because input lengths are rarely a multiple of three. One leftover byte produces two characters plus ==; two leftover bytes produce three characters plus =. A padded string therefore always has a length divisible by four, which gives you a free sanity check: if the length modulo four is one, the string is truncated rather than merely unpadded. Base64 is transport encoding and nothing else — it does not compress, and since the alphabet is public it provides no confidentiality whatsoever.
btoa encodes Latin-1, which is probably not what you meant
The browser's btoa() takes a string and treats each code unit as a single byte, so it can only represent U+0000 through U+00FF. Above that it throws InvalidCharacterError, which means btoa("日本") and anything containing an emoji fail loudly and get fixed.
The dangerous range is the one just below. é is U+00E9, comfortably inside Latin-1, so btoa("café") does not throw. It returns Y2Fm6Q==, four bytes in which the accent is the single byte 0xE9. The UTF-8 encoding of that same string is five bytes and produces Y2Fmw6k=. Two different outputs, both entirely plausible-looking, and only one of them is what the receiving system expects. Western European text is precisely the case where this fails silently.
Encode to bytes explicitly before encoding to base64. In a browser that means new TextEncoder().encode(str) and then base64-encoding the resulting Uint8Array; in Node it means Buffer.from(str, "utf8").toString("base64"), where the character encoding is named in the call and cannot be guessed wrong. The underlying rule: base64 has no opinion about text, so the encoding decision belongs one layer earlier and needs recording somewhere.
Choosing between the two RFC 4648 alphabets
RFC 4648 specifies two alphabets. Section 4 is the standard one ending in + and /. Section 5 is the URL and filename safe variant, which substitutes - and _ into those two positions and changes nothing else about the encoding.
Both replaced characters are actively hostile inside a URL. A + in a query string decodes to a space under application/x-www-form-urlencoded rules, so standard base64 pasted into a parameter comes back with spaces where data used to be. A / terminates a path segment. The = padding is a third problem, which is why formats that carry base64 in URLs drop it entirely. Concretely, the bytes fb ff fe encode to +//+ under the standard alphabet and -__- under the URL-safe one.
Pick by destination rather than by habit. Anything headed for a URL path, a query parameter, a filename, or an HTTP header wants section 5; anything headed for a JSON string value, a MIME body, or a PEM file wants section 4. Write down which one you chose, because the two are indistinguishable for any input that happens not to hit index 62 or 63 — so the bug surfaces in production, on the first payload that does.
Line wrapping is a MIME rule, not a base64 rule
Nothing in the base64 alphabet includes a newline, yet two long-standing formats mandate one anyway. RFC 2045 requires MIME-encoded base64 to be broken into lines of no more than 76 characters. RFC 7468, which specifies the PEM textual encoding used for certificates and keys, requires generators to wrap at 64.
This is why identical bytes produce visibly different output from different tools, and why a wrapped string handed to a strict decoder is rejected. It is also why PEM keys are so awkward to move around: pasting one into a JSON configuration file or a shell environment variable means either escaping every newline as \n or stripping them and letting the consumer re-wrap. A meaningful share of "invalid key" errors in deployment pipelines are line breaks mangled in transit rather than anything wrong with the key material.
When producing base64 for a JSON payload, an HTTP header, or a database column, emit a single unwrapped line. Those contexts impose no line-length rule and wrapping only creates work for whoever decodes it. Add wrapping only where the target format actually demands it.
When a data URI costs more than the request it saves
Inlining an asset as a data: URI trades a network request for page weight, and that trade has aged badly. The asset arrives 33% larger, it cannot be cached separately from the document containing it, so any change to either invalidates both, and it must be parsed as part of the HTML or CSS on the critical path instead of being fetched in parallel.
Compression does not rescue it. PNG, JPEG, WOFF2, and gzip payloads are already compressed, and base64-encoding compressed bytes yields something gzip and Brotli can barely improve on, so the 33% is real on the wire rather than only on disk. HTTP/2 and HTTP/3 multiplexing also removed the original justification, since request count is no longer the bottleneck it was under HTTP/1.1 with six connections per origin.
Two cases still hold up. Very small images, where per-request overhead genuinely dominates a few hundred bytes of payload. And SVG, which deserves a specific note: because SVG is text, percent-encoding it into a data URI escapes only a handful of characters and usually yields a smaller string than base64's unconditional 33% markup. One closing reminder about what base64 is not — HTTP Basic authentication (RFC 7617) base64-encodes user:password purely so it survives a header, and that string is reversible by anybody who sees it.
Related tools
Try these tools that work well with this one
Base64 Decoder
Convert Base64 back to original text and files
URL Encoder
Free online URL encoder tool for encoding special characters
API Tester
Send HTTP requests and view responses
CSV to JSON Converter
Convert CSV data to JSON
CSV to XML Converter
Convert CSV text to XML
Hash Generator
Generate MD5, SHA1, SHA256, SHA512 hashes
Related guides
Tutorials and guides to get more from this tool
Base64 Encoding: What It Is and How It Works
Master Base64 encoding in 5 minutes! Learn when to use it, how it works, and avoid common mistakes. Essential for API developers in 2025.
Regex Cheat Sheet: Patterns That Hold Up in Production
A practical regex reference with tested patterns for IDs, dates, URLs and logs, plus the mistakes that cause bugs and catastrophic backtracking.
JavaScript .then() and .catch(): Promise Error Handling Explained
How .then().catch() chains work in JavaScript: return values, error propagation, finally, common mistakes, and when to use async/await instead.
ThenCatch is a free developer toolkit. Learn more about us.