Base64 est une façon de représenter des données binaires (une image, un PDF, des octets arbitraires) avec seulement 64 caractères de texte imprimables : les lettres A-Z et a-z, les chiffres 0-9 et les symboles + et /, avec = comme remplissage. Il sert à transporter du binaire par des canaux conçus pour le texte, comme JSON, le courrier électronique, les URL ou les attributs HTML. Il augmente la taille d’environ 33 % et n’est pas du chiffrement : n’importe qui peut le décoder.
Cet article explique son fonctionnement, quand il a du sens (et quand il n’en a pas) et comment encoder et décoder correctement en JavaScript, Node.js et dans le terminal, y compris le cas des caractères non ASCII qui fait échouer btoa.
Comment ça marche
Base64 prend les données 3 octets (24 bits) à la fois et les répartit en 4 groupes de 6 bits. Chaque groupe de 6 bits (une valeur de 0 à 63) est remplacé par un caractère de la table. Si la longueur n’est pas un multiple de 3, on ajoute un ou deux = à la fin pour compléter le dernier bloc.
D’où le coût : chaque 3 octets deviennent 4 caractères, donc le résultat occupe 4/3 de l’original (33 % de plus), arrondi au multiple de 4 supérieur. Par exemple, la chaîne Año 2026 ñ occupe 12 octets en UTF-8 et son Base64, QcOxbyAyMDI2IMOx, fait 16 caractères.
La spécification complète est la RFC 4648, qui définit aussi la variante URL-safe : elle remplace + par - et / par _ pour que le résultat puisse figurer dans une URL ou un nom de fichier sans échappement. Les jetons JWT utilisent cette variante, généralement sans remplissage.
Quand utiliser Base64
- Intégrer une petite ressource dans du HTML, du CSS ou du JSON : une icône SVG ou PNG de quelques Ko en data URL évite une requête HTTP.
- Envoyer du binaire dans une API JSON quand vous ne pouvez pas utiliser
multipart/form-data. - Pièces jointes de courrier : le standard MIME encode les pièces jointes en Base64 parce que le courrier est un protocole texte.
- Authentification HTTP basique : l’en-tête
Authorization: Basic ...transporteutilisateur:motdepasseen Base64. Cela ne le protège pas : c’est pourquoi cela n’a de sens qu’en HTTPS. - Clés et certificats au format PEM, qui sont du Base64 entre des lignes
-----BEGIN ... -----.
Quand ne pas l’utiliser
- Pour « cacher » de l’information. Base64 se décode en une ligne de code. Si vous avez besoin de confidentialité, chiffrez.
- Pour de grandes images en HTML. Une photo de 300 Ko en Base64 passe à 400 Ko, n’est pas mise en cache séparément et bloque l’analyse du HTML. Au-delà de quelques Ko, servez le fichier avec sa propre URL (et convertissez-le en WebP).
- Pour du texte normal en JSON. JSON transporte déjà du texte Unicode ; l’encoder en Base64 n’ajoute que 33 % de poids.
Encoder et décoder
Dans le navigateur : btoa et atob (avec précaution)
btoa() et atob() travaillent avec des chaînes d’octets Latin-1, pas du texte Unicode. Avec des caractères hors de cette plage (un ñ fonctionne, un emoji ou des caractères asiatiques non), btoa lève InvalidCharacterError. La bonne approche est de passer d’abord par TextEncoder :
// Encoder du texte UTF-8 en Base64
function toBase64(texte) {
const octets = new TextEncoder().encode(texte);
let binaire = '';
for (const b of octets) binaire += String.fromCharCode(b);
return btoa(binaire);
}
// Décoder du Base64 en texte UTF-8
function fromBase64(b64) {
const binaire = atob(b64);
const octets = Uint8Array.from(binaire, (c) => c.charCodeAt(0));
return new TextDecoder().decode(octets);
}
toBase64('Año 2026 ñ'); // "QcOxbyAyMDI2IMOx"
fromBase64('QcOxbyAyMDI2IMOx'); // "Año 2026 ñ"
Pour des fichiers (par exemple une image choisie par l’utilisateur), utilisez FileReader.readAsDataURL(), qui renvoie directement une data URL avec le contenu en Base64.
Dans Node.js : Buffer
const b64 = Buffer.from('Año 2026 ñ', 'utf8').toString('base64'); // "QcOxbyAyMDI2IMOx"
const texte = Buffer.from(b64, 'base64').toString('utf8'); // "Año 2026 ñ"
// Variante URL-safe (sans + / =)
const urlSafe = Buffer.from('Año 2026 ñ').toString('base64url');
// Un fichier complet
import { readFile } from 'node:fs/promises';
const png = await readFile('icone.png');
const dataUrl = `data:image/png;base64,${png.toString('base64')}`;
Buffer gère correctement l’encodage des caractères, donc pas besoin du détour par TextEncoder.
Dans le terminal
# Encoder un fichier (GNU coreutils, Linux)
base64 image.png > image.b64
# Décoder
base64 -d image.b64 > image.png
# Encoder une chaîne sans le saut de ligne final
printf 'Año 2026 ñ' | base64
Sur macOS, l’option de décodage est -D dans les anciennes versions et -d ou --decode dans les récentes. Par défaut, l’outil GNU découpe la sortie en lignes de 76 caractères ; -w 0 l’évite.
Sans rien installer
Pour une conversion ponctuelle, l’encodeur d’AIMRAN Tools encode et décode du Base64 dans le navigateur, sans envoyer le contenu à aucun serveur. C’est l’option pratique pour inspecter un jeton, une pièce jointe ou une data URL.
Les data URL
Une data URL intègre le contenu dans l’adresse elle-même : data:[type MIME][;base64],données.
<img src="data:image/svg+xml;base64,PHN2ZyB4bWxucz0iaHR0cDovL3d3dy53My5vcmcvMjAwMC9zdmciIHdpZHRoPSIxMCIgaGVpZ2h0PSIxMCI+PC9zdmc+" alt="" width="10" height="10" />
Utiles pour de petites icônes et des fonds CSS minimes. Pour du SVG, il est souvent plus compact de l’intégrer en texte échappé pour URL qu’en Base64.
Erreurs fréquentes
- Utiliser
btoaavec du texte Unicode sans passer parTextEncoder:InvalidCharacterError. - Oublier le type MIME dans une data URL : le navigateur ne sait pas quoi faire des octets.
- Mélanger la variante standard et la variante URL-safe : un
+décodé comme-corrompt les données. Utilisez la même variante aux deux extrémités. - Prendre Base64 pour de la sécurité : des identifiants « encodés » dans un fichier public sont des identifiants publics.
- Intégrer des ressources volumineuses : plus de poids, pas de cache et un HTML plus lent à analyser.
Conclusion
Base64 résout un problème précis : faire passer des octets par un canal texte. Faites-le avec Buffer dans Node.js, avec TextEncoder + btoa dans le navigateur ou avec base64 dans le terminal, utilisez la variante URL-safe quand le résultat va dans une URL, et rappelez-vous ses deux limites : il augmente la taille d’un tiers et ne protège rien.