Qué es Base64 y por qué existe
Base64 es una forma de escribir datos binarios arbitrarios usando solo 64 caracteres ASCII imprimibles: A–Z, a–z, 0–9, + y /, más = como relleno. Es una codificación, lo que significa que cualquiera puede revertirla sin clave. No oculta nada (más sobre esto en codificación frente a cifrado).
El objetivo es que los bytes atraviesen intactos los canales que solo admiten texto. Un archivo PNG contiene bytes como 0x00, 0x1A y 0x89 que un canal de texto puede eliminar, traducir o tratar como código de control. Escrito en Base64, el mismo archivo se convierte en iVBORw0KGgo..., que pasa sin cambios por el correo, JSON, XML, URLs (con la variante URL-safe), terminales y el copiar y pegar.
La definición actual es RFC 4648. Las especificaciones anteriores del correo MIME (RFC 2045) y de los certificados PEM describen el mismo alfabeto con reglas adicionales sobre la longitud de línea. Hay un resumen de las variantes en la página de estándares Base64.
Por qué lo necesitaba el correo
El correo electrónico de los inicios se diseñó para texto ASCII de 7 bits. Los servidores de retransmisión de la época podían eliminar el bit alto de cada byte, partir las líneas largas y reescribir los finales de línea, algo inofensivo para una carta y fatal para un archivo ZIP. MIME necesitaba una forma de llevar cualquier adjunto por esa tubería, y necesitaba un alfabeto que sobreviviera a todos los sistemas del camino.
Base64 elige sus 64 caracteres por esa razón. Las letras y los dígitos son idénticos en ASCII y en casi todos los juegos de caracteres heredados, + y / son casi igual de seguros, y ninguno de ellos es un carácter de control ni un espacio en blanco. Además, 64 es la mayor potencia de dos que se puede llenar con ese conjunto seguro, y una potencia de dos mantiene sencilla la aritmética de bits. El precio es el tamaño: 6 bits útiles por cada carácter de 8 bits significa que la salida ocupa 4/3 de la entrada, más el relleno.
El problema de los 8 bits ha desaparecido casi por completo de los servidores de correo modernos, pero la misma restricción aparece en cualquier sitio donde los datos binarios tengan que ir dentro de un formato de texto. JSON no tiene tipo binario, y los atributos HTML, el CSS y las cabeceras HTTP son todos texto, así que Base64 sigue siendo la forma habitual de meter bytes en ellos.
El algoritmo: entran 3 bytes, salen 4 caracteres
Base64 trabaja con bloques de 24 bits. Es el menor número divisible a la vez entre 8 (un byte) y 6 (un carácter Base64), así que 3 bytes corresponden exactamente a 4 caracteres.
Para cada bloque:
- Toma 3 bytes y escríbelos como 24 bits seguidos.
- Corta esos 24 bits en cuatro grupos de 6 bits.
- Lee cada grupo como un número del 0 al 63.
- Busca el número en el alfabeto y escribe ese carácter.
El alfabeto es una tabla fija. El índice 0 es A, el 25 es Z, el 26 es a, el 51 es z, el 52 es 0, el 61 es 9, el 62 es + y el 63 es /. La tabla completa está en la página del alfabeto Base64.
| Rango | Caracteres | Ejemplo |
|---|---|---|
| 0–25 | A–Z | 19 → T |
| 26–51 | a–z | 46 → u |
| 52–61 | 0–9 | 52 → 0 |
| 62 | + | |
| 63 | / |
La decodificación sigue los mismos pasos al revés: busca cada carácter para obtener 6 bits, une cuatro de ellos en 24 bits y divídelos en 3 bytes.
Ejemplo resuelto: “Man” se convierte en TWFu
El ejemplo clásico usa el texto ASCII Man. En ASCII, M es 77, a es 97 y n es 110.
| M | a | n | |
|---|---|---|---|
| Decimal | 77 | 97 | 110 |
| Binario | 01001101 | 01100001 | 01101110 |
Une los bits: 010011010110000101101110. Ahora córtalos cada 6 bits en lugar de cada 8:
| Grupo de 6 bits | 010011 | 010110 | 000101 | 101110 |
|---|---|---|---|---|
| Valor | 19 | 22 | 5 | 46 |
| Carácter | T | W | F | u |
Así que Man se codifica como TWFu. Fíjate en que ningún carácter de salida coincide con una letra de entrada. La W se forma con los últimos 4 bits de M y los 2 primeros de a. Por eso cambiar un byte de la entrada cambia dos caracteres de la salida, y por eso no puedes leer Base64 a ojo aunque la entrada sea texto corriente.
Puedes comprobarlo en cualquier shell:
echo -n Man | base64
# TWFu
Sin -n, echo añade un byte de salto de línea, y Man\n se codifica como TWFuCg==.
Cuando la entrada no es múltiplo de 3: el relleno
Los datos reales rara vez tienen una longitud divisible entre 3. El último bloque tiene entonces 1 o 2 bytes, y Base64 lo completa con bits a cero y signos =.
Quedan dos bytes, “Ma” → TWE=. Dos bytes son 16 bits. Añade dos bits a cero para llegar a 18, que son tres grupos de 6 bits:
| Grupo de 6 bits | 010011 | 010110 | 000100 | (ninguno) |
|---|---|---|---|---|
| Valor | 19 | 22 | 4 | |
| Carácter | T | W | E | = |
El tercer grupo es 0001 de la a seguido de los dos ceros añadidos, lo que da 4, que es E. Un = ocupa el lugar del cuarto carácter que falta.
Queda un byte, “M” → TQ==. Un byte son 8 bits. Añade cuatro bits a cero para llegar a 12, que son dos grupos: 010011 (19, T) y 010000 (16, Q). Dos signos = completan el bloque.
Así, el número de signos = te dice cuántos bytes tenía el último bloque: ninguno significa 3, uno significa 2 y dos significa 1. Nunca hay un tercer =, porque no existe un bloque con cero bytes sobrantes. La guía del relleno explica cuándo se puede omitir el = y cómo volver a ponerlo.
import base64
for s in [b"Man", b"Ma", b"M"]:
print(s, base64.b64encode(s))
# b'Man' b'TWFu'
# b'Ma' b'TWE='
# b'M' b'TQ=='
El texto tiene que convertirse antes en bytes
Base64 codifica bytes. El texto solo se convierte en bytes cuando eliges una codificación de caracteres, y esa elección cambia el resultado. La palabra café en UTF-8 son 5 bytes (la é ocupa dos), así que se codifica como Y2Fmw6k=. En Latin-1 son 4 bytes y se codifica como Y2Fm6Q==.
Este es el origen de una trampa muy conocida de JavaScript. La función del navegador btoa() trata cada carácter de una cadena como un byte, que es el comportamiento de Latin-1:
btoa("café"); // "Y2Fm6Q==" (Latin-1, not UTF-8)
btoa("café ✓"); // throws InvalidCharacterError
Para obtener Base64 de UTF-8 en JavaScript, convierte antes a bytes con TextEncoder, o usa Buffer en Node.js. La página de código JavaScript muestra los patrones que funcionan, y Uint8Array.toBase64() trata el método integrado más reciente. El codificador Base64 de este sitio usa UTF-8 por defecto y te deja elegir otro juego de caracteres.
Dónde te encontrarás Base64
- Adjuntos de correo. Cada adjunto de un archivo
.emlen bruto es un bloque Base64 dividido en líneas de 76 caracteres. Consulta Base64 en el correo electrónico. - Data URIs.
data:image/png;base64,iVBORw0KGgo...incrusta una imagen directamente en HTML o CSS. Si es buena idea o no se explica en rendimiento de las data URI. - HTTP Basic Auth. La cabecera
Authorization: Basic dXNlcjpwYXNzno es más queuser:passen Base64. - JWT. Las tres partes separadas por puntos de un JSON Web Token son Base64URL. Consulta Base64 en JWT.
- Archivos PEM. Los certificados y las claves entre líneas
-----BEGIN ...-----son Base64 de datos DER binarios. - APIs y configuración. Los Secrets de Kubernetes, los metadatos de la nube, las cargas de webhooks y muchas APIs JSON transportan archivos o bloques binarios como cadenas Base64.
Con el tiempo empiezas a reconocer los bloques por sus primeros caracteres: iVBORw0KGgo es un PNG, JVBERi0 es un PDF, /9j/ es un JPEG y eyJ es un JSON que empieza por {". La página de prefijos Base64 habituales recoge más. Para ver qué contiene un bloque, la herramienta Base64 a archivo detecta el formato y lo previsualiza en tu navegador.
Pega Base64 y mira el texto o los bytes que contiene. Funciona en local, en tu navegador.
Preguntas frecuentes
¿Base64 es una forma de compresión?
No. Siempre aumenta el tamaño de los datos: cada 3 bytes de entrada se convierten en 4 caracteres de salida, alrededor de un 33 % más. Consulta El aumento de tamaño de Base64 para la fórmula exacta.
¿Por qué se llama Base64?
Cada carácter de salida lleva uno de 64 valores posibles, es decir, 6 bits de información. El nombre es el tamaño del alfabeto, igual que hex es base 16.
¿Se puede codificar cualquier dato en Base64?
Sí. El algoritmo trabaja con bytes y no le importa lo que signifiquen, así que el texto, las imágenes, los PDF, las claves y los archivos comprimidos se codifican igual. El texto primero tiene que convertirse en bytes con una codificación de caracteres, normalmente UTF-8.
¿La salida Base64 puede contener espacios o saltos de línea?
El Base64 RFC 4648 simple no. Algunos formatos lo dividen en líneas, por ejemplo el correo MIME a 76 caracteres y los archivos PEM a 64, y la mayoría de los decodificadores se saltan esos espacios en blanco.