¿Qué es el análisis de URL?
El análisis de URL es el proceso de descomponer un Localizador de Recursos Uniforme en sus componentes individuales: protocolo (esquema), hostname, puerto, pathname, parámetros de consulta e identificador de fragmento. Toda URL sigue una estructura definida por RFC 3986 y el Estándar de URL WHATWG. Un analizador de URL lee la cadena sin procesar, identifica cada segmento por sus caracteres delimitadores (://, :, /, ?, #, &, =) y los devuelve como campos separados y accesibles.
Los navegadores realizan el análisis de URL cada vez que escribes una dirección o haces clic en un enlace. El constructor URL de JavaScript, el módulo urllib.parse de Python y el paquete net/url de Go implementan analizadores que siguen las mismas reglas estructurales. Analizar una URL es la operación inversa a la codificación de URL: en lugar de transformar caracteres para el transporte seguro, descompones una URL ya formada en las partes que la componen.
Una URL típica como https://api.example.com:8080/v1/users?page=2&limit=10#section contiene seis componentes distintos. Los caracteres delimitadores — ://, :, /, ?, &, =, y # — son los que hacen que el análisis sea determinista: cada uno señala un límite y permite que el analizador extraiga campos sin ambigüedad.
¿Por qué usar un analizador de URL online?
Dividir una URL manualmente a ojo es propenso a errores, especialmente cuando la cadena contiene caracteres codificados, múltiples parámetros de consulta o puertos no estándar. Esta herramienta analiza la URL usando el mismo algoritmo compatible con WHATWG que usan los navegadores y muestra cada componente en una tabla clara y copiable.
Casos de uso del analizador de URL
Referencia de componentes de URL
La tabla muestra cada propiedad devuelta por el constructor URL de JavaScript al analizar una URL. Los mismos componentes existen en el resultado urlparse de Python, la estructura url.URL de Go y la salida de parse_url de PHP, aunque los nombres de las propiedades difieren entre lenguajes.
| Propiedad | Ejemplo | Descripción |
|---|---|---|
| protocol | https: | Scheme including the trailing colon |
| hostname | api.example.com | Domain name or IP address |
| port | 8080 | Port number (empty string if default) |
| pathname | /v1/users | Path starting with / |
| search | ?page=2&limit=10 | Query string including the leading ? |
| hash | #section | Fragment identifier including the leading # |
| origin | https://api.example.com:8080 | protocol + hostname + port |
| host | api.example.com:8080 | hostname + port |
| username | admin | Credentials before @ (rarely used in practice) |
| password | secret | Credentials before @ (avoid in production URLs) |
| href | (full URL) | The complete, serialized URL string |
Estándar URL WHATWG vs RFC 3986
Dos especificaciones definen cómo deben analizarse las URLs. Coinciden en la estructura básica pero divergen en casos límite — y esa divergencia suele ser la causa cuando tu navegador maneja una URL de forma diferente a tu servidor.
En la práctica, la mayoría de las diferencias aparecen al analizar URLs con nombres de dominio internacionales (IDN), esquemas ausentes o caracteres inusuales. El analizador WHATWG convierte automáticamente los hostnames IDN a Punycode, mientras que los analizadores estrictos de RFC 3986 pueden rechazarlos. Si pegas una URL en esta herramienta y ves resultados distintos a los que produce tu código del lado del servidor, la diferencia entre WHATWG y RFC es la causa más probable.
Ejemplos de código
Todos los lenguajes principales tienen un analizador de URL integrado. Los ejemplos a continuación analizan la misma URL y extraen sus componentes. Observa las pequeñas diferencias de nomenclatura entre lenguajes: Python usa scheme en lugar de protocol, y Go expone RawQuery en lugar de search.
const url = new URL('https://api.example.com:8080/v1/users?page=2&limit=10#section')
url.protocol // → "https:"
url.hostname // → "api.example.com"
url.port // → "8080"
url.pathname // → "/v1/users"
url.search // → "?page=2&limit=10"
url.hash // → "#section"
// Iterate over query parameters
for (const [key, value] of url.searchParams) {
console.log(`${key} = ${value}`)
}
// → "page = 2"
// → "limit = 10"
// Modify and re-serialize
url.searchParams.set('page', '3')
url.toString()
// → "https://api.example.com:8080/v1/users?page=3&limit=10#section"from urllib.parse import urlparse, parse_qs
result = urlparse('https://api.example.com:8080/v1/users?page=2&limit=10#section')
result.scheme # → 'https'
result.hostname # → 'api.example.com'
result.port # → 8080
result.path # → '/v1/users'
result.query # → 'page=2&limit=10'
result.fragment # → 'section'
# Parse query string into a dict
params = parse_qs(result.query)
params['page'] # → ['2']
params['limit'] # → ['10']
# Reconstruct with modifications
from urllib.parse import urlencode, urlunparse
new_query = urlencode({'page': '3', 'limit': '10'})
urlunparse(result._replace(query=new_query))
# → 'https://api.example.com:8080/v1/users?page=3&limit=10#section'package main
import (
"fmt"
"net/url"
)
func main() {
u, err := url.Parse("https://api.example.com:8080/v1/users?page=2&limit=10#section")
if err != nil {
panic(err)
}
fmt.Println(u.Scheme) // → "https"
fmt.Println(u.Hostname()) // → "api.example.com"
fmt.Println(u.Port()) // → "8080"
fmt.Println(u.Path) // → "/v1/users"
fmt.Println(u.RawQuery) // → "page=2&limit=10"
fmt.Println(u.Fragment) // → "section"
// Query params as map
q := u.Query()
fmt.Println(q.Get("page")) // → "2"
fmt.Println(q.Get("limit")) // → "10"
}<?php $url = 'https://api.example.com:8080/v1/users?page=2&limit=10#section'; $parts = parse_url($url); $parts['scheme']; // → "https" $parts['host']; // → "api.example.com" $parts['port']; // → 8080 $parts['path']; // → "/v1/users" $parts['query']; // → "page=2&limit=10" $parts['fragment']; // → "section" // Parse query string into an array parse_str($parts['query'], $params); $params['page']; // → "2" $params['limit']; // → "10"