Decodex

DECODEX · BASE64 · UTF-8

Base64 en JavaScript con Unicode: solucionar errores de btoa()

Codifica acentos, coreano y emojis con TextEncoder y decodifica con atob y TextDecoder. Código UTF-8 y ejemplos comprobados.

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)); // 안녕하세요 😀

Probar este ejemplo →

Base64 → UTF-8 · UTF-8 → Base64

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