Les encodages de texte expliqués : UTF-8, Base64 et encodage d’URL
Les ordinateurs stockent et envoient des octets, pas des lettres. Chaque fois qu’un texte est enregistré, envoyé ou placé dans une adresse web, il faut décider quels octets représentent quels caractères, et parfois réécrire les octets eux-mêmes pour qu’ils arrivent intacts. Trois encodages font l’essentiel de ce travail : UTF-8 transforme les caractères en octets, Base64 transforme n’importe quels octets en lettres et chiffres ordinaires, et l’encodage-pourcent rend un texte sûr à l’intérieur d’une URL.
Cette dernière partie de la série explique chacun d’eux avec des exemples vérifiables octet par octet, et les relie aux problèmes vus dans les parties sur le JSON et le CSV : la marque d’ordre des octets et les accents qui deviennent ã.
Caractères, points de code et octets
Unicode attribue à chaque caractère un numéro, appelé point de code et écrit U+ suivi de chiffres hexadécimaux : A est U+0041, é est U+00E9, € est U+20AC et l’émoji 😀 est U+1F600. La plage va de U+0000 à U+10FFFF. Un encodage décide comment ces numéros sont stockés en octets.
UTF-8, défini dans la RFC 3629 (norme Internet depuis novembre 2003), utilise d’un à quatre octets par caractère. Les 128 caractères ASCII gardent leur octet unique, si bien qu’un texte anglais sans accents est identique en ASCII et en UTF-8 ; les autres caractères prennent deux, trois ou quatre octets :
A → 41Un octet, comme en ASCII.é → C3 A9Deux octets. Lus un par un en Windows-1252, ils s’affichent é.€ → E2 82 ACTrois octets.😀 → F0 9F 98 80Quatre octets, comme tout caractère au-delà de U+FFFF.
UTF-8 est aujourd’hui le choix par défaut presque partout : W3Techs l’a trouvé sur 99,1 % des sites web dont il a pu identifier l’encodage en octobre 2026. D’autres encodages existent pourtant encore à l’intérieur des logiciels. Les chaînes JavaScript, par exemple, sont stockées en UTF-16, en unités de 16 bits, et MDN précise qu’un caractère au-delà de U+FFFF en occupe deux. C’est pourquoi le même émoji compte pour 1 caractère à l’écran, 2 dans la longueur JavaScript et 4 octets en UTF-8, et pourquoi les limites mesurées en caractères et en octets coïncident rarement.
La marque d’ordre des octets
La marque d’ordre des octets (BOM), U+FEFF, peut figurer tout au début d’un fichier. En UTF-8, ce sont toujours les trois octets EF BB BF. UTF-8 n’a pas d’ordre des octets à indiquer : elle n’y sert que de signature pour dire que le fichier est en UTF-8. Le Consortium Unicode la déconseille lorsqu’un protocole ou un logiciel attend des caractères précis au début du fichier.
Les deux parties précédentes de la série la rencontrent par des côtés opposés. Un JSON envoyé sur le réseau ne doit pas commencer par elle, et JSON.parse de JavaScript rejette un texte qui en contient une. Excel, au contraire, en a besoin pour ouvrir correctement un CSV en UTF-8 par double-clic. L’ajouter ou non dépend du logiciel qui lira le fichier.
Base64 : n’importe quels octets en texte
Certains endroits n’acceptent que du texte : le corps d’un e-mail, une chaîne JSON, un attribut HTML. Base64, défini dans la RFC 4648 (octobre 2006), permet à n’importe quels octets, y compris une image ou un PDF, d’y passer. Il prend l’entrée trois octets (24 bits) à la fois et écrit chaque groupe sous forme de quatre caractères d’un alphabet de 64 : A–Z, a–z, 0–9, + et /. Quand le dernier groupe est incomplet, = le complète. Voici les vecteurs de test de la RFC :
f → Zg==Un octet : deux caractères de données et deux = de remplissage.fo → Zm8=Deux octets : trois caractères et un =.foo → Zm9vTrois octets remplissent un groupe entier : quatre caractères, sans remplissage.
Quatre caractères pour trois octets : Base64 est plus gros d’un tiers que l’original, et un fichier de 3 000 000 d’octets devient 4 000 000 de caractères. L’e-mail (MIME) coupe en plus le Base64 en lignes de 76 caractères au maximum, ce qui ajoute encore un peu.
Base64 est un encodage, pas un chiffrement. N’importe qui peut le décoder, sans clé : il ne protège rien. Si un mot de passe ou un jeton n’a l’air illisible que parce qu’il est en Base64, il n’est pas protégé.
Le texte doit devenir des octets avant d’être encodé en Base64 : le résultat dépend donc de l’encodage du texte. La lettre é donne w6k= à partir de ses deux octets UTF-8, mais 6Q== à partir de son unique octet en Latin-1. web.dev souligne que la fonction btoa() du navigateur n’accepte que les caractères qui tiennent sur un octet et renvoie une erreur pour les autres, comme € ; il faut d’abord convertir le texte en octets UTF-8. L’outil Base64 de nTools encode le texte en UTF-8 et, au décodage, indique si les octets étaient en UTF-8 ou en Windows-1252.
base64url : la version pour les adresses web
Deux des caractères de Base64 posent problème hors du texte ordinaire. Dans une URL, + peut être lu comme une espace et / sépare les segments du chemin ; dans un nom de fichier, / est interdit. La RFC 4648 définit donc un second alphabet, sûr pour les URL et les noms de fichiers, souvent appelé base64url, qui utilise - et _ à la place. Les spécifications qui l’emploient peuvent aussi omettre le remplissage =, ce que la RFC 4648 permet quand elles le précisent explicitement.
😀 → 8J+YgA== / 8J-YgABase64 standard, puis base64url : + devient - et le remplissage disparaît.??? → Pz8/ / Pz8_/ devient _.
Les JSON Web Tokens en sont l’exemple le plus connu. La RFC 7515 définit leur encodage comme du base64url sans aucun = final ni saut de ligne : c’est pourquoi les parties d’un jeton peuvent contenir - et _, mais jamais +, / ni =. Un décodeur qui ne connaît que le Base64 standard rejette ces chaînes ; l’outil nTools en fait partie, remplacez donc - par + et _ par / avant de décoder.
L’encodage-pourcent : du texte dans une URL
Une URL ne peut contenir qu’un ensemble limité de caractères ASCII, et certains ont un rôle : / sépare le chemin, ? ouvre la requête, & sépare les paramètres, # ouvre le fragment. La RFC 3986 (janvier 2005, norme Internet) en fixe les règles. Les lettres, les chiffres et - . _ ~ peuvent toujours être utilisés tels quels. Les caractères qui ont un rôle sont encodés quand ils font partie d’une valeur et non d’un séparateur, et tout octet hors de l’ensemble autorisé s’écrit % suivi de deux chiffres hexadécimaux. Le texte est d’abord converti en UTF-8 : un caractère hors ASCII devient donc plusieurs codes % :
a b&c=d → a%20b%26c%3DdEncodé comme une seule valeur : l’espace, & et = ne coupent plus la requête.café → caf%C3%A9Les deux octets UTF-8 de é, chacun en code %.😀 → %F0%9F%98%80Quatre octets, quatre codes %.100% → 100%25Un % littéral doit lui aussi être encodé, en %25, sinon le décodeur y voit le début d’un code.
Encodez les valeurs que vous placez dans une URL, pas l’adresse entière : encoder https://example.com/?q=1 comme une seule valeur transforme ses : / ? et = en codes, ce qui est correct quand l’adresse est elle-même un paramètre d’une autre URL, et faux quand elle doit servir de lien. La fonction encodeURIComponent() de JavaScript fait exactement cet encodage par valeur et, comme l’indique MDN, laisse aussi ! ' ( ) et * tels quels. L’outil URL de nTools l’utilise.
Un + ou %20 ?
Les formulaires HTML envoient leurs données dans un format un peu différent, application/x-www-form-urlencoded, défini par le standard URL du WHATWG. Une espace y est écrite +, si bien qu’une recherche de a b&c=d est envoyée sous la forme q=a+b%26c%3Dd. Ailleurs dans une URL, + n’est qu’un signe plus.
Cela explique une confusion fréquente : décoder a+b%20c avec un décodeur d’URL général donne a+b c, car seul %20 y est une espace ; un décodeur de formulaire donne a b c. Choisissez le décodeur qui correspond à l’origine du texte. MDN suggère de remplacer %20 par + après encodeURIComponent() quand vous avez besoin du format de formulaire.
Le double encodage
La RFC 3986 avertit qu’une chaîne ne doit pas être encodée ou décodée en pourcent plus d’une fois. Quand cela arrive, le % de chaque code est de nouveau encodé en %25 :
a b → a%20b → a%2520bEncodé deux fois : après un décodage, le texte affiche encore a%20b au lieu de a b.
Des séquences comme %2520 ou %25C3%25A9 dans une adresse indiquent qu’un texte déjà encodé a été encodé une seconde fois. Décodez une fois, vérifiez le résultat et n’encodez que les parties qui en ont besoin.
Lequel vous faut-il ?
| Situation | À utiliser |
|---|---|
| Enregistrer ou envoyer du texte : fichiers, pages web, JSON, CSV | UTF-8 |
| Mettre des octets, comme une image ou un fichier, dans du texte : JSON, e-mail, HTML | Base64 |
| Du Base64 dans une URL, un nom de fichier ou un jeton | base64url |
| Une valeur dans une URL : un terme de recherche, un paramètre, un segment de chemin | Encodage-pourcent |
| Les données envoyées par un formulaire HTML | Encodage de formulaire (espaces en +) |
| Garder des données secrètes | Aucun de ceux-ci : utilisez le chiffrement |
Questions fréquentes
Base64 est-il une forme de chiffrement ?
Non. C’est un encodage réversible que tout le monde peut décoder sans clé. Il permet aux données de voyager sous forme de texte, pas d’échapper à la lecture.
Pourquoi mon Base64 diffère-t-il de celui d’un autre outil ?
En général parce que le texte a été converti en octets avec un autre encodage, comme le Latin-1 au lieu de l’UTF-8, parce qu’un outil utilise base64url ou omet le remplissage =, ou parce que l’un des deux ajoute des sauts de ligne.
Pourquoi un émoji compte-t-il pour deux caractères ?
Beaucoup de logiciels, dont JavaScript, comptent des unités UTF-16 de 16 bits, et un émoji comme 😀, au-delà de U+FFFF, en demande deux. En UTF-8, il occupe quatre octets.
Faut-il enregistrer les fichiers en UTF-8 avec BOM ?
Seulement quand le logiciel qui lit le fichier en a besoin, comme Excel avec les fichiers CSV. Pour le JSON et la plupart des fichiers web, enregistrez en UTF-8 sans BOM.
Pourquoi mon lien contient-il %2520 ?
Il a été encodé deux fois : %20, une espace, a été encodé de nouveau et son % est devenu %25. Décodez-le une fois et utilisez le résultat.
Les encodeurs nTools envoient-ils mon texte ?
Non. L’encodage et le décodage se font dans votre navigateur, et le texte n’est envoyé nulle part.
Partie précédente ← Les fichiers CSV expliqués : séparateurs, guillemets, encodage et Excel
Références
- RFC 3629 — UTF-8, a transformation format of ISO 10646
- Unicode Consortium — FAQ: UTF-8, UTF-16, UTF-32 & BOM
- W3Techs — Usage statistics of character encodings for websites
- MDN — UTF-16 (glossary)
- RFC 8259 — The JavaScript Object Notation (JSON) Data Interchange Format
- Microsoft Support — Opening CSV UTF-8 files correctly in Excel
- RFC 4648 — The Base16, Base32, and Base64 Data Encodings
- web.dev — The nuances of base64 encoding strings in JavaScript
- RFC 7515 — JSON Web Signature (JWS)
- RFC 3986 — Uniform Resource Identifier (URI): Generic Syntax
- WHATWG — URL Standard
- MDN — encodeURIComponent()
Guides associés
- Les adresses IP expliquées : IPv4, IPv6 et les plages réservées
- Les sous-réseaux et le CIDR expliqués : préfixes, masques et hôtes utilisables
- Les enregistrements DNS expliqués : A, AAAA, CNAME, MX, TXT et NS
- Un site est-il en panne, ou est-ce chez vous ? Comment vérifier, étape par étape
- Codes de statut HTTP et erreurs Cloudflare : ce que signifient 403, 404, 429, 500, 503 et 521
- Les timestamps Unix et les fuseaux horaires expliqués
- Compter les dates : jours entre deux dates, années bissextiles et semaines ISO
- Les formats d’image expliqués : JPEG, PNG, WebP, AVIF et HEIC
- La taille d’une image expliquée : pixels, DPI, poids et qualité
- Les photos de téléphone expliquées : HEIC, métadonnées EXIF et vie privée
- La robustesse des mots de passe expliquée : longueur, entropie et phrases de passe
- Le hachage expliqué : SHA-256, sommes de contrôle et mots de passe
- Les JSON Web Tokens expliqués : revendications, signatures, validation sûre
- Les UUID expliqués : v4, v7 et comment choisir la bonne version
- Les QR codes expliqués : capacité, correction d’erreurs et taille d’impression
- Les pourcentages et la TVA expliqués : ajouter, retirer et cumuler
- Erreurs JSON courantes et comment les corriger
- Les fichiers CSV expliqués : séparateurs, guillemets, encodage et Excel
- Modifier des PDF dans le navigateur : ce que la fusion, la division et la conversion conservent