Cómo funciona la codificación URL
Una URL solo puede contener un pequeño conjunto de caracteres ASCII, y algunos tienen una función: / separa la ruta, ? inicia la consulta, & y = la dividen en parámetros, # inicia el fragmento. Cualquier otro carácter, o uno de estos usado como dato normal, se escribe como % y dos dígitos hexadecimales por cada uno de sus bytes en UTF-8. Esto se llama codificación porcentual (RFC 3986).
espacio → %20 (o + en datos de formulario) & → %26 / → %2F é → C3 A9 → %C3%A9 € → E2 82 AC → %E2%82%AC
Qué caracteres codificar depende de lo que estés codificando. Un valor suelto, como un término de búsqueda, debe tener codificados también / ? & = #, o rompería la URL en la que va: eso es encodeURIComponent en JavaScript y urlencode en PHP. Una URL completa debe conservarlos, o dejaría de ser un enlace: eso es encodeURI. Los formularios HTML envían los espacios como + en lugar de %20 (application/x-www-form-urlencoded), así que un + en una cadena de consulta suele significar un espacio.
Decodificar lo revierte: cada %XX pasa a ser un byte, y los bytes se leen como UTF-8. El decodeURIComponent del propio navegador solo dice «URI malformed» cuando algo va mal. Esta página nombra la secuencia y la señala: un % sin dos dígitos hexadecimales detrás, o bytes que no son UTF-8 válido, lo que suele significar que el texto se codificó como Latin-1.
Ejemplo
El término de búsqueda «vps hosting/€5» como un solo valor se convierte en vps%20hosting%2F%E2%82%AC5: el espacio es %20, la barra %2F, y el signo del euro, tres bytes en UTF-8, pasa a ser %E2%82%AC. Con «Escribir los espacios como +» para datos de formulario queda vps+hosting%2F%E2%82%AC5. Decodificar r%C3%A9sum%C3%A9 da résumé, y decodificar caf%E9 falla en %E9, porque eso es é en Latin-1, no en UTF-8.
Preguntas
¿Qué es la codificación URL?
La codificación URL, o codificación porcentual, escribe los caracteres que no están permitidos en una URL, o que tienen allí un significado especial, como % seguido de dos dígitos hexadecimales por cada byte. Un espacio pasa a ser %20, & pasa a ser %26 y é pasa a ser %C3%A9. Permite que cualquier texto viaje sin problemas dentro de un enlace o de una cadena de consulta.
¿Qué diferencia hay entre encodeURI y encodeURIComponent?
encodeURI es para una dirección completa: conserva los caracteres que tienen una función en una URL, como : / ? # & =, para que el enlace siga funcionando. encodeURIComponent es para una pieza que va dentro de una URL, como el valor de un parámetro: codifica también esos caracteres, de modo que un & en el valor no pueda iniciar un parámetro nuevo. En caso de duda, codifica cada valor con encodeURIComponent y únelos después.
¿Un espacio debe ser %20 o +?
Las dos son correctas, en sitios distintos. En la ruta de una URL, un espacio debe ser %20. En una cadena de consulta enviada por un formulario HTML (application/x-www-form-urlencoded), un espacio se escribe como + y un signo más real como %2B. La mayoría de los servidores leen ambos en una cadena de consulta. Al decodificar datos de formulario, activa «Leer + como un espacio».
¿Por qué obtengo «URI malformed» al decodificar?
O bien un % no va seguido de dos dígitos hexadecimales, por ejemplo un simple «100%» o «%G1», o bien los bytes %XX no son UTF-8 válido, a menudo porque el texto se codificó en Latin-1 (é como %E9) o se cortó un carácter de varios bytes. Esta página muestra qué secuencia es la incorrecta y dónde está, para que puedas corregirla.
¿Cómo decodifico URL en la línea de comandos o en código?
En JavaScript: decodeURIComponent(s), tras s.replace(/\+/g, ' ') para datos de formulario. En Python: urllib.parse.unquote(s), o unquote_plus(s) para datos de formulario. En PHP: rawurldecode($s), o urldecode($s), que también convierte + en un espacio. En un shell con Python instalado: python3 -c "import sys, urllib.parse as u; print(u.unquote(sys.argv[1]))" 'r%C3%A9sum%C3%A9'.