Base64 Encoding in JavaScript: Complete Guide
โ Back to Blog
Base64 Encoding in JavaScript: Complete Guide
ยท 5 min read
Browser Built-in Methods: btoa and atob
Modern browsers provide two global functions for Base64 operations: btoa() (binary to ASCII, i.e., encoding) and atob() (ASCII to binary, i.e., decoding). These functions are convenient to use and require no external libraries.
// ็ผ็ / Encoding
const encoded = btoa('Hello, World!');
console.log(encoded); // "SGVsbG8sIFdvcmxkIQ=="
// ่งฃ็ / Decoding
const decoded = atob('SGVsbG8sIFdvcmxkIQ==');
console.log(decoded); // "Hello, World!"
Note that btoa() only accepts Latin-1 (ISO-8859-1) characters, meaning each character's Unicode code point must not exceed 255. If the input contains Chinese, emoji, or other multibyte Unicode characters, btoa() will throw an InvalidCharacterError exception. This is the most common pitfall for beginners.
Handling Unicode Strings
To Base64 encode strings containing Unicode characters, you need to first convert the string to a UTF-8 byte sequence, then perform Base64 encoding. Modern browsers can use TextEncoder for this step:
// ๅฏน Unicode ๅญ็ฌฆไธฒ่ฟ่ก Base64 ็ผ็
// Base64 encode a Unicode string
function encodeUnicode(str) {
const bytes = new TextEncoder().encode(str);
const binary = Array.from(bytes).map(b => String.fromCharCode(b)).join('');
return btoa(binary);
}
// ่งฃ็ Base64 ไธบ Unicode ๅญ็ฌฆไธฒ
// Decode Base64 to Unicode string
function decodeUnicode(base64) {
const binary = atob(base64);
const bytes = Uint8Array.from(binary, c => c.charCodeAt(0));
return new TextDecoder().decode(bytes);
}
console.log(encodeUnicode('ไฝ ๅฅฝ๏ผไธ็๏ผ'));
// "5L2g5aW977yM5LiW55WM77yB"
console.log(decodeUnicode('5L2g5aW977yM5LiW55WM77yB'));
// "ไฝ ๅฅฝ๏ผไธ็๏ผ"
Base64 Encoding in Node.js
Node.js doesn't have btoa and atob (although newer versions have added them), and traditionally uses the Buffer class to handle Base64. Buffer natively supports UTF-8 and doesn't have the Unicode limitations of btoa in browsers.
// Node.js Buffer ๆนๅผ
// Node.js Buffer approach
// ็ผ็ / Encode
const text = 'ไฝ ๅฅฝ๏ผWorld๏ผ';
const encoded = Buffer.from(text, 'utf8').toString('base64');
console.log(encoded);
// ่งฃ็ / Decode
const decoded = Buffer.from(encoded, 'base64').toString('utf8');
console.log(decoded); // "ไฝ ๅฅฝ๏ผWorld๏ผ"
// ็ผ็ ๆไปถไธบ Base64
// Encode a file to Base64
const fs = require('fs');
const fileBuffer = fs.readFileSync('./image.png');
const base64Image = fileBuffer.toString('base64');
console.log(`data:image/png;base64,${base64Image}`);
Node.js v16+ provides btoa and atob in the global scope for browser API compatibility. But for server-side applications, Buffer is still recommended as it's more flexible and can directly handle binary data streams.
Base64URL Encoding and Decoding
When handling JWT tokens or placing Base64 in URLs, you need to use the Base64URL variant. Base64URL replaces + with -, / with _, and removes padding =. Here's an implementation in the browser:
// Base64URL ็ผ็
// Base64URL encoding
function toBase64URL(str) {
return btoa(str)
.replace(/\+/g, '-')
.replace(/\//g, '_')
.replace(/=+$/, '');
}
// Base64URL ่งฃ็
// Base64URL decoding
function fromBase64URL(base64url) {
const base64 = base64url
.replace(/-/g, '+')
.replace(/_/g, '/');
// ่กฅๅ
จๅกซๅ
/ Add padding
const padded = base64 + '=='.slice(0, (4 - base64.length % 4) % 4);
return atob(padded);
}
Using Base64 with the Fetch API
When using the Fetch API to send HTTP requests, you sometimes need to send Base64 data as the request body, or decode Base64 data in the response. The following example shows how to handle both scenarios:
// ๅ้ๅ
ๅซ Base64 ๅพ็็ POST ่ฏทๆฑ
// Send POST request with Base64 image
async function uploadImageAsBase64(file) {
const reader = new FileReader();
const base64 = await new Promise((resolve) => {
reader.onload = (e) => resolve(e.target.result.split(',')[1]);
reader.readAsDataURL(file);
});
const response = await fetch('/api/upload', {
method: 'POST',
headers: { 'Content-Type': 'application/json' },
body: JSON.stringify({ image: base64 })
});
return response.json();
}
Converting File Objects to Base64
In browsers, a file selected by the user through an input[type=file] is a File object (a subclass of Blob). The FileReader API can convert it to a Base64 string. This is a common pattern for frontend file upload handling and preview:
// ๅฐ File ่ฝฌๆขไธบ Base64
// Convert File to Base64
function fileToBase64(file) {
return new Promise((resolve, reject) => {
const reader = new FileReader();
reader.onload = () => resolve(reader.result); // data URI
reader.onerror = reject;
reader.readAsDataURL(file);
});
}
// ไฝฟ็จ็คบไพ / Usage
const input = document.querySelector('input[type=file]');
input.addEventListener('change', async (e) => {
const file = e.target.files[0];
const dataURI = await fileToBase64(file);
document.querySelector('img').src = dataURI;
});
Common Errors and Debugging
The most common error is InvalidCharacterError: The string to be encoded contains characters outside of the Latin1 range, caused by calling btoa() directly on a string containing multibyte characters like Chinese. The solution is to use the TextEncoder method or encodeURIComponent trick introduced earlier.
Another common issue is getting garbled text after decoding, usually because the original data was encoded with a charset other than UTF-8. In such cases, use TextDecoder with the correct charset name, such as new TextDecoder('gbk') to decode Simplified Chinese GBK-encoded data.
Try the online tool now โ no installation, completely free.
Open Tool โ
Try the free tool now
Use Free Tool โ