Encoder une URL

Collez une chaîne et récupérez-la en encodage-pourcent, prête pour une URL. La seule décision qui compte vous est posée au lieu d’être devinée : encodez-vous une valeur qui va à l’intérieur d’une URL, ou une adresse entière dont les barres obliques et les points d’interrogation sont de la structure et doivent survivre ? Se tromper de sens produit une adresse qui a l’air juste et qui mène ailleurs.

Une valeur fait échapper ? & = / et #. Une adresse entière les conserve, car là ce sont des séparateurs.

Résultat

La réponse apparaît ici pendant que vous écrivez.

  • Où cela s’exécute

    Rien n’est envoyé, puisqu’il n’y a pas de fichier : tout est calculé dans cette page.

  • Sans file d’attente et sans compte

    Il répond aussi vite que votre machine le permet, et ne demande jamais qui vous êtes.

  • Autant de fois que vous voulez

    Rien n’est compté ni plafonné : répondre à nouveau ne nous coûte rien.

Comment cela fonctionne

  1. Collez le texte dans le champ.
  2. Dites ce que c’est : une valeur à l’intérieur d’une URL, ou une URL entière. C’est ce choix qui décide si ? et & sont échappés.
  3. Copiez le résultat. Rien n’a été envoyé.

La seule question posée ici, et pourquoi elle l’est

Une URL est faite de parties, et les caractères qui les séparent — `/`, `?`, `&`, `=`, `#` — sont de la structure quand ils font ce travail et de la donnée quand ils ne le font pas. Encoder une adresse entière doit les laisser intacts, sinon l’adresse cesse d’en être une. Encoder une seule valeur doit les échapper, sinon la valeur s’arrête et autre chose commence.

C’est exactement la différence entre `encodeURI` et `encodeURIComponent`, et c’est l’erreur derrière la plupart des paramètres de redirection cassés du web : un `?retour=https://exemple.fr/a?b=c` dont le second point d’interrogation n’a jamais été échappé, si bien que tout ce qui suit appartient à l’adresse extérieure. Le lien marche en recette, où la cible n’a pas de query string, et casse en production, où elle en a une.

L’encodage-pourcent transporte des octets, pas des caractères

Une séquence de pourcentage est un `%` suivi de deux chiffres hexadécimaux, et elle désigne un octet. Les caractères hors ASCII en prennent plusieurs : `é` s’écrit `%C3%A9`, pas `%E9`, parce que l’UTF-8 l’épelle en deux octets. Un emoji prend quatre séquences.

L’ancienne fonction `escape()` produisait `%E9` et est dépréciée précisément pour cela — elle est antérieure à la décision que le web est en UTF-8. Sa sortie traîne encore dans du vieux code et dans quelques API héritées, où elle donnera le mauvais caractère partout sauf sur un serveur Latin-1. Tout ici est en UTF-8.

Les cinq caractères qui piègent la signature de requêtes

`encodeURIComponent` laisse `!`, `'`, `(`, `)` et `*` sans échappement. Le RFC 3986 les classe comme réservés, si bien qu’un encodeur strictement conforme les échappe : les deux sont donc en désaccord sur cinq caractères qui apparaissent tout le temps dans du texte ordinaire, à commencer par l’apostrophe.

Personne ne le remarque tant qu’aucune signature n’est en jeu. OAuth 1.0 et AWS Signature Version 4 calculent tous deux une empreinte sur la chaîne encodée : une seule apostrophe non échappée change l’empreinte et la requête est rejetée — avec une erreur qui parle d’identifiants, ce qui vous envoie chercher au mauvais endroit. L’option stricte échappe les cinq.

Les espaces : %20, ou un signe plus

Les deux existent et ne relèvent pas de la même règle. `%20` est de l’encodage-pourcent et il est correct partout dans une URL. Le signe plus vient de `application/x-www-form-urlencoded`, le format dans lequel un formulaire HTML poste, où une espace s’écrit `+` — une convention antérieure à la spécification moderne, qui survit parce que les formulaires survivent.

Dans un chemin, `+` est un plus littéral. Dans un query string, la plupart des serveurs le lisent comme une espace, puisque c’est ce que dit l’encodage de formulaire : un vrai plus dans une valeur de query doit donc s’écrire `%2B` sous peine de disparaître. Cet encodeur émet `%20`, qui n’est ambigu à aucun des deux endroits.

Encoder deux fois, et comment le repérer

Encoder une chaîne déjà encodée échappe le `%` lui-même, donc `%20` devient `%2520`. Ce n’est une erreur pour aucun des composants concernés — c’est un encodage parfaitement valide du texte littéral « %20 » — et c’est pourquoi le double encodage survit jusqu’au point où un visiteur voit `Bonjour%20le%20monde` dans un titre.

L’indice est un `%25` là où devrait se trouver un `%`. Quand vous en voyez un, quelque chose dans la chaîne encode une valeur déjà encodée, en général parce qu’un framework le fait pour vous et qu’un gabarit le refait. Le correctif est d’en retirer un, pas de décoder deux fois à l’arrivée.

Les accents dans un chemin, et le piège de la normalisation

Un chemin peut contenir des caractères accentués, et un navigateur les affichera tels quels tout en envoyant leur forme encodée. `/café` part donc en `/caf%C3%A9`, ce qui est correct et lisible des deux côtés.

Le piège est qu’un `é` peut s’écrire de deux façons en Unicode : un seul point de code, ou un `e` suivi d’un accent combinant. Les deux s’affichent à l’identique et produisent des séquences de pourcentage différentes, donc deux URL visuellement identiques peuvent désigner deux ressources distinctes. macOS produit couramment la seconde forme, Windows et Linux la première : c’est la source d’un lien qui marche chez l’un et donne un 404 chez l’autre.

Les noms de domaine ne s’encodent pas ainsi

L’encodage-pourcent ne s’applique pas à l’hôte. Un nom de domaine accentué comme `café.example` s’écrit en Punycode : `xn--caf-dma.example`, une transformation entièrement différente définie pour les noms de domaine internationalisés, et c’est cette forme qui part sur le réseau.

La conséquence pratique est qu’encoder une adresse entière ici ne touchera pas son hôte : ce serait faux. Si vous devez placer un domaine accentué dans une configuration, dans un certificat ou dans un enregistrement DNS, c’est la forme `xn--` qu’il faut, et un navigateur vous la montre en collant l’adresse dans la barre puis en la recopiant.

Ce qu’il ne faut surtout pas encoder

Le schéma et les deux barres obliques qui suivent. L’esperluette qui sépare deux paramètres. Le signe égal qui sépare un nom de sa valeur. Le point d’interrogation qui ouvre le query string. Encoder l’un d’eux transforme une adresse structurée en une seule longue valeur, que le serveur recevra comme un chemin absurde.

C’est l’erreur symétrique de celle du début, et elle vient presque toujours d’un encodeur appliqué à la chaîne entière par réflexe. La règle tient en une phrase : on encode ce qu’on a écrit soi-même comme donnée, jamais ce qu’on a écrit comme structure.

Les longueurs maximales, qui existent en pratique

Aucune spécification ne fixe de longueur maximale à une URL, mais les implémentations si. Les serveurs plafonnent couramment la ligne de requête autour de 8 kilooctets, et plusieurs navigateurs et intermédiaires imposent leurs propres limites bien avant.

Comme l’encodage-pourcent triple la taille des caractères accentués, une valeur qui tenait de justesse peut dépasser après encodage : un texte français de trois mille caractères peut approcher les six mille octets une fois encodé. Quand une requête est rejetée sans message clair juste après un ajout de paramètre, la longueur est la première chose à mesurer.

Encoder une URL : questions fréquentes

Faut-il encoder l’URL entière ou seulement la valeur ?

Seulement la valeur, presque toujours. Encoder une adresse entière sert au cas rare où vous avez une adresse contenant une espace ou un caractère hors ASCII et devez la rendre légale sans toucher à sa structure. Si vous construisez un query string, chaque valeur est encodée séparément et les & et = qui les séparent ne le sont pas.

Pourquoi une espace est-elle parfois %20 et parfois + ?

Parce que le `+` vient de l’encodage des formulaires HTML et non des URL elles-mêmes. Les serveurs qui lisent un query string acceptent en général les deux, mais seul `%20` est correct dans un chemin et seul `%20` est non ambigu : un vrai plus dans une valeur doit s’écrire %2B sinon il sera lu comme une espace.

Les accents, le cyrillique et les emoji sont-ils gérés ?

Oui, en UTF-8, ce que spécifie le web moderne. Un caractère peut devenir plusieurs séquences : é vaut %C3%A9 et un emoji quatre séquences. L’ancienne fonction escape() produisait un seul octet et se trompe pour tout ce qui sort du Latin-1.

À quoi sert l’option stricte ?

À la signature de requêtes. OAuth 1.0 et AWS SigV4 hachent la chaîne encodée, et l’encodeur ordinaire laisse cinq caractères — point d’exclamation, apostrophe, les deux parenthèses et l’astérisque — sans échappement là où le RFC 3986 dit le contraire. Un seul d’entre eux dans vos données change l’empreinte et la requête est rejetée, souvent avec une erreur trompeuse sur les identifiants.

Mon texte part-il vers un serveur ?

Non. L’encodage a lieu dans cette page et rien n’est envoyé, ce que l’onglet réseau permet de confirmer. Les valeurs que les gens encodent sont souvent des termes de recherche, des identifiants et des cibles de redirection : rien de tout cela n’a besoin de voyager pour être échappé.

Autres outils