Saltar al contenido principal

Codificar y decodificar URL

El codificador y descodificador de URL aplica codificación porcentual y descodifica texto en tu navegador. El modo importa más de lo que parece: en una query string un espacio es +, en una ruta es %20, y descodificar el cuerpo de un formulario con el modo equivocado convierte “a + b” en “a b” sin ningún error.

Solo local
Modo
Texto sin codificar
0 B1 líneaLín. 1, Col. 1
Codificadosolo lectura
0 B1 línea

¿Cómo funciona Codificar y decodificar URL?

“Codificación de URL” nombra tres codificaciones distintas, y escoger la equivocada produce un error que nunca lanza una excepción.

La codificación porcentual no es la codificación de formulario

La codificación porcentual de RFC 3986 escribe un espacio como %20. El formato application/x-www-form-urlencoded —el que usan de verdad una query string y el cuerpo de un POST de formulario— lo escribe como +, lo que significa que un más literal tiene que escribirse %2B. Descodifica el cuerpo de un formulario con decodeURIComponent y el + sobrevive intacto, así que la búsqueda “a + b” llega como “a + b” cuando quien busca tecleó un más, y como “a+b” cuando tecleó espacios. Uno de los dos es incorrecto y ninguno lanza un error.

encodeURIComponent deja sin codificar cinco caracteres que el RFC reserva

!, ', (, ) y * están reservados por RFC 3986 y encodeURIComponent los deja tal cual. Casi siempre es inofensivo; no lo es cuando una firma se calcula sobre la forma codificada, y por eso todas las librerías de AWS SigV4 y OAuth 1.0a traen su propio codificador. La opción estricta los codifica.

Cada componente de la URL tiene sus propias reglas

Una ruta puede contener / ; un valor de query no puede contener un & sin codificar, o se parte en dos parámetros. Esa es la diferencia entre el modo componente y el modo URL completa: el primero codifica todo lo que no esté sin reservar, el segundo conserva los caracteres que dan estructura a una URL. Codificar una URL entera con encodeURIComponent produce una cadena que ya no es una URL.

La doble codificación y cómo detectarla

%2520 es un espacio que pasó dos veces por un codificador: el % de %20 se codificó a su vez como %25. A quien echa un vistazo a un log le parece “%20”, pero en el valor descodificado produce un %20 literal. La herramienta cuenta cuántas pasadas de descodificado sobrevive la entrada, así que una capa extra perdida se ve en lugar de quedar como un misterio.

Dividir una URL usa el parser de la plataforma

El desglose de componentes sale de la propia implementación de URL del navegador y no de una expresión regular, porque analizar URL tiene suficientes casos límite —userinfo, literales IPv6, puertos por defecto, hosts con codificación porcentual— como para que el algoritmo de WHATWG que ya está en la plataforma sea más corto y más correcto que cualquier patrón. Las claves de query duplicadas se conservan en orden, porque muchas APIs les dan significado.

Entrada

q=a + b

Codificado

component: q%3Da%20%2B%20b
form:      q%3Da+%2B+b

¿Qué opciones y casos límite admite Codificar y decodificar URL?

Referencia técnica y opciones
ParámetroTipoValor predeterminadoComportamiento y casos límite
ComponenteencodeURIComponentpredeterminadoPara un único valor de consulta o un segmento de ruta. Codifica todo excepto A–Z a–z 0–9 - _ . ~ y los cinco caracteres de abajo.
URL completaencodeURI—Para una URL entera. Conserva : / ? # [ ] @ ! $ & ' ( ) * + , ; = para que la URL siga siendo una URL. Usar aquí el modo componente destruye la estructura.
Formulariox-www-form-urlencoded—Para una cadena de consulta o un cuerpo POST. Un espacio es +, un + literal es %2B. Decodificar correctamente exige deshacer el + antes de la decodificación por porcentaje, o un + literal acaba convertido en un espacio.
base64urlRFC 4648 §5—El alfabeto base64 apto para URL: - y _ en lugar de + y /, sin relleno. Es lo que usan los segmentos de JWT.
RFC 3986 estrictobooleanodesactivadoTambién codifica ! ' ( ) *, que encodeURIComponent deja tal cual. Necesario cuando la forma codificada alimenta una firma.
Codificar todobooleanodesactivadoCodifica en porcentaje cada byte, incluidos los no reservados. Feo, válido y, de vez en cuando, lo único que acepta una pasarela exigente.
Juego de caracteresUTF-8siempreLo que no es ASCII se codifica como sus bytes UTF-8, un %XX por byte, que es lo que espera cualquier navegador y servidor actuales.
Entrada malformadanotificadacon posicióndecodeURIComponent lanza un URIError sin más. En su lugar, aquí la secuencia problemática se localiza y se nombra.

Preguntas frecuentes

¿Por qué mi espacio es un + en vez de %20?

Porque estás en modo formulario, que es el correcto para una query string o el cuerpo de un POST de formulario —ese formato define el espacio como +—. En un segmento de ruta o un fragmento, un espacio es %20 y un + es un más literal. Ambas codificaciones son correctas; usar la equivocada en cada posición es lo que corrompe el valor.

¿encodeURI o encodeURIComponent?

encodeURIComponent para una pieza suelta —un valor de query, un segmento de ruta, un fragmento—. encodeURI para una URL completa que quieres que siga siendo una URL. La prueba es sencilla: si el texto que codificas contiene caracteres estructurales (un ?, un &, una /) y quieres que sigan funcionando como tales, necesitas encodeURI; si quieres que se conviertan en datos, necesitas encodeURIComponent.

¿Qué es %2520 y cómo lo has conseguido?

Un espacio, codificado dos veces. La primera pasada produjo %20; la segunda codificó ese % como %25, y quedó %2520. Normalmente significa que un valor lo codificó el código de la aplicación y después otra vez un framework o un proxy. El contador de profundidad de arriba muestra cuántas pasadas sobrevive tu entrada, así que puedes saber si una capa es una demasiada.

¿Por qué !'()* no se codifican?

encodeURIComponent los deja deliberadamente, aunque RFC 3986 los reserva. Casi siempre es inofensivo —hasta que la cadena codificada es la entrada de una firma, donde quien firma y quien verifica tienen que coincidir byte a byte—. Por eso AWS SigV4 y OAuth 1.0a especifican cada uno su propio codificador. Activa el modo estricto si estás en esa situación.

¿base64url es lo mismo que base64?

El mismo algoritmo, otro alfabeto. base64 usa + y /, que significan algo dentro de una URL, así que base64url los cambia por - y _ y elimina el relleno =, que significa algo en una query string. Un JWT son tres segmentos base64url unidos por puntos, y por eso un JWT se puede pegar directamente en una URL y un bloque base64 no.

¿Se sube mi entrada?

No. Codificar y descodificar son operaciones de cadena que se ejecutan en tu navegador —abre el panel Network y obsérvalo mientras escribes—. Aquí importa porque las URL que la gente necesita descodificar suelen ser URL de callback firmadas, redirecciones OAuth y tokens de sesión; es decir, credenciales en una forma que parece inofensiva.