Analyseur & décodeur d'URL, gratuit

Analysez n'importe quelle URL en ses composants · protocole, hôte, port, chemin, paramètres de requête et fragment.

Anatomie d’une URL : six composants, une longue histoire

Une URL est analysée en six parties conceptuelles : scheme://userinfo@host:port/path?query#fragment. Le scheme indique au client quel protocole utiliser (https, http, ftp, mailto, file, data) et est la seule partie toujours présente. La composante userinfo (username:password@) est rare en usage moderne ; les navigateurs la retirent généralement des URL affichées car elle est un vecteur de phishing depuis les années 1990. Le host est l’emplacement réseau, un nom de domaine enregistré, une adresse IP (IPv4 en quadruplet pointé ou IPv6 entre crochets) ou un nom spécial comme localhost. Le port est le port TCP/UDP (80 par défaut pour HTTP, 443 pour HTTPS, etc.) ; si omis, le défaut du scheme s’applique. Le path est la hiérarchie séparée par des barres obliques qui identifie la ressource au sein du host. La query string (tout ce qui suit le ?) porte des paires clé-valeur séparées par &, utilisées pour le filtrage, la pagination, le tracking, la soumission de formulaires. Le fragment (tout ce qui suit #) est la seule partie de l’URL qui n’est jamais envoyée au serveur, elle est traitée entièrement côté client par le navigateur pour défiler jusqu’à une section spécifique ou, dans les single-page apps, pour indiquer l’état de la route.

Le format de la query string a lui-même une bifurcation : ?key=value&key2=value2 traditionnel avec valeurs percent-encodées selon RFC 3986, vs l’ancienne convention form-encoded application/x-www-form-urlencoded+ signifie un espace (à l’origine pour les soumissions de formulaires HTML). La plupart des parsers gèrent les deux, mais la conversion est asymétrique : %20 décode toujours en espace ; + ne décode en espace qu’à l’intérieur d’une query string, jamais dans un path. C’est l’un des bugs de parsing d’URL les plus courants en production.

Une brève histoire de l’URL

L’URL (à l’origine « Universal Document Identifier », puis « Universal Resource Locator ») a été inventée par Tim Berners-Lee entre son mémo « Information Management: A Proposal » de mars 1989 au CERN (celui que son patron Mike Sendall a annoté « Vague but exciting ») et les premières pages web publiquement consultables d’août 1991. La première URL canonique était http://info.cern.ch/hypertext/WWW/TheProject.html, publiée le 6 août 1991. Les discussions de l’IETF de 1992 ont renommé les UDI en URL pour éviter une bataille de vocabulaire. RFC 1738 (« Uniform Resource Locators »), rédigé par Berners-Lee, Masinter et McCahill, a été publié en décembre 1994 comme première syntaxe formelle d’URL. RFC 2396 a suivi en août 1998, généralisant les URL dans le concept plus large d’URI. La spec canonique actuelle est RFC 3986 (« URI Generic Syntax »), publiée en janvier 2005, éditée par Berners-Lee, Roy Fielding et Larry Masinter, un Internet Standard STD 66, le niveau de maturité le plus élevé de l’IETF. RFC 3986 est ce que tout parser d’URL cible nominalement. En pratique, les navigateurs modernes divergent de RFC 3986 dans de nombreux cas limites, raison pour laquelle le WHATWG maintient un URL Living Standard séparé sur url.spec.whatwg.org décrivant ce que les navigateurs font réellement ; la spec WHATWG vise explicitement à rendre obsolètes RFC 3986 et RFC 3987 à terme, et les deux divergent encore sur des points comme le traitement des espaces de tête, les jeux de percent-encoding et la normalisation Unicode.

Caractères non réservés, réservés et percent-encodés

RFC 3986 §2.3 définit les caractères non réservés: les seuls caractères garantis sûrs dans n’importe quelle composante d’URI sans percent-encoding : A-Z, a-z, 0-9, tiret (-), point (.), underscore (_) et tilde (~). 66 caractères au total. Tout le reste est soit un caractère réservé avec une signification structurelle dans une certaine composante (gen-delims (:/?#[]@) et sub-delims (!$&'()*+,;=)) soit « autre » et doit être percent-encodé s’il apparaît dans une URI. Le percent-encoding (RFC 3986 §2.1) prend la séquence d’octets d’un caractère (en UTF-8 sauf si le scheme dit autrement) et remplace chaque octet par %HH où HH est la valeur hex à deux chiffres de l’octet. Ainsi un é encodé en UTF-8 (octets 0xC3 0xA9) devient %C3%A9 ; le mot russe привет devient %D0%BF%D1%80%D0%B8%D0%B2%D0%B5%D1%82: deux octets par caractère, six triplets %XX et 36 caractères percent-encodés d'URL pour six lettres cyrilliques.

Les navigateurs affichent les paths percent-encodés de deux façons : la plupart des navigateurs modernes (Chrome, Firefox, Safari) décodent et rendent les glyphes Unicode originaux dans la barre d’adresse quand l’encodage est de l’UTF-8 valide, mais copient la forme percent-encodée littérale quand l’utilisateur copie l’URL. Les navigateurs plus anciens et de nombreux logs web ne montrent que la forme percent-encodée, c’est pourquoi les « jolies URL Unicode » peuvent être trompeuses : elles ont l’air belles dans la barre d’adresse et laides dans n’importe quel texte où elles sont partagées. RFC 3987 («Internationalized Resource Identifiers», IRI), publiée en janvier 2005, a formalisé les URL Unicode dans leur forme non encodée ; Punycode (RFC 3492, mars 2003) définit comment les noms de domaine internationalisés sont encodés en ASCII pour le DNS, label par label : le label de premier niveau chinois 中国 devient xn--fiqs8s, et donc example.中国 se résout au niveau DNS comme example.xn--fiqs8s. La démonstration canonique est constituée des URL IRI de Wikipédia : https://ja.wikipedia.org/wiki/東京 fonctionne dans tout navigateur moderne même si la requête sous-jacente encode le path comme /wiki/%E6%9D%B1%E4%BA%AC.

Le WHATWG URL Standard, ce que les navigateurs font vraiment

Le RFC 3986 de l’IETF dit une chose ; les navigateurs font quelque chose de légèrement différent. Le WHATWG (l’organisme de standardisation des éditeurs de navigateurs) maintient un URL Living Standard séparé sur url.spec.whatwg.org décrivant la machine à états algorithmique que les navigateurs exécutent réellement, y compris la gestion des espaces de tête, des caractères de contrôle, des jeux de percent-encoding qui varient selon la composante, et la normalisation Unicode. La spec WHATWG est ce que le constructeur URL du navigateur (new URL(input)) implémente, et ce sur quoi Node.js, Deno et Bun ont tous convergé pour leur parsing d’URL intégré. Le parseur Ada: écrit en C++ par Yagiz Nizipli, Daniel Lemire et d’autres, est devenu le parser conforme WHATWG qui alimente le parsing d’URL de Node.js depuis Node.js 18.16.0 (avril 2023), remplaçant l’ancien chemin url.parse() ; il est mesurablement plus rapide que toute implémentation antérieure et est le standard de facto pour le parsing d’URL haute performance en 2026. RFC 3986 et la spec WHATWG ne sont toujours pas pleinement réconciliées, et la divergence historique apparaît encore dans des chemins de code legacy et des versions plus anciennes de runtime.

La query string, et l’API URLSearchParams

La query string est techniquement juste « tout ce qui suit le ? et précède le # », la spec ne définit pas réellement comment l’interpréter. La convention ?key=value&key=value avec des séparateurs & est une convention, pas une exigence. En pratique, deux formats de query string dominent : application/x-www-form-urlencoded (le format de soumission de formulaire HTML par défaut, où + signifie un espace) et la convention de query URI standard (où l’espace est toujours %20). L’API URLSearchParams du navigateur (faisant partie du WHATWG URL Living Standard) gère les deux formats de manière transparente pour le parsing et émet la variante form-encoded lors du stringify. Les clés répétées sont légales : ?tag=red&tag=blue&tag=green est valide, et URLSearchParams.getAll('tag') retourne ['red', 'blue', 'green']. Différents frameworks web gèrent le cas des clés répétées différemment : Rails et Express collectent les clés répétées en tableaux, alors que PHP écrase les valeurs antérieures par les suivantes sauf si la clé utilise la convention de crochets name[] ; c’est une source constante de bugs cross-framework dans les intégrations d’API.

Pièges courants du parsing d’URL

Cas d’usage courants

Confidentialité : les URL portent de vrais secrets

Les URL ne sont généralement pas traitées comme secrètes, mais elles portent souvent des données qui le sont. Les URL de callback OAuth incluent des access tokens. Les URL de magic-link login incluent des tokens d’authentification à usage unique. Les liens de réinitialisation de mot de passe incluent des reset tokens. Les URL d’API internes incluent des noms d’hôtes internes et des chemins de routage qui révèlent l’infrastructure. Même des URL d’application ordinaires révèlent le comportement utilisateur via les paramètres de query, termes de recherche, sélections de filtres, IDs de profil, identifiants de session. L’en-tête Referer fuite l’URL précédente vers chaque site lié, mitigé par l’en-tête Referrer-Policy introduit comme W3C Candidate Recommendation en 2017 (les défauts varient encore selon les navigateurs). Les URL finissent dans les access logs serveur, dans l’historique du navigateur, dans les marque-pages, dans les logs CDN, dans les pipelines d’analytique, dans les aperçus de liens des apps de chat. Un parser d’URL côté serveur voit chaque URL qu’on y colle ; un parser uniquement côté navigateur, non. Pour les URL d’API internes, les callbacks OAuth avec tokens, les liens de réinitialisation de mot de passe, ou toute URL que vous ne voudriez pas voir copiée sur le disque dur d’un inconnu, un parser uniquement navigateur est la bonne architecture. Vérifiez dans l’onglet Réseau des DevTools pendant que vous parsez, ou mettez la page hors ligne (mode avion) après son chargement.

Questions fréquentes

Quelles parties contient une URL ?

Six parties conceptuelles : scheme (https, http, ftp, mailto), userinfo (rare en usage moderne, surtout retiré par les navigateurs comme atténuation de phishing), host (domaine ou IP), port (par défaut 80 pour HTTP, 443 pour HTTPS), path (hiérarchie séparée par des barres obliques), query (paires clé-valeur après ?) et fragment (après #, jamais envoyé au serveur). La grammaire complète est dans RFC 3986 §3 (janvier 2005, STD 66) et le WHATWG URL Living Standard.

Comment décoder les caractères URL-encodés ?

Le percent-encoding remplace les caractères dangereux par un % suivi du code hex de l’octet : un espace est %20, deux-points est %3A, une barre oblique est %2F, une esperluette est %26, l’arobase est %40. Les caractères multi-octets UTF-8 sont encodés octet par octet, donc é devient %C3%A9 (deux octets). Le parser décode automatiquement tous les caractères percent-encodés dans la sortie affichée. Les fonctions JavaScript standard sont encodeURIComponent() pour encoder des valeurs individuelles et decodeURIComponent() pour décoder.

Qu’est-ce qu’un fragment d’URL ?

Le fragment (tout ce qui suit #) est la seule partie de l’URL qui est traitée entièrement côté client, il n’est jamais envoyé au serveur web dans les requêtes HTTP. Objectif d’origine : faire défiler le navigateur jusqu’à un élément ancre avec cet ID. Les usages modernes incluent l’état de route des single-page applications (#/dashboard/profile), les tokens du flux implicite OAuth (désormais déconseillé en faveur de authorization code avec PKCE), et la navigation par page de PDF (file.pdf#page=5). Comme les fragments n’atteignent pas le serveur, c’est un endroit pour cacher des valeurs qui ne devraient pas apparaître dans les logs serveur.

Pourquoi + signifie parfois un espace et parfois + ?

Deux conventions d’encoding existent. application/x-www-form-urlencoded (le format de soumission de formulaire HTML par défaut) encode les espaces en + ; le percent-encoding standard (selon RFC 3986) encode les espaces en %20. Les deux sont valides dans les query strings ; seul %20 est valide dans les paths et fragments. URLSearchParams gère les deux de manière transparente. Le bug cross-context survient quand le code utilise encodeURIComponent (qui encode l’espace en %20) pour des paramètres de query que le serveur attend en form-encoded, ou vice versa.

Gère-t-il les URL relatives ?

Le parser attend une URL complète avec un scheme. Pour un path relatif comme /api/users, préfixez avec une URL de base (https://example.com/api/users) pour le parser. Un peu de parsing d’URL relative (résolution contre une URL de base comme le navigateur le fait pour les attributs href) est sur la roadmap, la forme à deux arguments du constructeur URL du WHATWG (new URL(relative, base)) gère cela et c’est ce que le code de production devrait utiliser.

Mes URL sont-elles envoyées quelque part ?

Non. Le parsing s’exécute entièrement dans votre navigateur via le constructeur URL du WHATWG, l’URL que vous collez ne quitte jamais votre appareil. Vérifiez dans l’onglet Réseau des DevTools pendant que vous cliquez sur Parser, ou mettez la page hors ligne (mode avion) après son chargement. Sûr pour les URL de callback OAuth contenant des access tokens, les liens de réinitialisation de mot de passe contenant des tokens à usage unique, les URL d’API internes qui révèlent l’infrastructure, ou toute URL que vous ne voudriez pas voir copiée sur le disque dur d’un inconnu.

Outils associés