Codificador y decodificador de Base64
Pega texto de un lado y obtén Base64 del otro. Los acentos y los emoji sobreviven la ida y la vuelta, que es más de lo que btoa() te va a dar en la consola. No se envía nada a ningún lado: la conversión ocurre en esta pestaña.
La variante apta para URL cambia los dos caracteres que rompen dentro de una query string y elimina el relleno =. Al decodificar se aceptan los dos alfabetos.
Solo afecta a la codificación. Los saltos de línea se quitan antes de decodificar.
Qué hace Base64 en realidad
Base64 reescribe bytes arbitrarios usando solo 64 caracteres que sobreviven al viaje por sistemas que esperan texto. Toma tres bytes —24 bits— y los parte en cuatro grupos de seis bits. Seis bits guardan un número del 0 al 63, y cada número corresponde a un carácter. Entran tres bytes, salen cuatro caracteres, siempre.
Esa proporción es toda la historia del costo: la salida Base64 es un tercio más grande que la entrada, antes de cualquier salto de línea. Cuando la longitud de la entrada no es un múltiplo de tres, el codificador rellena el último grupo y lo marca con signos =: uno cuando sobran dos bytes, dos cuando sobra un byte. Por eso tantas cadenas Base64 terminan en = o ==, y por eso ninguna termina nunca en tres.
Dos alfabetos, y el bug que aparece al mezclarlos
El alfabeto estándar del RFC 4648 es A–Z, a–z, 0–9, más + y /. Esos dos últimos son hostiles dentro de una URL: + se lee como un espacio en datos codificados de formulario, y / termina un segmento de la ruta. Por eso el mismo RFC define un segundo alfabeto, base64url, que los sustituye por - y _ y en general elimina el relleno, porque = también hay que escaparlo.
Los JSON Web Tokens usan base64url. También la mayoría de las cookies firmadas y muchos identificadores de API. Si un token se decodifica como basura en una biblioteca y bien en otra, el alfabeto es lo primero que conviene revisar: los dos no son intercambiables, aunque se vean casi idénticos. El decodificador de esta página acepta los dos y los normaliza, lo cual es cómodo pero también significa que va a leer sin quejarse una entrada que una biblioteca estricta rechazaría.
Por qué btoa() se rompe con la palabra "café"
El btoa() que trae el navegador no recibe texto. Recibe una cadena binaria, o sea que cada carácter tiene que caber en un byte. Cualquier cosa por encima de U+00FF lanza InvalidCharacterError, y por eso fallan los caracteres acentuados y los emoji mientras que el inglés simple no: un error que sobrevive a las pruebas y después aparece en producción la primera vez que alguien escribe su propio nombre.
La solución es convertir el texto a bytes UTF-8 primero y pasarle esos a btoa(). Esta herramienta lo hace con TextEncoder, así que su salida coincide exactamente con base64.b64encode(s.encode("utf-8")) de Python y con Buffer.from(s, "utf8").toString("base64") de Node. También significa que la cuenta de bytes de las estadísticas de arriba no es la cuenta de caracteres: un carácter latino acentuado son dos bytes, y la mayoría de los emoji son cuatro.
Base64 no es cifrado
No tiene clave ni secreto. Cualquiera que vea la cadena puede revertirla en un segundo, usando esta misma página. Una contraseña guardada en Base64 en un archivo de configuración es una contraseña en texto plano con un disfraz. Lo mismo vale para el contenido de un JWT: está firmado, no escondido, y cualquiera que tenga el token puede leer cada uno de los claims que hay adentro.
Tampoco es compresión. Codificar un zip en Base64 lo hace más grande, no más pequeño.
Hasta dónde llega esta herramienta
- Texto entra, texto sale. No hay selector de archivos. Pegar un archivo binario en una caja de texto lo destruye, así que codificar una imagen o un PDF es otro trabajo con otra forma.
- Una sola pasada, en memoria. Unos pocos megabytes están bien. Decenas de megabytes van a trabar la pestaña, porque el codificador arma una cadena intermedia tan larga como la entrada antes de empezar.
- El decodificador es permisivo. Quita los espacios en blanco, repone el relleno que falta y acepta cualquiera de los dos alfabetos. Si una cadena se decodifica aquí pero falla en tu código, sospecha del relleno o del alfabeto antes que de tu código.
- No puede decirte qué significan los bytes. Si el resultado decodificado parece ruido, el contenido era binario. La herramienta lo avisa, pero no va a identificar el tipo de archivo por ti.
La cuestión del corte de línea
MIME, el estándar detrás de los adjuntos de correo, limita las líneas a 76 caracteres. PEM, el formato que guarda certificados y claves privadas, corta a los 64. Los dos existen porque los servidores de correo antiguos destrozaban las líneas largas. Se supone que los decodificadores ignoran los saltos de línea, y casi todos lo hacen, pero unos pocos parsers estrictos, sobre todo en sistemas embebidos y empresariales viejos, no. Si un bloque Base64 copiado de un correo no se decodifica en algún lado, los saltos de línea duros son los culpables de siempre.
Preguntas frecuentes
¿Por qué mi texto con acentos se rompe con btoa() pero funciona aquí?
btoa() solo acepta caracteres por debajo de U+0100, así que cualquier cosa con un acento o un emoji lanza InvalidCharacterError. Esta herramienta convierte tu texto a bytes UTF-8 primero y codifica esos, que es lo que hacen Python y Node por defecto.
¿Cuál es la diferencia entre Base64 y base64url?
Los dos últimos caracteres del alfabeto. Base64 estándar usa + y /, base64url usa - y _, y base64url normalmente no lleva relleno =. Los JWT y la mayoría de los tokens que viajan dentro de una URL usan base64url. El resto de la codificación es idéntico.
¿Base64 es seguro?
No. Es una codificación, no un cifrado: no hay clave y cualquiera puede revertirlo al instante. Úsalo para mover bytes por canales que solo admiten texto, nunca para esconder algo.
¿Por qué mi cadena Base64 termina con signos =?
Porque la longitud de la entrada no era un múltiplo de tres. Un = final significa que el último grupo tenía dos bytes; dos = significan que tenía uno. Una cadena nunca puede terminar en tres caracteres de relleno.
¿Puedo decodificar una cadena a la que le falta el relleno?
Sí. El decodificador de esta página repone el relleno antes de decodificar. Muchas bibliotecas estrictas no lo hacen, y esa es la razón más común de que un token base64url falle en otro lado pero funcione aquí.
Última actualización 19 de septiembre de 2026