How can you encode/decode a string to Base64 in JavaScript?
Master System Design with Codemia
Enhance your system design skills with over 120 practice problems, detailed solutions, and hands-on exercises.
Introduction
Base64 encoding in JavaScript is easy for simple text, but the correct approach depends on two things: whether the input is really text or raw bytes, and whether the code runs in a browser or in Node.js. Most mistakes happen when code assumes all JavaScript strings are safe input for btoa, which is not true for arbitrary Unicode.
Browser API: btoa and atob
In browser environments, the classic functions are:
This works for text that fits the Latin1-style expectations of btoa and atob.
The Unicode Problem
The biggest surprise is that btoa does not accept arbitrary Unicode text safely.
That usually throws because btoa expects a binary string, not a full UTF-16 JavaScript string with arbitrary characters.
For Unicode-safe handling in browsers, encode the text to bytes first with TextEncoder, then convert those bytes to Base64.
Unicode-Safe Browser Helpers
This is a much safer browser pattern than older escape or encodeURIComponent workarounds.
Node.js: Use Buffer
In Node.js, Buffer is the standard solution and handles UTF-8 naturally:
For server-side JavaScript, this is usually the simplest and most reliable approach.
URL-Safe Base64
Some systems use a URL-safe Base64 variant that replaces + and / and may omit padding. JavaScript does not switch to that form automatically, so if an API expects URL-safe output you need to transform it deliberately after encoding.
Base64 Is Encoding, Not Encryption
It is important to remember what Base64 is for. It does not secure data. It only converts bytes into a text-safe representation.
Examples of valid uses:
- embedding binary content in text formats
- basic transport through systems expecting text
- data URLs or serialized payloads
Examples of invalid expectations:
- hiding secrets
- protecting passwords
- treating Base64 as cryptography
Anyone can decode Base64 immediately if they have the string.
Working with JSON Payloads
A common pattern is encoding a JSON string before transport or storage:
This works in the browser only if the JSON string stays within the character constraints of btoa. For arbitrary Unicode content, use the UTF-8-safe helper shown earlier.
Binary Data Versus Text
Another common confusion is mixing text encoding and binary encoding. If you are dealing with files, image bytes, or arbitrary binary blobs, treat the data as bytes first rather than as a JavaScript text string.
For example, in Node:
That is different from Base64-encoding human-readable text.
Common Pitfalls
The biggest mistake is using btoa directly on Unicode text. It may work for simple English strings and then break the moment accented or non-Latin characters appear.
Another issue is forgetting whether the code is running in the browser or in Node.js. Buffer is the natural Node solution, while btoa and atob are browser-oriented APIs.
Another common issue is confusing standard Base64 and URL-safe Base64. Two strings can look almost identical and still be invalid for the target API if the alphabet or padding rule is different.
Finally, do not treat Base64 as a security measure. If the problem is confidentiality, you need encryption, not encoding.
Summary
- In browsers,
btoaandatobwork for simple Base64 tasks. - For Unicode-safe browser code, use
TextEncoderandTextDecoder. - In Node.js, prefer
Buffer.from(...).toString("base64")and the reverse operation. - Base64 is encoding, not encryption.
- Keep text encoding and binary-byte handling separate so the conversion stays correct.

