Avouez-le — vous avez déjà eu un bug où une URL contenant des espaces ou des caractères spéciaux a cassé quelque chose. Peut-être qu'un & dans une recherche a provoqué un comportement bizarre. Ou vous avez vu %20 dans une URL en vous demandant ce que c'était. Éclaircissons tout cela.
Pourquoi les URLs ont besoin d'encodage
Les URLs ne peuvent contenir qu'un ensemble limité de caractères. La spécification RFC 3986 définit les caractères « non réservés » toujours sûrs : A-Z, a-z, 0-9, -, _, . et ~. Tout le reste — espaces, &, =, ?, caractères non-ASCII comme ñ ou 日本語 — doit être encodé en pourcentage.
Comment fonctionne l'encodage en pourcentage
C'est simple : on prend la valeur en octets UTF-8 du caractère, et on représente chaque octet par % suivi de deux chiffres hexadécimaux.
Exemples :
- Espace →
%20 &→%26=→%3Dé→%C3%A9(deux octets en UTF-8)日→%E6%97%A5(trois octets en UTF-8)
Ainsi Hello World devient Hello%20World dans un chemin d'URL.
Le bug n°1 : le double encodage
C'est l'erreur d'encodage URL la plus courante que je vois, et elle est subtile. Vous encodez une chaîne, puis la passez à une fonction qui l'encode à nouveau. Maintenant %20 (un espace déjà encodé) devient %2520 parce que le % lui-même est encodé.
Exemple du problème :
La solution : encoder les valeurs une seule fois, au bon niveau. N'encodez pas ce qui est déjà encodé.
Signe plus vs. %20 — Oui, c'est déroutant
Dans les query strings, les espaces peuvent être + ou %20. La convention du + vient de l'encodage des formulaires HTML (application/x-www-form-urlencoded). Dans les chemins d'URL, seul %20 est valide.
Donc https://example.com/hello world → le chemin s'encode en https://example.com/hello%20world
Mais https://example.com/search?q=hello world → la requête peut être ?q=hello+world ou ?q=hello%20world
encodeURI vs. encodeURIComponent
JavaScript vous donne deux fonctions, et utiliser la mauvaise est une erreur classique :
encodeURI()— Encode une URL complète. Laisse:,/,?,#,&,=intacts car ce sont des parties structurelles de l'URL.encodeURIComponent()— Encode un composant d'URL (comme la valeur d'un paramètre de requête). Encode AUSSI:,/,?,#,&,=car ils pourraient faire partie des données.
Règle d'or : utilisez encodeURIComponent() pour les valeurs, jamais pour des URLs entières. La documentation MDN explique la différence à merveille.
Autres langages
- Python :
urllib.parse.quote()pour les chemins,urllib.parse.urlencode()pour les query strings — documentation ici - Java :
URLEncoder.encode()(utilise+pour les espaces — attention !) - PHP :
urlencode()pour les query strings,rawurlencode()pour les chemins
Conseils rapides
- Encodez toujours les valeurs des paramètres, jamais les URLs entières
- Décodez une seule fois côté réception — ne faites pas passer les valeurs encodées à travers plusieurs couches
- Testez avec des cas limites : espaces,
&,=,#, caractères non-ASCII et emoji
Construire des URLs en toute sécurité en JavaScript
La bonne façon de construire des URLs avec des paramètres de requête est d'utiliser les APIs intégrées URL et URLSearchParams. Elles gèrent tout l'encodage pour vous :
Remarquez comment URLSearchParams utilise + pour les espaces (convention d'encodage de formulaires HTML) et encode correctement le & dans la valeur pour qu'il ne soit pas confondu avec le & qui sépare les paramètres. C'est bien plus sûr que la concaténation de chaînes.
Pièges courants de l'encodage URL
1. Encoder toute l'URL au lieu des valeurs seules. Si vous exécutez encodeURIComponent() sur une URL complète, il encodera les caractères ://, /, ? et & — rendant l'URL complètement inutilisable. N'encodez que les valeurs individuelles des paramètres.
2. Oublier d'encoder les fragments hash. Le caractère # dans une URL commence un identifiant de fragment. Si vos données contiennent un # et que vous ne l'encodez pas, tout ce qui suit disparaît du point de vue du serveur. Le serveur ne voit jamais les identifiants de fragment — ils sont uniquement côté client.
3. Ne pas gérer les noms de domaine internationaux (IDN). Les noms de domaine avec des caractères non-ASCII comme example.日本 nécessitent un traitement spécial appelé encodage Punycode. C'est séparé de l'encodage en pourcentage et ne s'applique qu'à la portion du nom d'hôte de l'URL.
4. Encoder les espaces de manière incohérente. Certaines parties de votre système pourraient encoder les espaces en + et d'autres en %20. Cela fonctionne généralement bien pour le décodage, mais peut causer des problèmes de comparaison d'URLs et de mise en cache. Choisissez une convention et tenez-vous-y.
Référence rapide d'encodage en pourcentage
| Caractère | Encodé | Pourquoi il doit être encodé |
| Espace | %20 ou + | Non autorisé dans les URLs |
& | %26 | Sépare les paramètres de requête |
= | %3D | Sépare la clé de la valeur |
? | %3F | Commence la chaîne de requête |
# | %23 | Commence l'identifiant de fragment |
% | %25 | Le caractère d'échappement lui-même |
/ | %2F | Séparateur de chemin |
@ | %40 | Utilisé dans la section userinfo |
L'encodage URL dans différents contextes
L'encodage URL ne concerne pas seulement les URLs de navigateur. Vous le rencontrerez dans ces situations courantes :
- Requêtes API : Les paramètres de requête dans les appels d'API REST nécessitent un encodage correct, surtout s'ils contiennent des entrées utilisateur
- URLs de redirection : Quand vous passez une URL de retour comme paramètre (comme
?redirect=https://...), l'URL de redirection entière doit être encodée comme valeur - Flux OAuth : Les URLs de callback OAuth et les paramètres d'état sont notoirement délicats car ils impliquent plusieurs couches d'encodage URL
- Deep links : Les deep links mobiles suivent les mêmes règles d'encodage URL, mais certaines plateformes ont des exigences supplémentaires
Déboguer les problèmes d'encodage URL
Quand quelque chose ne va pas avec l'encodage URL, voici ma checklist de débogage :
1. Vérifier le double encodage — Cherchez %25 dans l'URL, ce qui signifie qu'un % a été encodé deux fois
2. Vérifier la requête brute — Utilisez l'onglet Réseau des DevTools de votre navigateur pour voir exactement quelle URL a été envoyée, avant que le navigateur n'affiche la version décodée
3. Comparer encodé vs. décodé — Collez l'URL problématique dans un décodeur pour voir ce qu'elle contient réellement
4. Vérifier le décodage côté serveur — Certains frameworks décodent automatiquement les paramètres URL, et le faire manuellement en plus cause des problèmes
L'anatomie d'une URL
OK, prenons du recul. Avant d'aller plus loin dans l'encodage, vous devez vraiment comprendre de quoi une URL est faite. Je sais, je sais — vous utilisez des URLs depuis le début de votre carrière. Mais je parie que vous ne connaissez pas toutes les parties par leurs noms officiels. La plupart des développeurs non plus, et c'est là que la confusion sur l'encodage commence.
Selon RFC 3986, une URL a cette structure :
Laissez-moi vous expliquer chaque partie :
- Scheme (
https,ftp,mailto) — Le protocole. Pas besoin d'encodage ici, ce sont toujours des lettres ASCII. - Authority — Ceci inclut le
user:password@optionnel (que vous ne devriez pratiquement jamais utiliser en 2026), le host (nom de domaine ou IP) et un numéro de port optionnel. - Path (
/search/results) — La partie hiérarchique. Les barres obliques/séparent les segments. À l'intérieur de chaque segment, vous devez encoder les caractères spéciaux, mais vous n'encodez PAS les barres obliques elles-mêmes. - Query (
?q=hello&lang=en) — Paires clé-valeur après le?. Le&sépare les paires,=sépare les clés des valeurs. Vous encodez les clés et les valeurs, mais pas les&et=structurels. - Fragment (
#section-2) — La partie après#. Celle-ci est intéressante — elle n'est jamais envoyée au serveur. Elle est purement côté client. Mais vous devez quand même encoder les caractères spéciaux à l'intérieur.
Voici ce qui perturbe les gens : différentes parties de l'URL ont des règles d'encodage différentes. Un / est parfaitement valide dans le chemin (c'est un séparateur !) mais doit être encodé en %2F s'il apparaît à l'intérieur d'une valeur de paramètre de requête. Un signe @ est valide dans la section authority mais devrait être encodé dans le chemin. C'est pourquoi les fonctions d'encodage universelles causent tant de bugs.
Pensez-y comme ceci : l'URL est une phrase avec des règles de grammaire. Les caractères spéciaux sont la ponctuation. Vous n'encoderiez pas une virgule qui est réellement utilisée comme virgule — vous n'encodez qu'une virgule qui fait partie des données et pourrait être confondue avec de la ponctuation.
encodeURI vs. encodeURIComponent : Le champ de mines JavaScript
Bon, celui-ci me rend absolument fou parce que je vois des développeurs se tromper TOUT le temps. JavaScript vous donne deux fonctions d'encodage, et elles sonnent presque pareil, mais utiliser la mauvaise va ruiner votre journée.
Laissez-moi l'expliquer clairement :
encodeURI() est conçue pour encoder une URL complète. Elle encode les caractères dangereux mais laisse les caractères structurels tranquilles — des choses comme :, /, ?, #, &, =, @. Parce que si vous encodez une URL complète, vous ne voulez évidemment pas casser la structure de l'URL.
encodeURIComponent() est conçue pour encoder une valeur individuelle qui va à l'intérieur d'une URL. Elle encode TOUT sauf les lettres, les chiffres et - _ . ~. Cela inclut :, /, ?, #, &, = — parce que quand ceux-ci apparaissent dans une valeur, ce sont des données, pas de la structure.
Voici une comparaison qui rend les choses limpides :
| Caractère | encodeURI() | encodeURIComponent() |
: | : (inchangé) | %3A |
/ | / (inchangé) | %2F |
? | ? (inchangé) | %3F |
# | # (inchangé) | %23 |
& | & (inchangé) | %26 |
= | = (inchangé) | %3D |
@ | @ (inchangé) | %40 |
| Espace | %20 | %20 |
é | %C3%A9 | %C3%A9 |
Maintenant ça devient effrayant. Regardez ce qui arrive quand vous utilisez la mauvaise :
Et l'erreur inverse est tout aussi grave :
La règle d'or : encodeURIComponent pour les valeurs, encodeURI pour les URLs complètes. Ou mieux encore, utilisez simplement l'API URL et laissez le navigateur s'en occuper. Sérieusement, les classes URL et URLSearchParams existent pour une raison. Consultez la doc MDN encodeURIComponent et la doc MDN encodeURI pour tous les détails.
L'encodage URL dans différents langages
JavaScript n'est pas le seul langage avec des fonctions d'encodage URL déroutantes. Chaque langage a ses propres bizarreries, et je ne plaisante pas, certains sont encore plus déroutants que la paire de JavaScript.
Python — En fait assez raisonnable, une fois que vous avez trouvé le bon module :
Java — C'est là que ça devient bizarre. URLEncoder a été conçu pour l'encodage de formulaires HTML, pas pour l'encodage URL général. Donc les espaces deviennent + au lieu de %20 :
C# — .NET vous donne en fait les bons outils, mais il y a genre cinq méthodes différentes et elles font toutes des choses légèrement différentes :
PHP — Oh PHP. Bien sûr que vous avez deux fonctions avec des noms presque identiques qui font des choses légèrement différentes :
Go — Propre et sensé, comme Go a tendance à l'être :
La leçon à retenir ? Chaque langage gère le sujet + vs. %20 différemment, et chaque langage a au moins une fonction qui vous surprendra. Vérifiez toujours la documentation du langage avec lequel vous travaillez. Ne supposez pas que ça fonctionne comme en JavaScript.
Unicode dans les URLs : Le Far West
OK alors là ça devient VRAIMENT intéressant. Que se passe-t-il quand vous mettez des caractères non-ASCII dans une URL ? Genre, que se passe-t-il si vous voulez une URL avec du japonais, de l'arabe ou — sans blague — des emoji ?
La réponse implique deux systèmes complètement différents, et les confondre est une erreur classique.
Pour les parties chemin et requête : Vous utilisez l'encodage en pourcentage. Prenez les octets UTF-8 du caractère et encodez chacun d'eux. Donc café devient caf%C3%A9. Votre navigateur fait ça automatiquement et vous montre généralement la jolie version dans la barre d'adresse, mais sous le capot il envoie la version encodée en pourcentage.
Pour les noms de domaine : L'encodage en pourcentage n'est PAS utilisé. À la place, il y a ce système fou appelé Punycode. Il convertit les noms de domaine Unicode en chaînes compatibles ASCII qui commencent par xn--.
Regardez ça :
café.com→xn--caf-dma.commünchen.de→xn--mnchen-3ya.de例え.jp→xn--r8jz45g.jp
Pourquoi deux systèmes différents ? Parce que le DNS (le système qui transforme les noms de domaine en adresses IP) a été construit dans les années 1980 et ne supporte que l'ASCII. Donc ils ont dû inventer un moyen de faire entrer de l'Unicode dans des chaînes ASCII — et le Punycode est cette invention. Les parties chemin et requête d'une URL, en revanche, sont gérées par des serveurs web qui peuvent traiter des octets encodés en pourcentage.
Il y a en fait toute une spécification pour l'Unicode dans les URLs appelée IRI (Internationalized Resource Identifiers) définie dans RFC 3987. Un IRI est essentiellement une URL qui autorise les caractères Unicode directement. Les navigateurs convertissent les IRIs en URIs en coulisses.
Et oui, les domaines emoji existent. 💩.la est un vrai domaine (ou l'a été à un moment). Il est encodé en Punycode en xn--ls8h.la. Je ne recommande pas d'utiliser des domaines emoji pour quoi que ce soit de sérieux, mais c'est une preuve amusante que le système fonctionne.
Un piège avec l'Unicode dans les URLs : les différentes représentations Unicode du « même » caractère. Par exemple, é peut être représenté comme un seul codepoint (U+00E9) ou comme e + une marque d'accent combinante (U+0065 + U+0301). Ceux-ci produisent des chaînes encodées en pourcentage différentes ! Le Standard URL de WHATWG recommande la normalisation NFC, mais tous les systèmes ne suivent pas cela de manière cohérente.
Double encodage : Le bug qui hante vos rêves
J'ai mentionné le double encodage plus tôt, mais il mérite sa propre analyse approfondie parce que ce bug a probablement gaspillé plus d'heures collectives de développeurs que tout autre problème lié aux URLs. J'y suis passé — plusieurs fois.
Voici le scénario de base :
Que s'est-il passé ? Quand vous encodez hello%20world une deuxième fois, le caractère % est encodé en %25. Donc %20 devient %2520. Le serveur voit la chaîne littérale %20 au lieu d'un espace.
Ça semble évident quand je l'écris comme ça, mais dans de vrais codebases c'est incroyablement sournois. Voici les scénarios où le double encodage vous mord :
Chaînes de proxy. Vous envoyez une requête au serveur A, qui la transfère au serveur B. Si les deux serveurs encodent l'URL, boum — double encodage. Les API gateways comme Kong, AWS API Gateway ou les reverse proxies nginx sont des coupables courants.
Chaînes de redirection. L'utilisateur va à la page A, est redirigé vers la page B avec un paramètre ?returnUrl=..., et la page B redirige à nouveau avec l'URL de retour comme paramètre. Chaque redirection pourrait ré-encoder l'URL. Après trois redirections, votre URL est triple-encodée et complètement massacrée.
« Helpers » de framework. Certains frameworks web encodent automatiquement les paramètres URL. Si vous encodez manuellement avant de passer au framework, vous obtenez un double encodage. J'ai vu ça arriver avec Spring Boot, le middleware Express.js et le reversing d'URL de Django.
Comment détecter le double encodage ? Cherchez %25 dans l'URL. C'est un signe pourcentage qui a été encodé, ce qui signifie généralement que quelque chose a été encodé deux fois. Si vous voyez %2520, c'est un espace double-encodé. Si vous voyez %253D, c'est un signe = double-encodé.
Comment le corriger :
La meilleure défense est d'établir des frontières claires dans votre code : encodez aux bords (juste avant d'envoyer une requête HTTP, ou juste avant de construire une URL à afficher), et passez des chaînes brutes non encodées partout ailleurs en interne.
Limites de longueur d'URL et que faire à ce sujet
Voici quelque chose qui va vous surprendre : la spécification HTTP elle-même ne définit PAS de longueur maximale d'URL. RFC 3986 dit que les URLs devraient être « de longueur illimitée ». Mais le monde réel n'est pas d'accord.
Différents composants de la chaîne ont leurs propres limites, et c'est le plus court qui gagne :
| Composant | Longueur max d'URL |
| Internet Explorer (RIP) | 2 083 caractères |
| Chrome, Firefox, Safari | ~65 000+ caractères |
| Apache (par défaut) | 8 190 caractères |
| Nginx (par défaut) | 8 192 caractères |
| IIS (par défaut) | 16 384 caractères |
| AWS ALB | 8 192 caractères |
| Cloudflare | 32 768 caractères |
Cette vieille limite de 2 083 caractères d'IE dominait tout. Même si IE est pratiquement mort maintenant, certains développeurs et outils le traitent encore comme parole d'évangile. Mais en pratique, la plupart des stacks modernes peuvent gérer des URLs beaucoup plus longues.
Cela dit, ce n'est pas parce que vous POUVEZ faire une URL de 65 000 caractères que vous DEVRIEZ. Voici quelques vraies raisons de garder les URLs courtes :
- Logs serveur. Beaucoup de systèmes de logging tronquent les URLs longues, ce qui rend le débogage cauchemardesque.
- Copier-coller. Les utilisateurs copient et partagent les URLs. Les URLs super longues cassent dans les emails, messages de chat et documents.
- SEO. Les moteurs de recherche recommandent généralement de garder les URLs sous 2 000 caractères.
- Cache. Certaines limites de clé de cache CDN et proxy sont basées sur les URLs. URLs plus longues = plus de cache misses.
Alors que faire quand votre URL devient trop longue ? Ravi que vous posiez la question :
1. Utilisez POST au lieu de GET. Si vous envoyez beaucoup de données, mettez-les dans le corps de la requête. Le corps de la requête n'a pas de limite de taille pratique. C'est la solution la plus courante pour les formulaires de recherche complexes avec beaucoup de filtres.
2. Utilisez des raccourcisseurs d'URL ou des IDs de référence. Générez un court token qui correspond au jeu complet de paramètres stockés côté serveur. Donc au lieu de /search?filter1=abc&filter2=def&filter3=... vous obtenez /search/saved/abc123.
3. Compressez vos paramètres. Certaines apps encodent en base64 un blob JSON compressé et le mettent dans l'URL. Pas joli, mais ça marche. Vous verrez ça dans des outils comme les URLs de tableaux de bord Grafana.
Encodage de formulaires : application/x-www-form-urlencoded
Parlons de l'éléphant dans la pièce qui rend l'encodage URL encore plus confus : l'encodage de formulaires HTML. Quand vous soumettez un formulaire HTML avec method="POST", le navigateur encode les données du formulaire en utilisant un format appelé application/x-www-form-urlencoded. Et ce format est PRESQUE identique à l'encodage en pourcentage standard, mais avec une différence clé qui rend tout le monde fou.
Les espaces deviennent + au lieu de %20.
C'est tout. C'est la différence principale. Mais oh là là, ça cause de la confusion.
Pourquoi cette différence existe-t-elle ? Des raisons historiques, bien sûr. La spécification d'encodage de formulaires HTML est antérieure à la spécification d'encodage URL, et elle utilisait + pour les espaces parce que... eh bien, quelqu'un a trouvé que ça avait l'air mieux dans les années 90. Et maintenant on est coincé avec pour toujours.
Quand vous soumettez un formulaire HTML, le navigateur envoie un en-tête Content-Type: application/x-www-form-urlencoded, et le serveur sait interpréter + comme des espaces. Mais si vous construisez des URLs manuellement en JavaScript et que vous utilisez + pour les espaces dans la partie chemin, le serveur verra des signes plus littéraux. Moments amusants.
Voici où c'est important en pratique :
Et puis il y a multipart/form-data, qui est une bête complètement différente. Quand votre formulaire inclut des téléchargements de fichiers (), le navigateur passe à l'encodage multipart/form-data, qui utilise des délimiteurs pour séparer les champs au lieu de signes &. Il n'utilise pas du tout l'encodage URL — chaque partie a ses propres en-têtes et corps. Si vous avez déjà essayé de parser manuellement une requête multipart, vous connaissez la douleur.
Le conseil pratique : utilisez URLSearchParams pour les query strings et les données de formulaire. Utilisez FormData pour les téléchargements de fichiers. N'essayez pas d'encoder ces choses à la main sauf si vous devez vraiment, vraiment le faire.
Essayez par vous-même
Vous travaillez avec des URLs qui ont l'air incorrectes ? Collez-les dans notre Décodeur URL pour voir les caractères réels. Besoin d'encoder une valeur avant de la mettre dans une URL ? L'Encodeur URL s'en occupe instantanément. Et pour décomposer des URLs complexes en leurs composants, utilisez l'Analyseur d'URL pour voir chaque partie clairement.