Qu'est-ce que l'analyse d'URL ?
L'analyse d'URL est le processus qui consiste à décomposer un Localisateur de Ressource Uniforme en ses composants individuels : protocole (schéma), hostname, port, pathname, paramètres de requête et identificateur de fragment. Toute URL suit une structure définie par RFC 3986 et le standard WHATWG URL. Un analyseur d'URL lit la chaîne brute, identifie chaque segment grâce à ses caractères délimiteurs (://, :, /, ?, #, &, =) et les retourne sous forme de champs séparés et accessibles.
Les navigateurs analysent les URL à chaque fois que vous saisissez une adresse ou cliquez sur un lien. Le constructeur JavaScript URL, le module urllib.parse de Python et le package net/url de Go implémentent tous des analyseurs qui suivent les mêmes règles structurelles. Analyser une URL est l'opération inverse de l'encodage d'URL : au lieu de transformer des caractères pour un transport sécurisé, vous décomposez une URL déjà formée en les parties qui la constituent.
Une URL typique comme https://api.example.com:8080/v1/users?page=2&limit=10#section contient six composants distincts. Les caractères délimiteurs — ://, :, /, ?, &, = et # — sont ce qui rend l'analyse déterministe : chacun signale une frontière et permet à l'analyseur d'extraire les champs sans ambiguïté.
Pourquoi utiliser un analyseur d'URL en ligne ?
Décomposer une URL manuellement à l'œil est source d'erreurs, surtout lorsque la chaîne contient des caractères encodés, plusieurs paramètres de requête ou des ports non standard. Cet outil analyse l'URL en utilisant le même algorithme conforme au standard WHATWG que les navigateurs, et affiche chaque composant dans un tableau clair et copiable.
Cas d'utilisation de l'analyseur d'URL
Référence des composants d'URL
Le tableau ci-dessous présente chaque propriété retournée par le constructeur JavaScript URL lors de l'analyse d'une URL. Les mêmes composants existent dans le résultat urlparse de Python, la structure url.URL de Go et la sortie parse_url de PHP, bien que les noms de propriétés diffèrent selon les langages.
| Propriété | Exemple | Description |
|---|---|---|
| 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 |
Standard WHATWG URL vs RFC 3986
Deux spécifications définissent comment les URLs doivent être analysées. Elles s'accordent sur la structure de base mais divergent dans les cas limites — et cette divergence est généralement la cause lorsque votre navigateur traite une URL différemment de votre serveur.
En pratique, la plupart des différences apparaissent lors de l'analyse d'URLs avec des noms de domaine internationaux (IDN), des schémas manquants ou des caractères inhabituels. L'analyseur WHATWG convertit automatiquement les hostnames IDN en Punycode, tandis que les analyseurs stricts RFC 3986 peuvent les rejeter. Si vous collez une URL dans cet outil et obtenez des résultats différents de ceux de votre code côté serveur, la différence WHATWG vs RFC 3986 en est très probablement la cause.
Exemples de code
Chaque langage majeur dispose d'un analyseur d'URL intégré. Les exemples ci-dessous analysent la même URL et en extraient les composants. Notez les légères différences de nommage selon les langages : Python utilise scheme au lieu de protocol, et Go expose RawQuery au lieu 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"