Codificar y decodificar Base64 y URL en línea, con UTF-8

Para codificar y decodificar Base64 sin instalar nada, escribe o pega un texto y conviértelo, o pega un Base64 para ver qué contiene. También codifica y decodifica URL (los %20 y %C3%A9) y convierte un archivo en Base64 o en un data URI. Los acentos, la ñ y los emojis se pasan a UTF-8 antes de codificar, así que salen bien, y si algo no es válido te dice qué carácter falla y por qué. Todo se calcula en tu navegador: ni el texto ni los archivos se envían a ningún sitio.

Ejemplos:

Base64 no es cifrado. Cualquiera puede decodificarlo sin ninguna clave: no lo uses para ocultar contraseñas ni datos personales. Sirve para meter datos binarios en sitios que solo admiten texto, como un JSON, un correo o una URL.

Qué es Base64 y cómo funciona

Base64 (RFC 4648) representa cualquier secuencia de bytes con solo 64 caracteres «seguros»: las 26 letras mayúsculas, las 26 minúsculas, las 10 cifras, + y /. Toma los bytes de tres en tres (24 bits), los parte en cuatro grupos de 6 bits y cambia cada grupo, un número del 0 al 63, por su carácter. Por eso el resultado ocupa un tercio más que el original: 3 bytes se convierten en 4 caracteres.

Con la palabra Hola, que en UTF-8 son los bytes 48, 6F, 6C y 61 (en hexadecimal):

H        o        l          →  01001000 01101111 01101100
en grupos de 6 bits          →  010010 000110 111101 101100
números                      →  18     6      61     44
caracteres                   →  S      G      9      s

a                            →  01100001
se completa con ceros        →  011000 010000
números y caracteres         →  24 = Y, 16 = Q, y == de relleno

El resultado es SG9sYQ==. Como al final solo quedaba 1 byte, salen 2 caracteres y se añaden dos = de relleno para completar el grupo de 4. Con 2 bytes sobrantes se añade un solo =, y si los bytes son múltiplo de 3 no hay relleno.

Base64, base64url y relleno

  • base64url: cambia + por - y / por _, porque + y / tienen significado dentro de una URL. Es la que usan los JWT y muchos tokens.
  • Sin relleno: como el = también hay que codificarlo en una URL, base64url suele omitirlo cuando se conoce la longitud. El decodificador de esta página lo acepta y te avisa si falta en un Base64 estándar.
  • Saltos de línea: los certificados PEM y los adjuntos de correo parten el Base64 en líneas de 64 o 76 caracteres. El decodificador ignora los espacios y saltos de línea y te dice cuántos quitó.
  • Acentos y emojis: en JavaScript, btoa("ñ") funciona pero codifica en Latin-1, y btoa("👋") da error. Hay que pasar el texto a UTF-8 primero, con TextEncoder, como hace esta herramienta.
  • Datos binarios: si lo decodificado no es texto, la herramienta muestra los bytes en hexadecimal, reconoce los formatos más comunes (PNG, JPEG, PDF, ZIP…) y te deja descargar el archivo.

Codificar una URL: encodeURIComponent o encodeURI

  • Un valor (lo que va dentro de un parámetro, como el texto de una búsqueda): usa encodeURIComponent. Codifica todo menos las letras sin acento, las cifras y - _ . ! ~ * ' ( ), así que un & o un = del valor no rompen la URL.
  • Una URL completa: usa encodeURI. Respeta además los separadores ; , / ? : @ & = + $ #, para que la URL siga funcionando, y solo codifica los espacios, los acentos y otros caracteres que no pueden ir sueltos.
  • Espacios como +: los formularios HTML envían los espacios como + (formato application/x-www-form-urlencoded). En el resto de la URL, un espacio es %20.
  • UTF-8: cada carácter se pasa a UTF-8 y cada byte se escribe como % y dos cifras hexadecimales: la é es %C3%A9. Si ves %E9, la URL se codificó en Latin-1, y el decodificador te lo explica.

Base64 y URL en Python

import base64
from urllib.parse import quote, quote_plus, unquote

texto = "Hola, señor 👋"
datos = texto.encode("utf-8")                      # Base64 trabaja con bytes, no con texto

print(base64.b64encode(datos).decode())            # Base64 estándar, con relleno
print(base64.urlsafe_b64encode(datos).decode().rstrip("="))   # base64url sin relleno, como en los JWT

# Decodificar: validate=True rechaza los caracteres que no son de Base64 en vez de ignorarlos
print(base64.b64decode("SG9sYQ==", validate=True).decode("utf-8"))
try:
    base64.b64decode("SG9sYQ=", validate=True)
except ValueError as error:                        # binascii.Error hereda de ValueError
    print("No válido:", error)

# base64url sin relleno: se añade el = que falte antes de decodificar
s = "SG9sYQ"
print(base64.urlsafe_b64decode(s + "=" * (-len(s) % 4)).decode("utf-8"))

# URL: quote equivale a encodeURIComponent si se le dan los mismos caracteres seguros
print(quote("café con leche & pan", safe="-_.!~*'()"))
print(quote_plus("café con leche & pan"))          # espacios como +, como en los formularios
print(unquote("caf%C3%A9%20con%20leche"))
$ python3 base64url.pySG9sYSwgc2XDsW9yIPCfkYs=
SG9sYSwgc2XDsW9yIPCfkYs
Hola
No válido: Incorrect padding
Hola
caf%C3%A9%20con%20leche%20%26%20pan
caf%C3%A9+con+leche+%26+pan
café con leche

Otras herramientas para desarrolladores: generador de hash SHA-256 y MD5, formateador de JSON, decodificador de JWT y conversor de fechas Unix. Todas, en decodigo.com/herramientas.

Base64, base64url, relleno y forma canónica: RFC 4648, secciones 3.2, 3.3, 3.5, 4 y 5. Codificación de URL y caracteres reservados: RFC 3986, secciones 2.1 a 2.5. La herramienta se comparó con los módulos base64, binascii y urllib.parse de Python en 21,938 casos al azar, con acentos, emojis, caracteres de control y Base64 con errores: coinciden en todos.