Why Base64 Decoding Garbles Japanese Text & How to Fix It
Base64 Encoding JavaScript Troubleshooting
Conclusion
Using only atob() will not decode Japanese correctly. Reinterpreting it as UTF-8 using TextDecoder is the correct approach.
The Problem: Garbled Text with atob()
const base64Str = "44GT44KT44Gr44Gh44Gv"; // "こんにちは" (Hello)
const decoded = window.atob(base64Str);
console.log(decoded);
// -> "ã"ã‚"ã«ã¡ã¯" (Garbled)
The Cause
atob() is designed assuming 1 character = 1 byte (ASCII/Latin-1).
Since Japanese uses UTF-8 (1 character = up to 3 bytes), the byte sequence gets interpreted separately, resulting in garbled text.
| atob() Assumption | Japanese (UTF-8) |
|---|---|
| 1 character = 1 byte | 1 character = 3 bytes (Multi-byte) |
| Interprets raw bytes directly as characters | Requires combining multiple bytes to form a single character |
Code Solution
function safeBase64Decode(base64) {
const binStr = window.atob(base64);
const bytes = new Uint8Array(binStr.length);
for (let i = 0; i < binStr.length; i++) {
bytes[i] = binStr.charCodeAt(i);
}
return new TextDecoder('utf-8').decode(bytes);
}
console.log(safeBase64Decode("44GT44KT44Gr44Gh44Gv"));
// -> "こんにちは"
In Node.js
const decoded = Buffer.from("44GT44KT44Gr44Gh44Gv", 'base64').toString('utf-8');
console.log(decoded); // "こんにちは"
Note
For Base64URL formats (like JWT, where + -> -, / -> _, and padding is omitted), you need a preprocessing step to revert to standard Base64 before passing it to atob().
Quick Tool Check
If you want to quickly check Base64 contents before writing code, a UTF-8 compatible decoding tool is helpful.
🧪 Base64 Encode/Decode Tool
Fully supports Japanese text. A safe tool that runs entirely within the browser.
試す