La codificación de URL sustituye un carácter por un signo de porcentaje y dos dígitos hexadecimales: un espacio se convierte en %20, un ampersand se convierte en %26, un signo de interrogación se convierte en %3F. El objetivo es evitar que un carácter se lea como sintaxis de la URL cuando lo que querías era que fuera un dato. Nada más.
La razón por la que parece más difícil que eso es que casi toda pregunta sobre el tema es en realidad una pregunta sobre el alcance. ¿Qué caracteres, en qué parte de la URL, escapados por qué capa? Si te equivocas con el alcance obtienes uno de dos fallos clásicos: un parámetro de seguimiento que se trunca en silencio, o un destino que llega como https%3A%2F%2Fexample.com y da un 404. Este artículo cubre los dos conjuntos de caracteres que decantan la respuesta, los lugares donde cambian las reglas, y cómo comprobar qué lleva realmente un enlace. Para la imagen más amplia de qué hace una redirección con todo esto, consulta tipos de redirecciones.
Los dos conjuntos que deciden todo
RFC 3986, sección 2.3 define un conjunto no reservado que nunca necesita codificación: letras, dígitos, y exactamente cuatro signos de puntuación - guion, punto, guion bajo, tilde. Si tu valor solo contiene esos, no tienes nada que hacer.
Todo lo demás cae en uno de dos grupos. Los caracteres reservados llevan significado estructural: : / ? # [ ] @ separan las partes de una URL, y ! $ & ' ( ) * + , ; = separan cosas dentro de esas partes. La sección 2.2 los enumera. Son legales como sintaxis y deben codificarse cuando aparecen como datos. El resto es todo lo que queda fuera de ASCII, que se codifica byte a byte después de convertirse a UTF-8 - por eso una letra acentuada suele costar seis caracteres en lugar de tres.
Eso da la única regla que merece la pena memorizar: codifica un carácter cuando es un dato y de otro modo se leería como sintaxis. Un ampersand entre dos parámetros es sintaxis. Un ampersand dentro del nombre de una campaña es un dato, y si lo dejas tal cual, la lista de parámetros termina ahí.
Codifica el valor, no la URL
Este es el error que veo más a menudo, y siempre tiene la misma forma. Alguien tiene una URL, sabe que necesita codificación, así que pega todo el conjunto en un codificador y obtiene:
https%3A%2F%2Fexample.com%2Fspring%3Futm_campaign%3Dspring%20sale
Esa cadena no es una URL. Es un trozo de texto con forma de URL que solo puede ser un valor dentro de otra URL - que es exactamente donde pertenece cuando estás pasando un destino a través de un redirector, y exactamente donde no pertenece cuando estás intentando abrirla.
El tratamiento correcto codifica cada valor por separado:
https://example.com/spring?utm_campaign=spring%20sale&utm_source=flyer
El esquema, el host, los separadores de ruta y los ? y & se dejan como sintaxis. Solo cambió el valor. Cada lenguaje incluye dos funciones para esta distinción, y elegir la equivocada es la otra mitad del problema: la página de MDN sobre encodeURIComponent es tajante en que encodeURI deja deliberadamente los caracteres reservados tal cual porque espera una URI completa, mientras que encodeURIComponent los escapa porque espera un fragmento de una. Los valores quieren encodeURIComponent. En Python eso es urllib.parse.quote, en Go url.QueryEscape, en PHP rawurlencode.
El espacio es %20, salvo cuando es un más
Ambos son correctos, en lugares distintos, y esta es la cosa más confusa de todo el tema.
En una ruta o en una URI genérica, un espacio es %20. En una cadena de consulta construida como la construye un formulario HTML, un espacio es +, porque eso es lo que especifica la serialización application/x-www-form-urlencoded en el estándar de URL de WHATWG. Ambas formas se leen como un espacio en todo analizador de consultas del lado del servidor que probablemente te encuentres.
La trampa está en la dirección contraria. Si un signo más es dato - un número de teléfono, un término de búsqueda, una campaña llamada spring+summer - tiene que escribirse %2B. Dejado tal cual en una cadena de consulta se convierte en un espacio, y te pasarás una tarde preguntándote por qué el número en tu CRM perdió su código de país.
| Carácter | Codificado | Por qué importa |
|---|---|---|
| space | %20 o + | + solo dentro de una cadena de consulta, %20 en cualquier otro lugar |
& | %26 | Sin codificar, la lista de parámetros termina ahí |
? | %3F | Sin codificar, todo lo que va después se convierte en la consulta |
# | %23 | Sin codificar, el resto nunca llega al servidor |
+ | %2B | Sin codificar en una consulta, llega como un espacio |
% | %25 | Sin codificar, los siguientes dos caracteres se comen |
La fila de # merece una nota, porque es la que produce el informe de error más confuso. Un fragmento nunca se envía al servidor. Pon un # sin codificar en un destino de redirección y el servidor ve una URL truncada mientras que la barra de direcciones del navegador sigue pareciendo correcta, así que la persona que lo reporta jura que el enlace funciona bien.
Si construyes URLs de campaña a mano más que ocasionalmente, para: nuestro generador de UTM codifica cada valor mientras escribes, y convenciones de nomenclatura UTM explica cómo elegir valores que no necesiten codificación desde el principio. Acorta el resultado en tu propio dominio y el lío codificado deja de ser algo que nadie tiene que mirar.
Doble codificación, y cómo detectarla
La doble codificación es lo que pasa cuando un valor atraviesa dos capas que cada una hace su trabajo. El propio signo de porcentaje es un carácter que necesita escaparse, así que %20 se convierte en %2520, y %2520 se convierte en %252520.
Los síntomas son reconocibles una vez que los has visto. Un título de página que muestra spring%20sale a un visitante real. Un parámetro que llega a la analítica con secuencias de escape visibles. Una redirección que funciona en el primer salto y falla en el segundo. La causa es casi siempre una llamada de codificación envuelta alrededor de un valor que llegó ya codificado, a menudo porque salió de una base de datos que almacenaba la forma codificada.
La solución es decidir qué capa es propietaria de la codificación y dejar que las demás no la toquen. Decodifica una vez cuando lees un valor, codifica una vez cuando lo escribes en una URL, y nunca hagas las dos cosas en la misma función.
Dónde muerde esto en la práctica
Tres lugares, en el orden en que probablemente te los encontrarás.
Parámetros de seguimiento. Un valor de campaña con un ampersand sin codificar trunca la lista de parámetros, así que la sesión llega a tu analítica como tráfico directo y la campaña no recibe ningún crédito. Nada da error. Los parámetros UTM no aparecen en GA4 cubre el diagnóstico desde el lado de los informes, y los navegadores eliminan los parámetros UTM cubre la otra razón por la que un parámetro puede desaparecer entre el clic y la página.
Redirecciones. Las reglas del servidor vuelven a codificar de forma incoherente, y que una cadena de consulta sobreviva o no depende de la directiva que usaste. Una redirección 301 en .htaccess tiene la tabla completa para Apache; la versión corta es que una regla que sustituye la cadena de consulta descartará la tuya en silencio.
Códigos QR. La codificación aumenta la longitud de la carga útil, y la longitud de la carga útil decide cuán denso es el código impreso. Cada espacio cuesta tres caracteres en lugar de uno, cada letra acentuada seis. Una URL de seguimiento con un par de nombres de campaña codificados puede subir un código una versión o dos, lo que es una diferencia real al tamaño de una tarjeta de visita - el código QR no escanea incluye la longitud de la carga útil entre las cuatro causas exactamente por esta razón. Codificar un enlace corto en lugar de la URL completa es la solución más económica disponible.
Comprueba qué lleva realmente un enlace
Dos comandos resuelven casi cualquier discusión. El primero muestra lo que recibe el servidor tras una redirección:
curl -sI 'https://example.com/spring?utm_campaign=spring%20sale' | grep -i '^location'
El segundo construye la codificación por ti en lugar de confiar en tus dedos, lo cual es útil cuando un valor contiene varios infractores a la vez:
curl -G --data-urlencode 'utm_campaign=spring & summer sale' \
--data-urlencode 'utm_source=flyer' \
-o /dev/null -w '%{url_effective}\n' https://example.com/spring
Lee la salida como datos, no como decoración. Si ves %2520 tienes un problema de doble codificación, si ves un valor que termina antes de tiempo tienes un separador sin codificar, y si ves %3A%2F%2F al principio codificaste la URL entera. Nuestro comprobador de enlaces hace la mitad de la redirección en un navegador si prefieres no abrir una terminal.
El hábito que merece la pena crear es mirar la URL final una vez, a simple vista, antes de que salga una campaña. Los errores de codificación son invisibles en un navegador y obvios en una terminal, y te cuestan atribución en lugar de tiempo de actividad, que es la razón por la que sobreviven tanto tiempo.
Lee la serie central
Este artículo pertenece al clúster de ingeniería. Para el lado de la redirección, tipos de redirecciones cubre todos los códigos de estado y los métodos del lado del cliente, y cómo funcionan los acortadores de URL cubre qué pasa entre el clic y la página.
Relacionados en el blog
- Parámetros UTM explicados, con un esquema de nomenclatura que sobrevive
- ¿Los parámetros UTM no aparecen en GA4? Aquí tienes el porqué
- Una redirección 301 en .htaccess: reglas, orden, cadenas de consulta
- Cómo acortar una URL en Python con la librería requests
- ¿El código QR no escanea? Cuatro causas y cómo solucionarlas
Preguntas frecuentes
¿Qué es la codificación de URL?
Sustituir un carácter por un signo de porcentaje seguido de su valor de byte en hexadecimal, de modo que el carácter no se pueda confundir con sintaxis de la URL. Un espacio se convierte en %20, un ampersand se convierte en %26, un signo de interrogación se convierte en %3F. El mecanismo está definido en RFC 3986 y también se llama percent-encoding.
¿Qué caracteres deben codificarse en la URL?
Todo lo que quede fuera del conjunto no reservado, que RFC 3986 define como letras, dígitos, y los cuatro caracteres guion, punto, guion bajo y tilde. Todo lo demás es o bien puntuación reservada que lleva significado estructural, o un byte fuera de ASCII, y ambos deben codificarse con el signo de porcentaje cuando aparecen dentro de un valor en lugar de como sintaxis.
¿Debo codificar la URL entera o solo partes de ella?
Solo las partes. Pasar una URL completa por un codificador convierte https://example.com en https%3A%2F%2Fexample.com, que ya no es una URL en absoluto. Codifica cada valor de parámetro de consulta y cada segmento de ruta por separado, y deja en paz el esquema, el host y los separadores.
¿Un espacio es %20 o un signo más?
Ambos, en lugares distintos. En una ruta y en una URI genérica, un espacio es %20. En una cadena de consulta construida como la construyen los formularios HTML, un espacio es un signo más, porque eso es lo que especifica la serialización application/x-www-form-urlencoded. Un signo más literal dentro de un valor de consulta, por tanto, tiene que escribirse %2B o se leerá como un espacio.
¿Qué es la doble codificación?
Codificar algo que ya estaba codificado, de modo que %20 se convierte en %2520 porque el propio signo de porcentaje se escapa a %25. El síntoma es una página que muestra un %20 literal en su texto o un parámetro que llega con secuencias de escape visibles. Casi siempre es un valor que pasa por dos capas que cada una lo codificó, con la mejor intención.
¿Por qué los caracteres codificados hacen que un código QR sea más difícil de escanear?
Porque cada uno cuesta tres caracteres en lugar de uno. Un espacio es un carácter de intención y tres de carga útil, así que un puñado de ellos puede subir el código una versión o dos, lo que significa más módulos en la misma área impresa. Codificar una URL de seguimiento larga en un QR es una de las formas más rápidas de crear un código que solo se escanea de cerca.
Prueba Elido
Pega una URL, obtén un enlace corto
Sin registro. El enlace vive 30 días. Crea una cuenta para conservarlo.
Gratis, sin registro · 2 por día