ToolPal
Câbles réseau et infrastructure serveur

Anatomie d'une URL : décomposer instantanément n'importe quelle URL en ses composants

📷 Jordan Harrison / Pexels

Anatomie d'une URL : décomposer instantanément n'importe quelle URL en ses composants

Protocole, nom d'hôte, port, chemin, paramètres de requête, fragment — comprendre chaque élément d'une URL et les analyser avec notre outil gratuit en ligne.

DPar Daniel Park30 mars 202614 min de lecture

Les URL sont trompeusement simples

Chaque développeur travaille avec des URL tous les jours. On les copie, on les colle, on les enregistre, on les débogue — et la plupart du temps, on peut regarder une URL et deviner à peu près ce qu'elle pointe. Il est donc facile de penser qu'on maîtrise les URL.

Puis un jour on fixe quelque chose comme ça :

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

...et soudainement l'analyse d'URL ne semble plus si triviale.

C'est là qu'un vrai analyseur d'URL entre en jeu. Que vous utilisiez les DevTools du navigateur, un outil CLI, un script ou quelque chose comme toolboxhubs.com/en/tools/url-parser, avoir un moyen de décomposer une URL en ses parties individuelles fait gagner beaucoup de temps.

Ce guide passe en revue chaque composant d'une URL, couvre les scénarios réels où l'analyse est importante, et traite des cas limites qui vous surprendront si vous n'y êtes pas préparé.


Anatomie d'une URL

Utilisons cette URL comme exemple tout au long de l'article :

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

Elle couvre la plupart des composants qui nous intéressent. Passons-les en revue un par un.

Protocole (Schéma)

https://

Le protocole (aussi appelé schéma) définit comment la ressource doit être récupérée. https signifie HTTP chiffré TLS. Vous rencontrerez aussi http, ftp, ws (WebSocket), wss (WebSocket sécurisé), mailto, file, et de nombreux schémas personnalisés comme myapp:// dans les deep links mobiles.

À noter : le séparateur :// fait partie de la syntaxe, pas du schéma lui-même. Le schéma est juste https, pas https://. Cela perturbe les gens lors de l'analyse manuelle de chaînes.

Nom d'utilisateur et mot de passe

admin:secret@

Ce sont des identifiants intégrés — assez rares dans les applications Web modernes mais encore très utilisés dans les outils internes, les systèmes legacy et certaines configurations API. Ils se trouvent entre :// et le nom d'hôte, séparés par un deux-points, avec un @ à la fin.

On ne veut presque jamais enregistrer des URL avec des identifiants intacts. Si vous construisez quelque chose qui touche à l'authentification et que vous enregistrez des URL complètes, c'est là qu'il faut nettoyer. La plupart des bibliothèques d'analyse d'URL vous donnent username et password comme propriétés séparées pour que vous puissiez les supprimer avant de les persister.

Nom d'hôte

api.example.com

Le nom d'hôte est résolu via DNS. Il peut s'agir d'un nom de domaine, d'un sous-domaine, d'une adresse IP nue, ou — voilà le cas intéressant — d'une adresse IPv6 comme [2001:db8::1]. Les crochets autour d'IPv6 sont requis par la spécification URL, ce qui signifie que la division naïve sur : échouera complètement en rencontrant un hôte IPv6. Plus de détails sur les cas limites plus tard.

Port

:8080

Le port est optionnel. Quand il n'est pas spécifié, le navigateur (ou le client) suppose la valeur par défaut du schéma — port 80 pour http, port 443 pour https. Quand vous spécifiez explicitement le port par défaut (comme https://example.com:443/), un bon analyseur d'URL le normalisera généralement ou vous informera qu'il est redondant.

Le port 8080 et 3000 sont des classiques du développeur. Vous verrez 8443 pour le HTTPS de développement. Si vous déboguez un environnement de staging ou local et que quelque chose ne se résout pas, cela vaut la peine de vérifier si le port est correctement récupéré ou avalé quelque part.

Chemin d'accès

/v1/users/42

Le chemin est la partie après l'hôte (et le port) jusqu'au ? ou #. Il identifie la ressource spécifique sur le serveur. Pour les API REST, le chemin encode souvent le type de ressource et l'ID — /v1/users/42 signifie : API version 1, collection users, enregistrement avec l'ID 42.

Les chemins peuvent contenir des caractères encodés en pourcentage. /search/hello%20world et /search/hello world (avec un vrai espace) sont techniquement différents — même si en pratique ils sont souvent traités de la même façon. Si vous comparez des chemins, assurez-vous de comparer des valeurs décodées de manière cohérente.

Chaîne de requête

?format=json&include=profile

La chaîne de requête est probablement la partie d'une URL la plus fréquemment analysée dans le travail quotidien. Elle commence par ? et contient des paires clé-valeur séparées par &. Chaque paire est key=value.

Les valeurs peuvent être :

  • Des chaînes simples : ?name=John
  • Encodées en URL : ?q=hello%20world (espace encodé en %20)
  • Avec + pour les espaces (encodage de formulaire) : ?q=hello+world
  • Des tableaux (non standard mais courant) : ?ids[]=1&ids[]=2 ou ?ids=1&ids=2
  • Des objets imbriqués (style PHP) : ?filter[status]=active

Ce dernier exemple — filter%5Bstatus%5D=active — est filter[status]=active avec les crochets encodés. Un analyseur d'URL qui ne fait que le fractionnement basique clé-valeur vous retournera filter%5Bstatus%5D comme clé, et vous devrez le décoder séparément. C'est à surveiller.

Fragment (Hash)

#contact

Le fragment est tout ce qui vient après le #. Critiquement, le fragment n'est jamais envoyé au serveur. Il est entièrement géré côté client par le navigateur. Cela signifie que si vous essayez de déterminer quel fragment un utilisateur avait dans son URL à partir des logs serveur — vous ne pouvez pas. Le serveur ne le voit jamais.

Les fragments sont utilisés pour la navigation interne à la page (saut vers un élément ancre), le routage des applications à page unique, et parfois comme stockage d'état simple. Ils sont aussi utilisés dans les flux implicites OAuth et certains schémas de passage de tokens, ce qui rappelle que les fragments peuvent contenir des données sensibles même s'ils semblent "invisibles".


Analyser des URL dans le code

JavaScript — L'API URL intégrée

JavaScript moderne a un constructeur URL intégré solide qui gère très bien l'analyse. Pas besoin de bibliothèque.

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 requête comme objet itérable
const params = url.searchParams;
console.log(params.get('format'));   // 'json'
console.log(params.get('include'));  // 'profile'

// Itérer sur tous les params
for (const [key, value] of params) {
  console.log(`${key}: ${value}`);
}

La propriété searchParams est un objet URLSearchParams — il gère automatiquement l'encodage et le décodage. Donc si votre URL a ?q=hello+world, params.get('q') vous donne 'hello world' avec le plus décodé. C'est le comportement souhaité.

Un piège : le constructeur URL lance un TypeError si l'entrée n'est pas une URL absolue valide. Si vous analysez des entrées fournies par des utilisateurs, enveloppez dans un try/catch :

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

Pour les URL relatives, vous devez passer une base :

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

Python — urllib.parse

La bibliothèque standard de Python a une analyse d'URL solide dans 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  (entier, pas une chaîne)
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'

# Analyser la chaîne de requête en dict
params = parse_qs(parsed.query)
print(params)  # {'format': ['json'], 'include': ['profile']}

# parse_qs retourne des listes pour chaque valeur (supporte les params multi-valeurs)
# Utiliser parse_qs(qs, keep_blank_values=True) pour préserver les valeurs vides

Notez que parse_qs retourne des listes, pas des valeurs simples — parce qu'un paramètre de requête peut apparaître plusieurs fois. Donc params['format'] est ['json'], pas 'json'. Si vous voulez des valeurs simples, utilisez parse_qs avec strict_parsing=False et indexez avec [0], ou utilisez urllib.parse.parse_qsl qui retourne une liste de tuples.


Cas d'utilisation courants

Déboguer les appels API

C'est probablement la raison principale pour laquelle j'utilise un analyseur d'URL. Vous obtenez une erreur 400, vous regardez l'URL de la requête et devez comprendre ce qui est réellement envoyé.

Prenons une URL de l'API GitHub :

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

En l'analysant, vous pouvez immédiatement voir : on récupère les commits du dépôt facebook/react sur la branche main, 50 par page, page 3, depuis le 1er janvier 2024 — avec la valeur since encodée en pourcentage (%3A est :). Si vous construisez cette URL par programmation et qu'elle ne se comporte pas correctement, voir toutes les valeurs décodées d'un coup rend les problèmes évidents.

Extraire les paramètres UTM

Les équipes marketing adorent les paramètres UTM. Vous trouverez des URL comme celle-ci partout dans les tableaux de bord d'analytics :

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

Si vous devez les extraire pour le reporting, l'attribution ou les transmettre dans un tunnel :

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' }

Simple et propre. Pas besoin de regex.

Tracer les chaînes de redirection

Si vous avez jamais eu à déboguer une boucle de redirection ou à tracer où va réellement une URL raccourcie, vous vous retrouverez à examiner une série de valeurs d'en-tête Location. Chacune peut être absolue ou relative. Un analyseur d'URL vous aide à résoudre les redirections relatives par rapport à la base actuelle pour pouvoir suivre la chaîne correctement.

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')
            # Ne pas suivre les redirections automatiquement
            opener = urllib.request.build_opener(
                urllib.request.HTTPRedirectHandler()
            )
            resp = opener.open(req)
            break  # Destination finale atteinte
        except urllib.error.HTTPError as e:
            if e.code in (301, 302, 303, 307, 308):
                location = e.headers.get('Location', '')
                url = urljoin(url, location)  # Gère les redirections relatives
                chain.append(url)
            else:
                break

    return chain

L'appel urljoin est ce qui fait fonctionner les redirections relatives — si un serveur retourne /new-path comme Location, urljoin le résout par rapport à la base de l'URL actuelle.


Cas limites et pièges

J'ai mentionné plus tôt que l'analyse d'URL semble simple jusqu'à ce que ce ne soit plus le cas. Voici les situations spécifiques qui m'ont causé des problèmes ou à un membre de mon équipe à un moment donné.

Hôtes IPv6

Une adresse IPv6 dans une URL ressemble à ceci :

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

Les crochets sont obligatoires. Si vous essayez de diviser sur : pour extraire l'hôte et le port, vous obtiendrez des résultats incohérents. Le constructeur URL en JavaScript gère cela correctement — url.hostname vous donne 2001:db8::1 (sans crochets), et url.port vous donne 8080. Le urlparse de Python le gère aussi. Mais si vous êtes tenté de faire une division manuelle de chaînes, IPv6 est une des raisons de ne pas le faire.

Paramètres de requête encodés en pourcentage

C'est subtil. Si une clé de paramètre de requête est elle-même encodée en pourcentage — comme filter%5Bstatus%5D pour filter[status] — différents parseurs la traitent différemment. Le URLSearchParams de JavaScript la décodera pour vous. Le parse_qs de Python décode aussi par défaut. Mais toutes les bibliothèques ne font pas cela de manière cohérente, surtout les plus anciennes.

Vérifiez toujours si votre bibliothèque d'analyse décode à la fois les clés et les valeurs, pas seulement les valeurs.

Protocole manquant

Une URL comme //example.com/path est une URL relative au protocole — elle hérite du protocole du contexte de la page actuelle. Le constructeur URL la rejettera comme invalide sans base. Et quelque chose comme example.com/path sans aucun schéma n'est techniquement pas une URL ; c'est un chemin relatif qui ressemble à un domaine.

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

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

Si vous construisez un outil qui accepte des entrées utilisateur, vous voudrez probablement détecter les protocoles manquants et soit demander à l'utilisateur, soit supposer https:// comme solution de repli.

URL vs URI

Techniquement, les URL sont un sous-ensemble des URI. Un URI (Uniform Resource Identifier) identifie une ressource ; un URL (Uniform Resource Locator) décrit aussi comment la localiser (c'est-à-dire inclut un schéma pour la récupérer). En pratique, la plupart des développeurs utilisent "URL" pour tout. Mais si vous analysez des choses comme urn:isbn:0451450523 ou mailto:user@example.com, soyez conscient que les analyseurs d'URL peuvent les gérer de manière incohérente, car ils ne suivent pas le modèle schéma://autorité/chemin.

Le fragment est uniquement côté client

Cela vaut la peine d'être répété car c'est important dans les contextes de sécurité : #tokens, #access_token=abc123, ce genre de choses — le serveur ne les voit jamais. Si quelqu'un passe des données sensibles dans un fragment, elles n'apparaîtront pas dans les logs serveur, mais elles seront dans l'historique du navigateur et potentiellement visibles pour le JavaScript côté client (y compris les scripts tiers).


Analyseur d'URL vs découpage manuel de chaînes — Quand utiliser lequel

Il existe un certain type de développeur (j'ai été ce développeur) qui utilise split('?') et split('&') au lieu d'un vrai analyseur d'URL. Parfois ça marche bien ! Pour un script jetable rapide sur une entrée bien contrôlée, c'est probablement acceptable.

Mais voici la règle de base honnête : si l'URL peut provenir d'une entrée utilisateur, d'une API tierce ou d'un système que vous ne contrôlez pas, utilisez un vrai analyseur. Les cas limites — encodage, IPv6, ports manquants, identifiants intégrés, URL relatives — finiront par apparaître, et le découpage manuel produira silencieusement de mauvais résultats plutôt que d'échouer bruyamment.

L'API URL intégrée en JavaScript et urllib.parse en Python conviennent à presque tous les cas d'utilisation. N'utilisez une bibliothèque que si vous avez besoin de normalisation d'URL, d'encodage IDNA pour les domaines internationaux, ou de gestion spéciale de schémas non standard.

Pour une inspection rapide d'URL ponctuelle, toolboxhubs.com/en/tools/url-parser est utile quand vous voulez simplement coller une URL et voir immédiatement tous les composants — particulièrement pratique pour déboguer une URL avec un encodage imbriqué.


Un exemple concret : Analyser une URL de l'API GitHub

Récapitulons avec quelque chose de concret. Vous construisez un script qui appelle l'API GitHub et voulez enregistrer les requêtes sans fuiter de tokens. Une URL typique de l'API GitHub authentifiée pourrait être :

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

Voici comment vous le géreriez en JavaScript :

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

  // Supprimer les identifiants intégrés
  url.username = '';
  url.password = '';

  // Vous pouvez toujours extraire des infos utiles
  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'
// }

Définir url.username = '' et url.password = '' puis appeler url.toString() vous donne une URL propre sans identifiants. Beaucoup plus sûr pour les logs.


Conclusion

Les URL sont une de ces choses qui restent dans votre champ de vision en tant que développeur — toujours présentes, généralement comprises, parfois frustrantes. Une fois que vous avez rencontré un bug dû à un double-encodage en pourcentage, ou passé dix minutes à comprendre pourquoi un paramètre de requête a des crochets dans la clé, vous arrêtez de traiter les URL comme de simples chaînes.

Les points clés :

  • Utilisez un vrai analyseur (API URL JavaScript, Python urllib.parse) plutôt que le découpage de chaînes pour tout ce qui provient d'utilisateurs ou de sources externes
  • Rappelez-vous que les fragments sont uniquement côté client — le serveur ne les voit jamais
  • Les URL relatives nécessitent une base pour se résoudre correctement
  • L'encodage en pourcentage s'applique aux clés et aux valeurs dans les chaînes de requête
  • Les hôtes IPv6 cassent la division naïve sur les deux-points
  • URL et URI sont techniquement différents, bien que presque tout le monde utilise URL pour les deux

Pour une inspection et un débogage rapides, un outil visuel d'analyse d'URL fait gagner du temps. Pour le code de production, les analyseurs de la bibliothèque standard sont solides et bien testés — pas besoin d'un package tiers sauf si vous avez un besoin spécifique.

Une fois que vous vous êtes familiarisé avec la structure des URL, beaucoup de débogage Web devient plus clair : vous pouvez repérer les redirections mal configurées, détecter les identifiants qui fuient, tracer les données qu'un appel API envoie réellement, et raisonner plus précisément sur vos propres URL. C'est une de ces compétences à faible effort et à fort impact.

Questions Fréquentes

D

À propos de l'auteur

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.

En savoir plus

Partager

XLinkedIn

Articles associés