btoa() recibe una cadena binaria con unidades de código de un byte. No convierte texto a UTF-8 automáticamente. Coreano, hindi y muchos emojis pueden causar InvalidCharacterError. Usa bytes UTF-8 explícitos para conseguir una conversión fiable.
Codificar y decodificar Unicode
TextEncoder convierte el texto en bytes. El código de abajo procesa pequeños bloques antes de llamar a btoa, evitando un argumento por cada byte de un texto grande. Para recuperar el texto, atob produce bytes que TextDecoder interpreta como UTF-8. La opción fatal detecta bytes inválidos.
Verifica la conversión de ida y vuelta
안녕하세요 😀 produce 7JWI64WV7ZWY7IS47JqUIPCfmIA=. La decodificación debe recuperar exactamente el texto, el espacio y el emoji. El enlace del ejemplo abre el conversor con datos públicos predefinidos, sin incluir texto del usuario en la URL. Decodex convierte localmente texto UTF-8 de hasta 5 MB.
Identifica dónde ocurre el error
Un error de atob suele indicar Base64, relleno o prefijos incorrectos. Un error de TextDecoder puede indicar datos binarios o una codificación distinta, aunque el alfabeto Base64 sea válido. Node.js ofrece Buffer.from(text, "utf8").toString("base64"), pero su decodificación permisiva no sustituye la validación de entrada.
Probar este ejemplo
// Browser JavaScript: text → UTF-8 bytes → Base64.
function utf8ToBase64(text) {
const bytes = new TextEncoder().encode(text);
let binary = '';
for (let i = 0; i < bytes.length; i += 8192) {
binary += String.fromCharCode(...bytes.subarray(i, i + 8192));
}
return btoa(binary);
}
// Accept standard Base64 or Base64URL, with complete or omitted padding.
function base64ToUtf8(value) {
let normalized = value.replace(/\s/g, '').replace(/-/g, '+').replace(/_/g, '/');
if (!/^[A-Za-z0-9+/]*={0,2}$/.test(normalized) ||
normalized.length % 4 === 1 ||
(normalized.includes('=') && normalized.length % 4 !== 0)) {
throw new Error('Invalid Base64 characters, length or padding');
}
normalized += '='.repeat((4 - normalized.length % 4) % 4);
const binary = atob(normalized);
const bytes = Uint8Array.from(binary, character => character.charCodeAt(0));
return new TextDecoder('utf-8', { fatal: true }).decode(bytes);
}
const text = '안녕하세요 😀';
const encoded = utf8ToBase64(text);
console.log(encoded); // 7JWI64WV7ZWY7IS47JqUIPCfmIA=
console.log(base64ToUtf8(encoded)); // 안녕하세요 😀
Preguntas frecuentes
¿atob devuelve directamente texto legible?
No. Devuelve una cadena binaria. Convierte sus valores en Uint8Array y utiliza TextDecoder("utf-8"). Prefiere este enfoque a funciones antiguas como unescape().
Referencias
Más guías de Base64
Base64 y Base64URL: diferencias, relleno y ejemplos
Compara Base64 y Base64URL, los caracteres + / y - _, el relleno y la decodificación de texto UTF-8 con ejemplos comprobados.
Relleno Base64: qué significan = y ==
Entiende el relleno Base64 con f, fo y foo. Comprueba cadenas sin =, longitudes inválidas y errores de relleno parcial.
