Encodage URL vs Base64 : lequel choisir ?
Comparez l'encodage URL (pourcentage) et Base64 : découvrez les alphabets, le surcoût en octets, pourquoi Base64 casse les URLs et comment utiliser base64url.
Lors du développement d'applications web et d'API REST, les équipes techniques transfèrent en permanence des données à travers les protocoles réseau : paramètres de recherche, cibles de redirection, jetons d'authentification, signatures cryptographiques ou charges binaires. Choisir un format d'encodage inadapté pour ces données engendre des anomalies de production particulièrement vicieuses : paramètres de requête altérés, données binaires tronquées, erreurs de routage 404 ou surconsommation inutile de bande passante.
Deux formats prédominent dans les architectures web : l'encodage URL (percent-encoding) et l'encodage Base64. Bien que tous deux convertissent des données en caractères ASCII capables de transiter sur les réseaux sans altération, ils ont été conçus pour des contextes entièrement différents, imposent des surcoûts en octets distincts et se comportent différemment au sein d'une URL.
Vous pouvez encoder, décoder et analyser ces deux formats directement dans votre navigateur grâce aux outils Encodage & Décodage URL et Encodage & Décodage Base64 de ToolPorta. Ce guide détaille le fonctionnement de chaque format selon les spécifications officielles RFC, calcule leur surcoût exact en mémoire et en bande passante, dévoile le piège classique de l'intégration de Base64 dans les URLs et fournit une méthode rigoureuse pour sélectionner le format adapté à votre architecture.
Qu'est-ce que l'encodage URL (percent-encoding) ?#
L'encodage URL — formellement standardisé sous le nom d'encodage en pourcentage dans la RFC 3986 — est un mécanisme d'échappement spécifiquement élaboré pour les identifiants uniformes de ressources (URI).
Les URIs s'appuient sur un nombre restreint de caractères pour définir leur structure et leurs délimitations. Par exemple, : sépare les protocoles, // introduit l'autorité hôte, / sépare les segments de chemin, ? débute la chaîne de requête et & sépare les paramètres. Si des données dynamiques contiennent l'un de ces caractères sans échappement, les serveurs web et routeurs HTTP interprètent ces symboles comme des éléments structurels, corrompant la requête.
Classification des caractères selon la RFC 3986#
La spécification RFC 3986 répartit l'ensemble des caractères ASCII en trois groupes :
- Caractères non réservés (
A-Z,a-z,0-9,-,_,.,~) : Ils n'ont aucune fonction structurelle et les producteurs d'URI les laissent normalement tels quels. - Caractères réservés (
: / ? # [ ] @ ! $ & ' ( ) * + , ; =) : Ces caractères servent de délimiteurs structurels. Lorsqu'un de ces caractères représente une valeur littérale de données et non un séparateur, il doit obligatoirement être échappé. - Caractères interdits : Les espaces, les caractères de contrôle ASCII (
0x00à0x1F) et les caractères non-ASCII (lettres accentuées, idéogrammes, émojis) sont formellement prohibés dans une URI brute et doivent toujours être encodés.
Fonctionnement de l'encodage en pourcentage#
L'encodage remplace chaque octet interdit ou réservé par un triplet composé d'un symbole pourcent (%) suivi de deux chiffres hexadécimaux représentant la valeur binaire de l'octet (0x00 à 0xFF) :
- Une espace (
0x20) devient%20. - Un perluète (
&,0x26) devient%26. - Une barre oblique (
/,0x2F) devient%2F. - Un signe égal (
=,0x3D) devient%3D.
Pour les caractères Unicode multi-octets, la chaîne est d'abord transformée en séquence d'octets UTF-8, puis chaque octet est encodé individuellement :
- La lettre
é(octets UTF-80xC3 0xA9) devient%C3%A9. - L'émoji fusée
🚀(octets UTF-80xF0 0x9F 0x9A 0x80) devient%F0%9F%9A%80.
Qu'est-ce que l'encodage Base64 ?#
L'encodage Base64 — standardisé dans la RFC 4648 — a été pensé pour répondre à une problématique bien distincte : transporter des données binaires brutes à travers des protocoles textuels historiques limités aux caractères ASCII imprimables 7 bits (notamment le courrier électronique SMTP).
Plutôt que d'échapper des caractères individuels avec des triplets, Base64 traite l'entrée comme un flux continu de bits. Il regroupe les octets par blocs de 3 octets (24 bits) et les divise en 4 segments de 6 bits. Chaque segment de 6 bits correspond à l'un des 64 caractères de l'alphabet Base64 :
- Lettres majuscules :
AàZ(indices 0 à 25) - Lettres minuscules :
aàz(indices 26 à 51) - Chiffres :
0à9(indices 52 à 61) - Symboles :
+(indice 62) et/(indice 63) - Remplissage (padding) :
=(ajouté lorsque le nombre total d'octets d'entrée n'est pas un multiple de 3)
Base64 est massivement utilisé pour les pièces jointes MIME, les Data URIs (data:image/png;base64,...), le transport de clés cryptographiques dans des objets JSON et les en-têtes d'authentification HTTP Basic.
Base64 est un simple format d'encodage pour le transport de données et n'offre aucun chiffrement ni sécurité. N'importe qui peut décoder une chaîne Base64 en quelques millisecondes sans aucune clé. Pour une analyse approfondie, lisez notre article Base64 est un encodage, pas un chiffrement.
Tableau comparatif : Encodage URL vs Base64#
| Dimension | Encodage URL (Percent-Encoding) | Base64 Standard | Base64 adapté aux URLs (base64url) |
|---|---|---|---|
| Norme RFC principale | RFC 3986 | RFC 4648 (§4) | RFC 4648 (§5) |
| Objectif principal | Échapper les séparateurs d'URI dans du texte | Représenter du binaire en texte ASCII | Représenter du binaire sans casser les URIs |
| Alphabet autorisé | %, 0-9, A-F, plus caractères non réservés | A-Z, a-z, 0-9, +, /, = | A-Z, a-z, 0-9, -, _ (sans =) |
| Surcoût sur texte ASCII | 0 % pour les caractères non réservés ; jusqu'à 200 % par octet échappé | Environ 33 % sur les grandes entrées, plus l'effet du remplissage | Environ 33 % ; remplissage parfois omis par accord |
| Surcoût sur données binaires | Variable, avec un maximum de 200 % par octet encodé | Environ 33 % sur les grandes entrées | Environ 33 % sur les grandes entrées |
| Sûr pour les chemins d'URL | Oui (échappe / en %2F) | Non (contient des / bruts) | Oui (remplace / par _) |
| Sûr pour les query strings | Oui (échappe &, =, +) | Non (+ devient espace, = perturbe le parsing) | Oui (utilise - et _, omet le =) |
| Padding requis | Non | Oui (= ou == final) | Non (supprimé par convention) |
| Gestion des espaces | Échappé en %20 (ou + en formulaire) | Encodé comme tout autre octet | Encodé comme tout autre octet |
Le piège du « Base64 dans les URLs » : pourquoi le format standard casse les paramètres#
Une erreur d'implémentation très répandue consiste à injecter une chaîne Base64 standard directement dans l'URL d'une requête HTTP :
En production, cette requête échoue fréquemment de manière intermittente. Le format Base64 standard contient trois caractères incompatibles avec les spécifications de routage des URIs :
1. Le signe plus (+) se transforme en espace#
Dans les données application/x-www-form-urlencoded, utilisées par les formulaires HTML et de nombreux parseurs de requêtes, + représente une espace. La syntaxe de requête de la RFC 3986 ne donne pas elle-même ce sens à + : le comportement dépend du parseur.
Lorsque votre framework backend (Node.js Express, Python Django/Flask, Java Spring ou Go) parse le paramètre ?token=a+b/c=, il convertit automatiquement le + en espace littérale :
Lorsque votre serveur tente de décoder "a b/c=" en Base64, le décodeur rejette le caractère espace et déclenche une exception de décodage (Invalid character in Base64 string ou binascii.Error: Incorrect padding).
2. La barre oblique (/) casse le routage des chemins#
Si vous intégrez une chaîne Base64 standard dans le segment de chemin d'une URL (comme /api/v1/files/a+b/c=), les serveurs web tels que Nginx ou Apache interprètent / comme un séparateur de répertoires. La requête est alors acheminée vers une ressource inexistante /api/v1/files/a+b/ avec pour sous-chemin c=, renvoyant une erreur 404 Not Found.
Même si le slash est encodé en %2F, de nombreux reverse-proxies bloquent les slashes encodés par défaut par mesure de sécurité (notamment la directive Apache AllowEncodedSlashes Off destinée à contrer les attaques par traversée de répertoires).
3. Le signe égal (=) perturbe les parseurs de chaînes de requête#
Base64 utilise le symbole = comme caractère de remplissage final. Dans une chaîne de requête, = sépare le nom du paramètre de sa valeur (cle=valeur). Bien que les parseurs modernes gèrent généralement les = présents dans les valeurs, des expressions régulières ou des découpages naïfs peuvent être déstabilisés par ces caractères de fin.
La solution : Base64 adapté aux URLs (base64url)#
Pour éliminer définitivement cette incompatibilité, la section 5 de la RFC 4648 a introduit le standard Base64 adapté aux URLs (ou base64url).
Cette variante applique deux substitutions. Le remplissage peut être omis lorsque le protocole permet de déduire la longueur :
- Remplacer
+par le tiret- - Remplacer
/par le tiret bas_ - Omettre les
=finaux uniquement si le protocole l'autorise
Une valeur base64url sans remplissage ne contient que des caractères URI non réservés : elle s'insère généralement dans un segment, une valeur de requête ou un fragment sans encodage supplémentaire. La grammaire et le protocole environnants déterminent néanmoins les délimiteurs et le remplissage autorisés.
Les JSON Web Tokens utilisent des segments base64url sans remplissage, séparés par des points (en-tête.charge.signature). Placer un JWT dans une URL reste une décision de sécurité distincte, car les URLs peuvent être conservées dans l'historique, les journaux, les référents et les outils d'analyse.
Guide de décision : quel format utiliser ?#
Suivez cet arbre décisionnel pour déterminer le format approprié :
Cas pratiques courants :#
- Paramètre de recherche (
?q=c++ & python) : Utilisez l'encodage URL. Il transforme+en%2B, l'espace en%20et&en%26, générant?q=c%2B%2B%20%26%20python. - URL de redirection en paramètre (
?next=/dashboard?tab=facturation) : Utilisez l'encodage URL. L'URL cible doit être échappée avecencodeURIComponentafin que ses propres symboles?et=ne soient pas interprétés comme ceux de la requête principale. - Image intégrée en CSS ou HTML (
data:image/png;base64,...) : Utilisez Base64 Standard. La spécification Data URI impose l'alphabet Base64 standard. - Nouveau jeton opaque représentant des octets aléatoires : Base64URL est une représentation pratique. Traitez les codes OAuth et autres jetons fournis par un tiers comme des valeurs opaques sans les réencoder, sauf exigence explicite du protocole.
- Signature binaire dans une query string : Utilisez Base64URL. Si vous devez impérativement employer Base64 standard, appliquez ensuite un encodage URL sur la chaîne (
encodeURIComponent(base64)), maisbase64urldemeure bien plus élégant et concis.
Exemples d'implémentation en JavaScript et Python#
JavaScript / TypeScript#
L'environnement JavaScript moderne propose tous les outils nécessaires pour manipuler l'encodage URL et transformer des chaînes en base64url :
Python#
La bibliothèque standard de Python dispose de modules dédiés à la fois pour le traitement des URIs et pour le format base64url :
Foire aux questions#
Puis-je simplement encoder en URL une chaîne Base64 standard au lieu d'utiliser base64url ?#
Oui, appliquer un encodage URL sur du Base64 standard (en convertissant + en %2B, / en %2F et = en %3D) neutralise les erreurs de parsing dans les query strings. Néanmoins, cette approche est sous-optimale : elle allonge inutilement la charge utile, complique le débogage dans les logs d'accès et crée des risques de double-échappement entre microservices. L'emploi de Base64URL (base64url) est plus sobre, plus compact et constitue le standard universel recommandé par l'IETF.
Quelle est la différence entre encodeURI et encodeURIComponent en JavaScript ?#
encodeURI est conçu pour traiter une URL complète : il préserve l'ensemble des délimiteurs structurels du protocole (:, /, ?, #, &, =) et n'échappe que les caractères invalides comme les espaces ou les symboles Unicode. À l'inverse, encodeURIComponent cible un paramètre individuel : il échappe rigoureusement tous les caractères réservés (y compris /, ?, & et =). N'utilisez jamais encodeURI sur une valeur de paramètre, sous peine de laisser passer des séparateurs non échappés qui fausseront le découpage de la requête.
Doit-on encoder les espaces en %20 ou avec un signe plus (+) ?#
Privilégiez systématiquement %20 pour assurer une parfaite conformité avec la RFC 3986, dans les segments de chemin d'URL et au sein des API REST modernes. Le signe plus (+) n'est historiquement valide pour désigner une espace que dans les formulaires soumis avec le type MIME application/x-www-form-urlencoded. Dans un segment de chemin, un + est interprété comme le caractère littéral plus et non comme une espace. %20 est le seul format universellement sans ambiguïté.
Outils ToolPorta complémentaires#
Testez, convertissez et inspectez vos chaînes encodées directement dans votre navigateur :
- Utilisez l'outil Encodage & Décodage URL pour tester vos URLs et paramètres avec prise en charge du format RFC 3986 et des formulaires.
- Utilisez l'outil Encodage & Décodage Base64 pour convertir instantanément du texte ou des fichiers en Base64 standard ou Base64URL.
- Utilisez le Générateur de Hash pour calculer des empreintes SHA-256 ou MD5 et comparer leurs représentations hexadécimales et Base64.
- Consultez notre guide JavaScript d'encodage URL et des exemples équivalents en Python pour vos applications backend.