Base64 es una forma de representar datos binarios (una imagen, un PDF, bytes arbitrarios) usando solo 64 caracteres de texto imprimible: las letras A-Z y a-z, los dígitos 0-9 y los símbolos + y /, con = como relleno. Sirve para transportar binarios por canales pensados para texto, como JSON, correo electrónico, URLs o atributos HTML. Aumenta el tamaño aproximadamente un 33 % y no es cifrado: cualquiera puede decodificarlo.
Este artículo explica cómo funciona, cuándo tiene sentido usarlo (y cuándo no) y cómo codificar y decodificar correctamente en JavaScript, Node.js y la terminal, incluido el caso de los caracteres no ASCII que hace fallar a btoa.
Cómo funciona
Base64 toma los datos de 3 en 3 bytes (24 bits) y los reparte en 4 grupos de 6 bits. Cada grupo de 6 bits (un valor de 0 a 63) se sustituye por un carácter de la tabla. Si la longitud no es múltiplo de 3, se añaden uno o dos = al final para completar el último bloque.
De ahí sale el coste: cada 3 bytes se convierten en 4 caracteres, así que el resultado ocupa 4/3 del original (un 33 % más), redondeado hacia arriba al múltiplo de 4. Por ejemplo, la cadena Año 2026 ñ ocupa 12 bytes en UTF-8 y su Base64, QcOxbyAyMDI2IMOx, tiene 16 caracteres.
La especificación completa es el RFC 4648, que define también la variante URL-safe: sustituye + por - y / por _ para que el resultado pueda ir en una URL o un nombre de archivo sin escapes. Los tokens JWT usan esta variante, normalmente sin relleno.
Cuándo usar Base64
- Incrustar un recurso pequeño en HTML, CSS o JSON: un icono SVG o PNG de unos pocos KB como data URL evita una petición HTTP.
- Enviar binarios en una API JSON cuando no puedes usar
multipart/form-data. - Adjuntos de correo: el estándar MIME codifica los adjuntos en Base64 porque el correo es un protocolo de texto.
- Autenticación HTTP básica: la cabecera
Authorization: Basic ...llevausuario:contraseñaen Base64. Esto no lo protege: por eso solo tiene sentido sobre HTTPS. - Claves y certificados en formato PEM, que son Base64 entre líneas
-----BEGIN ... -----.
Cuándo no usarlo
- Para “ocultar” información. Base64 se decodifica con una línea de código. Si necesitas confidencialidad, cifra.
- Para imágenes grandes en HTML. Una foto de 300 KB en Base64 pasa a 400 KB, no se cachea por separado y bloquea el parseo del HTML. Por encima de unos pocos KB, sirve el archivo con su propia URL (y conviértelo a WebP).
- Para texto normal en JSON. JSON ya transporta texto Unicode; codificarlo en Base64 solo añade un 33 % de peso.
Codificar y decodificar
En el navegador: btoa y atob (con cuidado)
btoa() y atob() trabajan con cadenas de bytes Latin-1, no con texto Unicode. Con caracteres fuera de ese rango (una ñ funciona, un emoji o caracteres asiáticos no) btoa lanza InvalidCharacterError. La forma correcta es pasar primero por TextEncoder:
// Codificar texto UTF-8 a Base64
function toBase64(texto) {
const bytes = new TextEncoder().encode(texto);
let binario = '';
for (const b of bytes) binario += String.fromCharCode(b);
return btoa(binario);
}
// Decodificar Base64 a texto UTF-8
function fromBase64(b64) {
const binario = atob(b64);
const bytes = Uint8Array.from(binario, (c) => c.charCodeAt(0));
return new TextDecoder().decode(bytes);
}
toBase64('Año 2026 ñ'); // "QcOxbyAyMDI2IMOx"
fromBase64('QcOxbyAyMDI2IMOx'); // "Año 2026 ñ"
Para archivos (por ejemplo, una imagen seleccionada por el usuario) usa FileReader.readAsDataURL(), que devuelve directamente una data URL con el contenido en Base64.
En Node.js: Buffer
const b64 = Buffer.from('Año 2026 ñ', 'utf8').toString('base64'); // "QcOxbyAyMDI2IMOx"
const texto = Buffer.from(b64, 'base64').toString('utf8'); // "Año 2026 ñ"
// Variante URL-safe (sin + / =)
const urlSafe = Buffer.from('Año 2026 ñ').toString('base64url');
// Un archivo completo
import { readFile } from 'node:fs/promises';
const png = await readFile('icono.png');
const dataUrl = `data:image/png;base64,${png.toString('base64')}`;
Buffer gestiona la codificación de caracteres correctamente, así que no hay que hacer el rodeo de TextEncoder.
En la terminal
# Codificar un archivo (GNU coreutils, Linux)
base64 imagen.png > imagen.b64
# Decodificar
base64 -d imagen.b64 > imagen.png
# Codificar una cadena sin el salto de línea final
printf 'Año 2026 ñ' | base64
En macOS la opción de decodificar es -D en versiones antiguas y -d o --decode en las recientes. Por defecto, la herramienta de GNU parte la salida en líneas de 76 caracteres; -w 0 lo evita.
Sin instalar nada
Para una conversión puntual, las herramientas de texto de AIMRAN Tools permiten codificar y decodificar Base64 en el navegador, sin enviar el contenido a ningún servidor. Es la opción cómoda para inspeccionar un token, un adjunto o una data URL.
Data URLs
Una data URL incrusta el contenido en la propia dirección: data:[tipo MIME][;base64],datos.
<img src="data:image/svg+xml;base64,PHN2ZyB4bWxucz0iaHR0cDovL3d3dy53My5vcmcvMjAwMC9zdmciIHdpZHRoPSIxMCIgaGVpZ2h0PSIxMCI+PC9zdmc+" alt="" width="10" height="10" />
Útiles para iconos pequeños y fondos CSS mínimos. Para SVG, a menudo es más compacto incrustarlo como texto con escape de URL que en Base64.
Errores habituales
- Usar
btoacon texto Unicode sin pasar porTextEncoder:InvalidCharacterError. - Olvidar el tipo MIME en una data URL: el navegador no sabe qué hacer con los bytes.
- Mezclar la variante estándar y la URL-safe: un
+decodificado como-corrompe los datos. Usa la misma variante en ambos extremos. - Tratar Base64 como seguridad: credenciales “codificadas” en un archivo público son credenciales públicas.
- Incrustar recursos grandes: más peso, sin caché y HTML más lento de parsear.
Conclusión
Base64 resuelve un problema concreto: mover bytes por un canal de texto. Hazlo con Buffer en Node.js, con TextEncoder + btoa en el navegador o con base64 en la terminal, usa la variante URL-safe cuando el resultado vaya en una URL, y recuerda sus dos límites: aumenta el tamaño un tercio y no protege nada.