Skip to content

Comparison

Base64 vs base64url : deux caractères qui changent tout

Même alphabet, deux derniers caractères différents, rembourrage différent. Une ligne de différence, des cas d’usage totalement distincts.

By Published

En bref. Base64 et base64url sont le même encodage à trois détails près définis dans la RFC 4648 : + devient -, / devient _, et le rembourrage =est supprimé. Utilisez base64url partout où la valeur encodée transite dans une URL, un JWT ou un cookie signé ; utilisez le Base64 standard pour les pièces jointes d’e-mail, l’authentification HTTP Basic et les URI de données.

Les deux sont définis dans la RFC 4648. Base64 standard (§4) et base64url(§5) diffèrent exactement sur trois points : deux substitutions d’alphabet et le traitement du rembourrage. C’est tout. Mais les mélanger casse les JWT, les cookies signés et tout ce qui transite dans une URL.

La différence

PropriétéBase64 standardBase64url
62e caractère+-
63e caractère/_
Rembourrage= jusqu’au multiple de 4Généralement omis
Compatible URL ?Non (+, /, = nécessitent un encodage pourcent)Oui
Défini dansRFC 4648 §4RFC 4648 §5

La même entrée, les deux encodages

Encodage de https://example.com/?q=hello world :

  • Standard : aHR0cHM6Ly9leGFtcGxlLmNvbS8/cT1oZWxsbyB3b3JsZA==
  • Base64url : aHR0cHM6Ly9leGFtcGxlLmNvbS8_cT1oZWxsbyB3b3JsZA

Notez que le / dans la forme standard devient_ en base64url, et le == final est supprimé.

Pourquoi les URL ont besoin de leur propre variante

L’alphabet Base64 standard inclut + et/. Les deux sont réservés dans la syntaxe URL :

  • / est le séparateur de chemin.
  • + est, par convention dans les chaînes de requête encodées en formulaire, interprété comme un espace.
  • = est le délimiteur clé-valeur dans les chaînes de requête.

Intégrer une chaîne Base64 standard dans une URL nécessite d’encoder en pourcent les trois : + devient%2B, / devient %2F,= devient %3D. La chaîne s’allonge et devient moins lisible. base64url évite l’encodage pourcent en choisissant des caractères déjà compatibles avec les URL.

Pourquoi le rembourrage est optionnel en base64url

Le Base64 standard complète toujours la sortie à un multiple de 4 caractères en utilisant =. Ce n’est pas mathématiquement nécessaire — le décodeur peut déduire la longueur originale depuis la longueur de sortie modulo 4. Le rembourrage existe pour les décodeurs en flux continu qui doivent connaître la frontière entre des segments concaténés.

base64url supprime le rembourrage car : (a) il est redondant, (b) =nécessite un encodage pourcent dans les URL, et (c) les signes égal en fin d’URL perturbent parfois les analyseurs de chemin, les CDN et les clés de cache.

Cas d’usage de chacun

Cas d’usageVariante
Pièces jointes e-mail (MIME)Base64 standard
HTTP Basic Auth (Authorization: Basic …)Base64 standard
URI de données (data:image/png;base64,…)Base64 standard
JWT (les trois segments)Base64url, sans rembourrage
Vérificateur/défi PKCE OAuth 2.0Base64url, sans rembourrage
Clés WebPush, JOSE/JWS/JWEBase64url, sans rembourrage
Cookies signés (Rails, Django, etc.)Base64url, sans rembourrage

Le piège du décodage

Le décodeur Base64 par défaut de nombreuses bibliothèques échoue sur une entrée base64url. base64.b64decode de Python rejette - et _ ;Buffer.from(s, "base64")de Node.js est permissif mais l’inverse (.toString("base64")) produit du Base64 standard.

Astuce multi-langage : remplacez avant de décoder.

// base64url → Base64 standard
const standard = base64url
  .replace(/-/g, "+")
  .replace(/_/g, "/")
  .padEnd(Math.ceil(base64url.length / 4) * 4, "=");

Mieux : utilisez une bibliothèque qui supporte explicitement base64url (Node 16+ a Buffer.from(s, "base64url") ; Python a base64.urlsafe_b64decode).

La règle pragmatique

Si la valeur encodée apparaîtra dans une URL, un JWT, un cookie signé ou un segment de chemin — utilisez base64url. Si c’est pour une pièce jointe e-mail, un en-tête HTTP (autre que les cookies) ou une URI de données JSON — utilisez le Base64 standard.

Notre encodeur Base64gère les deux variantes, avec un commutateur pour l’alphabet. Le décodeur JWTsuppose base64url car la norme l’exige.

Données numériques

  • Longueur encodée : les deux variantes expandent les données binaires exactement de 4/3 (ceil(n/3)*4). 100 octets d’entrée → 136 caractères en Base64 standard, ou 134 caractères sans rembourrage en base64url.
  • Surcharge du rembourrage : le Base64 standard ajoute 0, 1 ou 2 caractères = par chaîne encodée — au plus une pénalité de taille de 1,5 % pour les charges utiles courtes, négligeable pour les longues.
  • Coût de l’encodage pourcent dans les URL : chaque + / = en Base64 standard s’étend à 3 octets (%2B %2F %3D) quand encodé en URL. Pour un JWT de 512 caractères, cela représente typiquement 30 à 60 octets gaspillés — base64url l’évite entièrement.
  • Taille de l’alphabet : 64 caractères dans les deux, donc chaque caractère de sortie transporte exactement 6 bits d’entrée.
  • Tailles de segments JWT (RFC 7519) : en-tête typique 40-50 caractères, charge utile 100-400 caractères, signature HS256 43 caractères (exactement 32 octets / 6 = 43 caractères base64url, sans rembourrage).
  • Débit : Buffer.from(s, "base64") de Node 20 décode à ~2 Go/s ; base64.b64decode de Python à ~600 Mo/s sur un ordinateur portable 2024.

Matrice de décision

Où vit la valeurChoisir
Chemin ou chaîne de requête URLbase64url, sans rembourrage
JWT (en-tête / charge utile / signature)base64url, sans rembourrage (RFC 7519)
Vérificateur PKCE OAuth 2.0base64url, sans rembourrage (RFC 7636 §4.1)
Cookie signé (Rails / Django / Express)base64url, sans rembourrage
URI data: en HTML/CSSBase64 standard avec rembourrage
Pièce jointe e-mail MIMEBase64 standard avec rembourrage, saut de ligne 76 caractères (RFC 2045)
En-tête HTTP Basic AuthBase64 standard (RFC 7617)
Clés d’abonnement WebPushbase64url, sans rembourrage (RFC 8291)

Sources

Frequently asked questions

Puis-je décoder du base64url avec un décodeur Base64 standard ?
Parfois — Buffer.from de Node est permissif, b64decode de Python ne l’est pas. L’approche sûre en multi-langage : remplacez '-' par '+', '_' par '/', et complétez jusqu’à un multiple de 4 avec '=' avant de décoder. Les environnements modernes fournissent des décodeurs base64url explicites (Node 16+, urlsafe_b64decode de Python) qui gèrent cela directement.
Pourquoi base64url supprime-t-il le rembourrage ?
Trois raisons : il est mathématiquement redondant (les décodeurs peuvent déduire la longueur originale depuis la longueur de sortie modulo 4), le caractère '=' nécessite un encodage pourcent dans les URL, et le '=' en fin de chaîne perturbe certains analyseurs de chemin, CDN et clés de cache.
Les segments JWT sont-ils toujours en base64url ?
Oui. La RFC 7519 impose base64url sans rembourrage pour les trois segments JWT (en-tête, charge utile, signature). Encoder un JWT en Base64 standard produit un jeton qui ne sera pas vérifié par une bibliothèque conforme.
Base64url économise-t-il des octets par rapport au Base64 standard ?
Marginalement — la même taille d’alphabet signifie la même longueur encodée avant rembourrage. La suppression du rembourrage économise 0 à 2 octets par encodage. La vraie économie vient d’éviter l’encodage pourcent (chaque %XX représente 3 octets pour 1), ce qui peut économiser 6 à 9 octets par chaîne Base64 dans une URL.

Related

Published May 16, 2026