Subir un archivo
  1. base64hub
  2. Aprende Base64
  3. Errores de Base64
Solución de problemas

Errores al decodificar Base64 y cómo solucionarlos

La mayoría de los fallos con Base64 tienen cinco causas: el alfabeto equivocado, la falta de relleno, caracteres sueltos, el juego de caracteres equivocado o datos codificados dos veces. Busca tu mensaje de error abajo y salta a la solución.

Los mensajes de error de un vistazo

MensajeDónde lo vesCausa más probable
binascii.Error: Incorrect paddingbase64.b64decode de PythonFaltan = al final, a menudo por Base64URL o una cadena cortada
binascii.Error: Invalid base64-encoded string: number of data characters (5) cannot be 1 more than a multiple of 4PythonEntrada truncada, o -/_ descartados sin avisar
binascii.Error: Only base64 data is allowedPython con validate=TrueSalto de línea, espacio, - o _ en la entrada
InvalidCharacterError: Failed to execute 'atob' on 'Window': The string to be decoded is not correctly encoded.Chrome, EdgeCaracteres Base64URL, caracteres basura, longitud incorrecta
InvalidCharacterError: String contains an invalid characterFirefoxLo mismo que arriba
InvalidCharacterError: Invalid characteratob de Node.jsLo mismo que arriba
IllegalArgumentException (“Illegal base64 character …”)java.util.Base64 de JavaDecodificador que no corresponde al alfabeto, o saltos de línea
FormatExceptionConvert.FromBase64String de .NETCaracteres Base64URL o falta de relleno
base64: invalid inputbase64 -d de GNU coreutilsCaracteres fuera del alfabeto

Cómo solucionar los errores del decodificador

«Incorrect padding» en Python

La salida Base64 siempre tiene una longitud múltiplo de 4, rellenada con = al final. El decodificador de Python exige el relleno:

>>> import base64
>>> base64.b64decode("SGVsbG8")
Traceback (most recent call last):
  ...
binascii.Error: Incorrect padding
>>> base64.b64decode("SGVsbG8=")
b'Hello'

La falta de relleno suele significar que la cadena es Base64URL (los JWT, los tokens en URL y muchas API omiten el =) o que algo la recortó. Vuelve a añadir el relleno:

s = "SGVsbG8"
s += "=" * (-len(s) % 4)

Cuando la longitud es uno más que un múltiplo de 4, el relleno no sirve de nada. Python informa entonces de number of data characters (5) cannot be 1 more than a multiple of 4. Un solo carácter sobrante contiene solo 6 bits, así que falta parte de los datos. Este mensaje también puede aparecer sin que la cadena esté truncada: sin validate=True, Python descarta los caracteres fuera del alfabeto, incluidos - y _. base64.b64decode("SGk_Pg==") elimina el _ y se queda con 5 caracteres de datos. Usa base64.urlsafe_b64decode para las entradas Base64URL.

«Invalid character» y fallos de atob

Los navegadores implementan atob con el mismo algoritmo, pero redactan el error de forma distinta. Chrome dice «The string to be decoded is not correctly encoded», Firefox dice «String contains an invalid character» y Node.js dice «Invalid character». Los tres lanzan un InvalidCharacterError con estas entradas:

  • Caracteres Base64URL. atob("SGk_Pg") falla por el _. Sustituye antes - por + y _ por /.
  • Una longitud de 4n+1 después de quitar los espacios en blanco, como en atob("A").
  • Caracteres que no pintan nada ahí: comillas copiadas de un JSON, un prefijo data:, un %2F de la codificación de URL.

atob sí perdona algunas cosas. Se salta espacios y saltos de línea, y acepta la falta de relleno cuando la longitud cuadra, así que atob("SGVsbG8") devuelve "Hello". El error inverso, btoa fallando con «characters outside of the Latin1 range», tiene que ver con el texto Unicode y se explica en Uint8Array.toBase64.

Un decodificador tolerante que admite los dos alfabetos, espacios en blanco y falta de relleno:

function decodeLoose(s) {
  s = s.replace(/\s+/g, "").replace(/-/g, "+").replace(/_/g, "/");
  s += "=".repeat((4 - (s.length % 4)) % 4);
  return Uint8Array.from(atob(s), (c) => c.charCodeAt(0));
}

new TextDecoder().decode(decodeLoose("SGk_Pg")); // "Hi?>"

El equivalente en Python:

import base64

def b64decode_any(s: str) -> bytes:
    s = "".join(s.split())
    s = s.replace("-", "+").replace("_", "/")
    s += "=" * (-len(s) % 4)
    return base64.b64decode(s, validate=True)

La herramienta Reparar Base64 aplica la misma limpieza y te dice qué ha cambiado.

«Illegal base64 character» en Java y FormatException en .NET

java.util.Base64 de Java trae tres decodificadores, y cada uno es estricto con su propio alfabeto. El mensaje indica el carácter problemático en hexadecimal: 5f es _, 2d es -, 2f es /, 20 es un espacio y a es un salto de línea.

La entrada contieneUsa
+ y /Base64.getDecoder()
- y _Base64.getUrlDecoder()
Saltos de línea (MIME, cuerpos PEM)Base64.getMimeDecoder()

El decodificador básico rechaza los saltos de línea y los espacios. Sí acepta la falta de relleno, así que SGVsbG8 se decodifica sin quejas.

Convert.FromBase64String de .NET lanza FormatException con caracteres Base64URL y cuando falta el relleno. Se salta los espacios y los saltos de línea. Corrige el alfabeto y el relleno como se muestra arriba antes de llamarlo. Consulta Base64 en Java y Base64 en C# para ver ejemplos completos.

El texto sale ilegible

La decodificación ha funcionado, pero el texto se ve mal. Base64 guarda bytes, y esos bytes se generaron a partir de un texto con una codificación de caracteres concreta. Si los lees con otra distinta, obtienes mojibake.

VesOriginalQué ha pasado
CaféCaféBytes UTF-8 leídos como Latin-1 o Windows-1252
Caf�CaféBytes Windows-1252 leídos como UTF-8
H e l l o o H\0e\0l\0l\0o\0HelloBytes UTF-16LE leídos como UTF-8

La primera fila es la trampa clásica de atob. atob("Q2Fmw6k=") devuelve "Café", porque atob asigna un carácter a cada byte. Decodifica los bytes como UTF-8:

const bytes = Uint8Array.from(atob("Q2Fmw6k="), (c) => c.charCodeAt(0));
new TextDecoder().decode(bytes); // "Café"

UTF-16LE es habitual con las herramientas de Windows: el -EncodedCommand de PowerShell y muchas API de .NET lo generan. Base64 a texto te deja cambiar el juego de caracteres hasta que la salida se lea bien, y Base64 a UTF-16 se ocupa del caso de caracteres anchos.

La salida parece binaria

Si el resultado decodificado está lleno de �, caracteres de control o fragmentos como PNG, PK y %PDF, el contenido es un archivo. Mira los primeros caracteres del Base64: iVBORw0KGgo es un PNG, JVBERi0 un PDF y H4sI gzip. La lista completa está en prefijos Base64 habituales. Abre los datos con Base64 a archivo, que detecta el formato y ofrece la descarga. Para H4sI, usa decodificar gzip en Base64.

La decodificación da bytes distintos de los esperados

No hay error, pero los bytes no son los correctos. Estas son las razones habituales:

  • Un salto de línea final al codificar. echo "hello" | base64 da aGVsbG8K (con \n), mientras que echo -n "hello" | base64 da aGVsbG8=. Usa printf '%s' o echo -n.
  • El + convertido en espacio. En las query strings de las URL y en los cuerpos de formulario, + significa espacio. URLSearchParams("t=PGI+Ym9sZDwvYj4=").get("t") devuelve PGI Ym9sZDwvYj4=. Algunos decodificadores lanzan entonces un error y otros descartan el espacio y producen basura. Codifica el Base64 con encodeURIComponent antes de meterlo en una URL, o usa Base64URL.
  • Codificación porcentual sin deshacer. SGk%2FPg%3D%3D debe decodificarse como URL, quedando SGk/Pg==, antes de decodificar el Base64.
  • Escapes copiados de un JSON. Copiar una cadena de un JSON en bruto puede arrastrar un \n literal (dos caracteres). El decodificador tolerante de Python descarta la barra invertida, se queda con la n y devuelve bytes incorrectos sin ningún error: b64decode("SGVs\\nbG8=") da b'Hel\x9d\xb1\xbc'. Analiza el JSON en lugar de copiar de él. El decodificador Base64 para JSON lo hace con todos los campos.
  • Espacios en blanco: estricto frente a tolerante. Python sin validate=True, atob, .NET y el decodificador MIME de Java se saltan los saltos de línea. Python con validate=True y el decodificador básico de Java los rechazan. Los datos MIME y PEM vienen cortados a 76 o 64 caracteres, así que elige un decodificador que los acepte.

Datos codificados dos veces

Al decodificar U0dWc2JHOGdkMjl5YkdRaA== se obtiene SGVsbG8gd29ybGQh, que vuelve a ser Base64 válido y se decodifica como Hello world!. Cuando el resultado de una decodificación está formado solo por caracteres Base64 y su longitud es múltiplo de 4, sospecha de una doble codificación.

Ocurre a menudo con los Secrets de Kubernetes. Los valores bajo data: están en Base64, y kubectl create secret --from-literal los codifica por ti. Si codificas tú antes el valor, el pod recibe texto Base64 en lugar de la contraseña. Usa stringData: para los valores en claro, o comprueba lo que hay guardado con el decodificador de Secrets de Kubernetes. Si tienes dudas, el validador Base64 indica si una cadena es válida y cuántos bytes contiene.

Preguntas frecuentes

¿Cómo soluciono binascii.Error: Incorrect padding?

Añade = hasta que la longitud sea múltiplo de 4: s += "=" * (-len(s) % 4). Si la cadena es Base64URL, sustituye además - por + y _ por /, o usa base64.urlsafe_b64decode.

¿Por qué atob falla con un JWT?

Los JWT usan Base64URL, que tiene - y _. atob solo conoce + y /. Convierte antes los caracteres o pega el token en el decodificador JWT.

¿Por qué el texto decodificado muestra é en lugar de é?

Los bytes son UTF-8, pero se leyeron como Latin-1 o Windows-1252. Decodifica los bytes como UTF-8, por ejemplo con TextDecoder en JavaScript o .decode("utf-8") en Python.

¿Se puede reparar una cadena Base64 de longitud 4n+1?

No. Un carácter sobrante solo lleva 6 bits, menos de un byte, así que falta al menos un carácter. Busca la fuente original o comprueba dónde se cortó la cadena.

¿Cómo sé si unos datos se codificaron en Base64 dos veces?

Decodifícalos una vez. Si el resultado vuelve a ser una cadena formada solo por A-Z a-z 0-9 + / = con una longitud múltiplo de 4, decodifícala otra vez.

Sigue leyendo