Codage · 5 septembre 2026

Codage d'URL — pourquoi %20 existe, quand coder, et le piège qui casse les APIs

Le codage d'URL transforme les caractères non sûrs en séquences codées en pourcentage. C'est simple jusqu'à ce que ça ne le soit pas — double codage, paramètres de requête vs chemins, et la règle qui empêche 90% des bugs.

Chaque URL que vous avez tapée ou cliquée est passée par le codage d’URL. L’espace dans « mon fichier.txt » devient %20. Le & dans une chaîne de requête devient %26. Le / dans un chemin reste / — mais seulement parce que le codeur sait quels caractères sont sûrs et lesquels ne le sont pas.

Le codage d’URL (officiellement « codage en pourcentage ») est la façon dont les URLs représentent les caractères qui ne font pas partie du jeu de caractères non réservés. C’est une transformation simple, mais les cas limites sont là où vivent la plupart des bugs d’API.

Les caractères non réservés

Ces caractères sont toujours sûrs dans les URLs et n’ont jamais besoin de codage :

A-Z a-z 0-9 - _ . ~

Tout le reste — espaces, barres, esperluettes, signes égaux, caractères non ASCII — doit être codé comme un signe pourcentage suivi de deux chiffres hexadécimaux :

  • Espace → %20
  • & → %26
  • = → %3D
  • / → %2F
  • ? → %3F
  • # → %23

Le codage est les valeurs d’octets UTF-8 du caractère, chacune représentée par deux chiffres hexadécimaux. Un caractère multi-octets comme é (UTF-8 : 0xC3 0xA9) devient %C3%A9.

Où le codage compte

Paramètres de requête. C’est là que le codage d’URL cause le plus de bugs. Si une valeur de requête contient & ou =, l’analyseur d’URL divise sur ces caractères et brise la structure du paramètre :

/search?q=cats&dogs     ← ambigu : « dogs » est-il un paramètre séparé ?
/search?q=cats%26dogs   ← correct : « cats&dogs » est une seule valeur

Chaque bibliothèque HTTP a une fonction pour coder les paramètres de requête. Utilisez-la. Ne concaténez jamais des chaînes dans une chaîne de requête à la main.

Chemins. Les espaces dans les noms de fichiers nécessitent un codage :

/download/my file.pdf     ← cassé
/download/my%20file.pdf   ← fonctionne

Mais les barres à l’intérieur d’un segment de chemin nécessitent aussi un codage :

/file/path/segment   ← deux segments : « file/path » divisé par /
/file%2Fpath/segment ← un segment : « file/path »

Caractères non ASCII. Les URLs sont uniquement ASCII. Tout caractère non ASCII (lettres accentuées, caractères CJK, emoji) doit être codé en pourcentage :

  • café → caf%C3%A9
  • 日本語 → %E6%97%A5%E6%9C%AC%E8%AA%9E
  • 🎉 → %F0%9F%8E%89

La plupart des navigateurs affichent la version décodée dans la barre d’adresse, mais les octets réels envoyés sur le réseau sont codés.

Le piège du double codage

Le bug de codage d’URL le plus courant : coder une chaîne déjà codée.

Prenez le chemin /hello%20world. Si vous le codez à nouveau en URL, le % devient %25 :

/hello%20world      ← original (correct)
/hello%2520world    ← double codé (cassé)

Le serveur décode %25 en %, puis voit %20 et le décode en espace. Vous finissez avec /hello world — mais seulement si le serveur fait un seul décodage. S’il en fait deux (certaines le font), vous récupérez l’original. Le comportement est incohérent et imprévisible.

La règle : codez une fois, decodez une fois. Si vous recevez une chaîne codée, decodez-la avant de recoder. Vérifiez si le constructeur d’URL de votre bibliothèque HTTP attend des valeurs brutes ou pré-codées — la différence entre path et rawPath dans la plupart des frameworks compte.

Codage de chaîne de requête

Les chaînes de requête ont leurs propres règles de codage. La différence clé avec les chemins : + représente un espace dans les chaînes de requête (application/x-www-form-urlencoded), mais %20 représente aussi un espace. Les deux sont valides, mais ils viennent de normes différentes :

  • application/x-www-form-urlencoded (soumissions de formulaire) — + pour les espaces
  • Codage en pourcentage (URLs) — %20 pour les espaces

La plupart des APIs modernes acceptent les deux. Mais si vous analysez une chaîne de requête d’une soumission de formulaire, + → espace. Si vous construisez une URL, %20 → espace. Les mélanger cause des bugs subtils où les espaces deviennent des signes + ou vice-versa.

Utilisez la fonction de codage d’URL de votre langage. Elle gère la distinction pour vous.

Codage vs échappement

Le codage d’URL n’est pas l’échappement HTML. Ils résolvent des problèmes différents :

  • Codage d’URL (%20) — pour les caractères dans les URLs. Empêche les caractères d’être interprétés comme syntaxe d’URL.
  • Échappement HTML (&, <) — pour les caractères dans HTML. Empêche les caractères d’être interprétés comme balises ou entités HTML.

Une URL dans un href HTML nécessite les deux : codez les valeurs des paramètres en URL, puis encodez toute la URL en HTML :

<a href="/search?q=cats%26dogs&amp;page=1">

Le %26 empêche & d’être interprété comme séparateur de requête. Le &amp; empêche & d’être interprété comme début d’entité HTML.

Pièges courants

Les espaces dans différents contextes. %20 dans une URL, + dans un corps de formulaire, %2520 si vous avez accidentellement double codé. Savoir dans quel contexte vous êtes.

Fragments de hash. Tout après # n’est pas envoyé au serveur. Si vous codez une URL avec un fragment et que le fragment contient ? ou &, le serveur ne les voit jamais. Le fragment est uniquement côté client.

Coder le signe pourcentage. % → %25. Si un % littéral apparaît dans vos données (comme un mot de passe contenant %), il doit être codé. Si vous ne le codez pas, l’analyseur interprète les deux caractères qui le suivent comme une séquence hexadécimale.

Normalisation Unicode. Certains systèmes normalisent Unicode avant de coder. café (avec accent combiné) et café (avec é précomposé) codent en séquences de pourcentage différentes. Cela cause des problèmes avec les noms de fichiers et les noms de domaine internationalisés.

Référence rapide

Caractère Codé en pourcentage Contexte
Espace %20 URL
Espace + Corps de formulaire
& %26 Chaîne de requête
= %3D Chaîne de requête
/ %2F Segment de chemin
? %3F Chaîne de requête
# %23 Chemin/requête
% %25 Partout
+ %2B Chaîne de requête

Essayez

Si vous avez une URL ou une chaîne codée à décoder (ou des données brutes à coder), utilisez un outil local pour que la conversion se fasse dans votre navigateur — aucune donnée n’est envoyée nulle part.