ToolPal
Cables de red e infraestructura de servidores

Anatomía de una URL: desglosa cualquier URL en sus componentes al instante

📷 Jordan Harrison / Pexels

Anatomía de una URL: desglosa cualquier URL en sus componentes al instante

Protocolo, nombre de host, puerto, ruta, parámetros de consulta, fragmento — entiende cada parte de una URL y analízalas con nuestra herramienta gratuita en línea.

DPor Daniel Park30 de marzo de 202614 min de lectura

Las URL son engañosamente simples

Cada desarrollador trabaja con URL todos los días. Las copias, las pegas, las registras, las depuras — y la mayor parte del tiempo, puedes mirar una y saber aproximadamente a qué apunta. Es fácil asumir que dominas las URL.

Luego un día te quedas mirando algo como esto:

https://user:p%40ss@api.example.com:8443/v2/search?q=hello+world&filter%5Bstatus%5D=active&sort=desc#results

...y de repente el análisis de URL ya no parece tan trivial.

Ahí es donde entra un analizador de URL adecuado. Ya sea que uses las DevTools del navegador, una herramienta CLI, un script o algo como toolboxhubs.com/en/tools/url-parser, tener una forma de descomponer una URL en sus partes individuales ahorra mucho tiempo de escrutinio.

Esta guía recorre cada componente de una URL, cubre los escenarios del mundo real donde el análisis importa, y profundiza en los casos extremos que te sorprenderán si no los esperas.


Anatomía de una URL

Usemos esta URL como ejemplo a lo largo del artículo:

https://admin:secret@api.example.com:8080/v1/users/42?format=json&include=profile#contact

Cubre la mayoría de los componentes que nos interesan. Revisemos cada uno.

Protocolo (Esquema)

https://

El protocolo (también llamado esquema) define cómo se debe obtener el recurso. https significa HTTP con cifrado TLS. También encontrarás http, ftp, ws (WebSocket), wss (WebSocket seguro), mailto, file, y muchos esquemas personalizados como myapp:// en los deep links móviles.

Vale la pena notar: el separador :// es parte de la sintaxis, no del esquema en sí. El esquema es solo https, no https://. Esto confunde a la gente al hacer análisis manual de cadenas.

Nombre de usuario y contraseña

admin:secret@

Son credenciales incrustadas — bastante raras en las aplicaciones web modernas pero aún muy usadas en herramientas internas, sistemas legacy y algunas configuraciones de API. Se sitúan entre el :// y el nombre de host, separadas por dos puntos, con un @ al final.

Casi nunca querrás registrar URL con credenciales intactas. Si estás construyendo algo que toca la autenticación y estás registrando URL completas, este es un lugar para limpiar. La mayoría de las bibliotecas de análisis de URL te dan username y password como propiedades separadas para que puedas eliminarlos antes de persistirlos.

Nombre de host

api.example.com

El nombre de host se resuelve a través de DNS. Puede ser un nombre de dominio, un subdominio, una dirección IP desnuda, o — aquí está el caso interesante — una dirección IPv6 como [2001:db8::1]. Los corchetes alrededor de IPv6 son requeridos por la especificación URL, lo que significa que la división ingenua en : fallará completamente al encontrar un host IPv6. Más sobre casos extremos más adelante.

Puerto

:8080

El puerto es opcional. Cuando no se especifica, el navegador (o cliente) asume el predeterminado para el esquema — puerto 80 para http, puerto 443 para https. Cuando especificas explícitamente el puerto predeterminado (como https://example.com:443/), un buen analizador de URL generalmente lo normalizará o al menos te informará que es redundante.

El puerto 8080 y 3000 son clásicos de los desarrolladores. Verás 8443 para HTTPS de desarrollo. Si estás depurando un entorno de staging o local y algo no se resuelve, vale la pena verificar si el puerto se está leyendo correctamente o se está perdiendo en algún lugar.

Nombre de ruta

/v1/users/42

La ruta es la parte después del host (y puerto) hasta el ? o #. Identifica el recurso específico en el servidor. Para las API REST, la ruta a menudo codifica el tipo de recurso e ID — /v1/users/42 dice: API versión 1, colección de usuarios, registro con ID 42.

Las rutas pueden contener caracteres codificados en porcentaje. /search/hello%20world y /search/hello world (con un espacio literal) son técnicamente diferentes — aunque en la práctica a menudo se tratan igual. Si estás comparando rutas, asegúrate de comparar valores decodificados de manera consistente.

Cadena de consulta

?format=json&include=profile

La cadena de consulta es probablemente la parte de una URL más frecuentemente analizada en el trabajo diario. Comienza con ? y contiene pares clave-valor separados por &. Cada par es key=value.

Los valores pueden ser:

  • Cadenas simples: ?name=John
  • Codificados en URL: ?q=hello%20world (espacio codificado como %20)
  • Usando + para espacios (codificación de formulario): ?q=hello+world
  • Arrays (no estándar pero común): ?ids[]=1&ids[]=2 o ?ids=1&ids=2
  • Objetos anidados (estilo PHP): ?filter[status]=active

El último ejemplo — filter%5Bstatus%5D=active — es filter[status]=active con los corchetes codificados. Un analizador de URL que solo hace división básica de clave-valor te devolverá filter%5Bstatus%5D como clave, y tendrás que decodificarlo por separado. Algo a tener en cuenta.

Fragmento (Hash)

#contact

El fragmento es todo lo que viene después del #. Críticamente, el fragmento nunca se envía al servidor. Lo maneja completamente el navegador en el lado del cliente. Esto significa que si intentas averiguar qué fragmento tenía un usuario en su URL desde los registros del servidor — no puedes. El servidor nunca lo ve.

Los fragmentos se usan para la navegación dentro de la página (saltar a un elemento ancla), el enrutamiento de aplicaciones de una sola página, y a veces como almacén de estado simple. También se usan en los flujos implícitos de OAuth y algunos patrones de paso de tokens, lo que recuerda que los fragmentos pueden contener datos sensibles incluso si se sienten "invisibles".


Analizar URL en código

JavaScript — La API URL integrada

JavaScript moderno tiene un constructor URL integrado sólido que maneja el análisis muy bien. No se necesita ninguna biblioteca.

const raw = 'https://admin:secret@api.example.com:8080/v1/users/42?format=json&include=profile#contact';

const url = new URL(raw);

console.log(url.protocol);  // 'https:'
console.log(url.username);  // 'admin'
console.log(url.password);  // 'secret'
console.log(url.hostname);  // 'api.example.com'
console.log(url.port);      // '8080'
console.log(url.pathname);  // '/v1/users/42'
console.log(url.search);    // '?format=json&include=profile'
console.log(url.hash);      // '#contact'

// Params de consulta como objeto iterable
const params = url.searchParams;
console.log(params.get('format'));   // 'json'
console.log(params.get('include'));  // 'profile'

// Iterar sobre todos los params
for (const [key, value] of params) {
  console.log(`${key}: ${value}`);
}

La propiedad searchParams es un objeto URLSearchParams — maneja la codificación y decodificación automáticamente. Entonces si tu URL tiene ?q=hello+world, params.get('q') te da 'hello world' con el más decodificado. Ese es el comportamiento que quieres.

Un inconveniente: el constructor URL lanza un TypeError si la entrada no es una URL absoluta válida. Si estás analizando entradas proporcionadas por el usuario, envuélvelo en un try/catch:

function parseURL(input) {
  try {
    return new URL(input);
  } catch {
    return null;
  }
}

Para URL relativas, necesitas pasar una base:

const url = new URL('/v1/users/42', 'https://api.example.com');
// Se resuelve en: https://api.example.com/v1/users/42

Python — urllib.parse

La biblioteca estándar de Python tiene un análisis de URL sólido en urllib.parse:

from urllib.parse import urlparse, parse_qs, urlencode, quote, unquote

raw = 'https://admin:secret@api.example.com:8080/v1/users/42?format=json&include=profile#contact'

parsed = urlparse(raw)

print(parsed.scheme)    # 'https'
print(parsed.netloc)    # 'admin:secret@api.example.com:8080'
print(parsed.hostname)  # 'api.example.com'
print(parsed.port)      # 8080  (entero, no cadena)
print(parsed.username)  # 'admin'
print(parsed.password)  # 'secret'
print(parsed.path)      # '/v1/users/42'
print(parsed.query)     # 'format=json&include=profile'
print(parsed.fragment)  # 'contact'

# Analizar cadena de consulta en un dict
params = parse_qs(parsed.query)
print(params)  # {'format': ['json'], 'include': ['profile']}

# parse_qs devuelve listas para cada valor (soporta parámetros de múltiples valores)
# Usar parse_qs(qs, keep_blank_values=True) para preservar valores vacíos

Nota que parse_qs devuelve listas, no valores únicos — porque un parámetro de consulta puede aparecer varias veces. Entonces params['format'] es ['json'], no 'json'. Si quieres valores únicos, usa parse_qs con strict_parsing=False e indexa con [0], o usa urllib.parse.parse_qsl que devuelve una lista de tuplas.


Casos de uso comunes

Depurar llamadas a API

Esta es probablemente la razón principal por la que uso un analizador de URL. Obtienes un error 400, miras la URL de la solicitud y necesitas averiguar qué se está enviando realmente.

Toma una URL de la API de GitHub como:

https://api.github.com/repos/facebook/react/commits?sha=main&per_page=50&page=3&since=2024-01-01T00%3A00%3A00Z

Al analizarla, puedes ver inmediatamente: está recuperando commits del repositorio facebook/react en la rama main, 50 por página, página 3, desde el 1 de enero de 2024 — con el valor since codificado en porcentaje (%3A es :). Si estás construyendo esta URL programáticamente y no se comporta correctamente, ver todos los valores decodificados de una vez hace que los problemas sean obvios rápidamente.

Extraer parámetros UTM

Los equipos de marketing adoran los parámetros UTM. Encontrarás URL como esta en todos los paneles de análisis:

https://example.com/landing?utm_source=newsletter&utm_medium=email&utm_campaign=spring_sale_2026&utm_content=cta_button

Si necesitas extraerlos para informes, atribución o pasarlos a través de un embudo:

const url = new URL(window.location.href);
const utm = {};

for (const [key, value] of url.searchParams) {
  if (key.startsWith('utm_')) {
    utm[key] = value;
  }
}

console.log(utm);
// { utm_source: 'newsletter', utm_medium: 'email', utm_campaign: 'spring_sale_2026', utm_content: 'cta_button' }

Limpio y simple. No se necesita regex.

Rastrear cadenas de redirección

Si alguna vez has tenido que depurar un bucle de redirección o rastrear a dónde va realmente una URL acortada, terminarás mirando una serie de valores del encabezado Location. Cada uno puede ser absoluto o relativo. Un analizador de URL te ayuda a resolver redirecciones relativas contra la base actual para poder seguir la cadena correctamente.

import urllib.request
from urllib.parse import urljoin

def trace_redirects(start_url, max_hops=10):
    url = start_url
    chain = [url]

    for _ in range(max_hops):
        try:
            req = urllib.request.Request(url, method='HEAD')
            # No seguir redirecciones automáticamente
            opener = urllib.request.build_opener(
                urllib.request.HTTPRedirectHandler()
            )
            resp = opener.open(req)
            break  # Destino final alcanzado
        except urllib.error.HTTPError as e:
            if e.code in (301, 302, 303, 307, 308):
                location = e.headers.get('Location', '')
                url = urljoin(url, location)  # Maneja redirecciones relativas
                chain.append(url)
            else:
                break

    return chain

La llamada a urljoin es lo que hace funcionar las redirecciones relativas — si un servidor devuelve /new-path como Location, urljoin lo resuelve contra la base de la URL actual.


Casos extremos y trampas

Mencioné antes que el análisis de URL parece simple hasta que no lo es. Aquí están las situaciones específicas que me han causado problemas a mí o a un compañero de equipo en algún momento.

Hosts IPv6

Una dirección IPv6 en una URL se ve así:

http://[2001:db8::1]:8080/path

Los corchetes son obligatorios. Si intentas dividir en : para extraer el host y el puerto, obtendrás resultados incorrectos. El constructor URL en JavaScript maneja esto correctamente — url.hostname te da 2001:db8::1 (sin corchetes), y url.port te da 8080. El urlparse de Python también lo maneja. Pero si alguna vez te ves tentado a hacer división manual de cadenas, IPv6 es una de las razones para no hacerlo.

Parámetros de consulta codificados en porcentaje

Esto es sutil. Si la clave de un parámetro de consulta está codificada en porcentaje — como filter%5Bstatus%5D para filter[status] — diferentes analizadores lo tratan de manera diferente. El URLSearchParams de JavaScript lo decodificará por ti. El parse_qs de Python también decodifica por defecto. Pero no todas las bibliotecas hacen esto de manera consistente, especialmente las más antiguas.

Siempre verifica si tu biblioteca de análisis decodifica tanto las claves como los valores, no solo los valores.

Protocolo faltante

Una URL como //example.com/path es una URL relativa al protocolo — hereda el protocolo del contexto de la página actual. El constructor URL la rechazará como inválida sin una base. Y algo como example.com/path sin ningún esquema técnicamente no es una URL; es una ruta relativa que parece un dominio.

new URL('//example.com/path');
// TypeError: Failed to construct 'URL': Invalid URL

new URL('//example.com/path', 'https://current-page.com');
// Funciona: https://example.com/path

Si estás construyendo una herramienta que acepta entrada del usuario, probablemente querrás detectar protocolos faltantes y ya sea pedir al usuario o asumir https:// como alternativa.

URL vs URI

Técnicamente, las URL son un subconjunto de los URI. Un URI (Identificador Uniforme de Recursos) identifica un recurso; una URL (Localizador Uniforme de Recursos) también describe cómo localizarlo (es decir, incluye un esquema para recuperarlo). En la práctica, la mayoría de los desarrolladores usan "URL" para todo. Pero si estás analizando cosas como urn:isbn:0451450523 o mailto:user@example.com, ten en cuenta que los analizadores de URL pueden manejarlos de manera inconsistente, ya que no siguen el patrón esquema://autoridad/ruta.

El fragmento es solo del lado del cliente

Vale la pena repetirlo porque importa en contextos de seguridad: #tokens, #access_token=abc123, ese tipo de cosas — el servidor nunca las ve. Si alguien pasa datos sensibles en un fragmento, no aparecerán en los registros del servidor, pero estarán en el historial del navegador y potencialmente visibles para el JavaScript del lado del cliente (incluidos los scripts de terceros).


Analizador de URL vs división manual de cadenas — Cuándo usar cuál

Hay cierto tipo de desarrollador (yo he sido ese desarrollador) que usa split('?') y split('&') en lugar de un analizador de URL real. A veces funciona bien. Para un script desechable rápido con entrada bien controlada, probablemente está bien.

Pero aquí está la regla honesta: si la URL podría venir de entrada del usuario, una API de terceros o un sistema que no controlas, usa un analizador real. Los casos extremos — codificación, IPv6, puertos faltantes, credenciales incrustadas, URL relativas — eventualmente aparecerán, y la división manual producirá resultados incorrectos en silencio en lugar de fallar ruidosamente.

La API URL integrada en JavaScript y urllib.parse en Python son suficientes para casi todos los casos de uso. Recurre a una biblioteca solo si necesitas normalización de URL, codificación IDNA para dominios internacionales, o manejo especial de esquemas no estándar.

Para la inspección rápida de URL de una sola vez, toolboxhubs.com/en/tools/url-parser es útil cuando solo quieres pegar una URL y ver inmediatamente todos los componentes — especialmente útil al depurar una URL que tiene codificación anidada.


Un ejemplo del mundo real: Analizar una URL de la API de GitHub

Resumamos con algo concreto. Estás construyendo un script que llama a la API de GitHub y quieres registrar las solicitudes sin filtrar tokens. Una URL típica de la API de GitHub autenticada podría ser:

https://github-token:ghp_REDACTED@api.github.com/repos/my-org/my-repo/pulls?state=open&per_page=100&page=1

Así es como lo manejarías en JavaScript:

function sanitizeGitHubURL(rawUrl) {
  let url;
  try {
    url = new URL(rawUrl);
  } catch {
    return '[invalid URL]';
  }

  // Eliminar credenciales incrustadas
  url.username = '';
  url.password = '';

  // Todavía puedes extraer información útil
  const info = {
    host: url.hostname,
    path: url.pathname,
    params: Object.fromEntries(url.searchParams),
    sanitized: url.toString(),
  };

  return info;
}

const result = sanitizeGitHubURL(
  'https://github-token:ghp_abc123@api.github.com/repos/my-org/my-repo/pulls?state=open&per_page=100&page=1'
);

console.log(result);
// {
//   host: 'api.github.com',
//   path: '/repos/my-org/my-repo/pulls',
//   params: { state: 'open', per_page: '100', page: '1' },
//   sanitized: 'https://api.github.com/repos/my-org/my-repo/pulls?state=open&per_page=100&page=1'
// }

Establecer url.username = '' y url.password = '' y luego llamar a url.toString() te da una URL limpia sin credenciales. Mucho más seguro para registrar.


Conclusión

Las URL son una de esas cosas que están en tu campo periférico como desarrollador — siempre presentes, generalmente entendidas, ocasionalmente frustrantes. Una vez que has encontrado un bug por doble codificación en porcentaje, o has pasado diez minutos averiguando por qué un parámetro de consulta tiene corchetes en la clave, dejas de tratar las URL como cadenas simples.

Los puntos clave:

  • Usa un analizador real (API URL de JavaScript, Python urllib.parse) en lugar de división de cadenas para cualquier cosa proporcionada por el usuario o de fuentes externas
  • Recuerda que los fragmentos son solo del lado del cliente — el servidor nunca los ve
  • Las URL relativas requieren una base para resolverse correctamente
  • La codificación en porcentaje se aplica tanto a las claves como a los valores en las cadenas de consulta
  • Los hosts IPv6 rompen la división ingenua en dos puntos
  • URL y URI son técnicamente diferentes, aunque casi todo el mundo usa URL para ambos

Para inspección y depuración rápidas, una herramienta visual de análisis de URL ahorra tiempo. Para el código de producción, los analizadores de la biblioteca estándar son sólidos y bien probados — no hay necesidad de un paquete de terceros a menos que tengas una necesidad específica.

Una vez que te familiarices con la estructura de URL, mucha depuración web se vuelve más clara: puedes detectar redirecciones mal configuradas, atrapar credenciales filtradas, rastrear qué datos está enviando realmente una llamada a la API, y razonar sobre tus propias URL con más precisión. Es una de esas habilidades de bajo esfuerzo y alto impacto.

Preguntas Frecuentes

D

Sobre el autor

Daniel Park

Senior frontend engineer based in Seoul. Seven years of experience building web applications at Korean SaaS companies, with a focus on developer tooling, web performance, and privacy-first architecture. Open-source contributor to the JavaScript ecosystem and founder of ToolPal.

Saber más

Compartir

XLinkedIn

Publicaciones relacionadas