Skip to content

Comparison

Base64 vs base64url: due caratteri che fanno la differenza

Stesso alfabeto, ultimi due caratteri diversi, padding diverso. Una riga di differenza, casi d’uso completamente diversi.

By Published

In sintesi. Base64 e base64url sono la stessa codifica tranne per tre dettagli definiti in RFC 4648: + diventa -, / diventa _, e il padding = viene eliminato. Usa base64url ovunque il valore codificato viaggi in un URL, JWT o cookie firmato; usa Base64 standard per gli allegati email, HTTP Basic Auth e data URI.

Entrambi sono definiti in RFC 4648. Il Base64standard (§4) e il base64url(§5) differiscono in esattamente tre dettagli: due sostituzioni nell’alfabeto e il trattamento del padding. Tutto qui. Ma confonderli rompe i JWT, i cookie firmati e tutto ciò che viaggia in un URL.

La differenza

ProprietàBase64 standardBase64url
62° carattere+-
63° carattere/_
Padding= fino a multiplo di 4Di norma omesso
Sicuro per URL?No (+, /, = richiedono percent-encoding)
Definito inRFC 4648 §4RFC 4648 §5

Lo stesso input, entrambe le codifiche

Codifica di https://example.com/?q=hello world:

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

Si noti che la / nella forma standard diventa_ in base64url, e il == finale viene eliminato.

Perché gli URL hanno bisogno della propria variante

L’alfabeto Base64 standard include + e/. Entrambi sono riservati nella sintassi degli URL:

  • / è il separatore di percorso.
  • + è, per convenzione nelle query string codificate come form, interpretato come spazio.
  • = è il delimitatore chiave-valore nelle query string.

Incorporare una stringa Base64 standard in un URL richiede la percent-encoding di tutti e tre: + diventa%2B, / diventa %2F,= diventa %3D. La stringa si allunga e diventa più difficile da leggere. base64url evita la percent-encoding scegliendo caratteri già sicuri per gli URL.

Perché il padding è opzionale in base64url

Base64 standard aggiunge sempre padding all’output fino a multiplo di 4 caratteri usando =. Questo non è matematicamente necessario — il decoder può ricavare la lunghezza originale dalla lunghezza dell’output modulo 4. Il padding esiste per i decoder in streaming che devono conoscere il confine tra chunk concatenati.

Base64url omette il padding perché: (a) è ridondante, (b) = richiede la percent-encoding negli URL, e (c) i segni uguali finali negli URL a volte confondono i parser di percorso, i CDN e le chiavi di cache.

Dove viene usato ciascuno

Caso d’usoVariante
Allegati email (MIME)Base64 standard
HTTP Basic Auth (Authorization: Basic …)Base64 standard
Data URI (data:image/png;base64,…)Base64 standard
JWT (tutti e tre i segmenti)Base64url, senza padding
OAuth 2.0 PKCE code verifier/challengeBase64url, senza padding
Chiavi WebPush, JOSE/JWS/JWEBase64url, senza padding
Cookie firmati (Rails, Django, ecc.)Base64url, senza padding

Il problema della decodifica

Il decoder Base64 predefinito di molte librerie fallisce sull’input base64url. base64.b64decode di Python rifiuta -e _; Buffer.from(s, "base64")di Node.js è permissivo ma l’inverso (.toString("base64")) produce Base64 standard.

Hack cross-linguaggio: sostituire prima di decodificare.

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

Meglio ancora: usare una libreria che supporti esplicitamente base64url (Node 16+ ha Buffer.from(s, "base64url"); Python ha base64.urlsafe_b64decode).

La regola pratica

Se il valore codificato apparirà in un URL, in un JWT, in un cookie firmato o come segmento di percorso — usa base64url. Se è per un allegato email, un header HTTP (diverso dai cookie), o un data URI JSON — usa Base64 standard.

Il nostro codificatore Base64gestisce entrambe le varianti, con un selettore per l’alfabeto. Il decoder JWT presuppone base64url perché lo standard lo richiede.

Dati numerici

  • Lunghezza codificata: entrambe le varianti espandono il binario esattamente di 4/3 (ceil(n/3)*4). 100 byte di input → 136 caratteri di output in Base64 standard, o 134 caratteri senza padding in base64url.
  • Overhead del padding: Base64 standard aggiunge 0, 1 o 2 caratteri = per stringa codificata — al massimo un incremento del 1,5% per payload brevi, trascurabile per quelli lunghi.
  • Costo della percent-encoding negli URL: ogni + / = in Base64 standard si espande a 3 byte (%2B %2F %3D) quando codificato per URL. Per un JWT di 512 caratteri, si sprecano tipicamente 30-60 byte — base64url li evita completamente.
  • Dimensione dell’alfabeto: 64 caratteri in entrambe, quindi ogni carattere di output trasporta esattamente 6 bit di input.
  • Dimensioni segmenti JWT (RFC 7519): header tipico 40-50 caratteri, payload 100-400 caratteri, firma HS256 43 caratteri (esattamente 32 byte / 6 = 43 caratteri base64url, senza padding).
  • Throughput: Buffer.from(s, "base64") di Node 20 decodifica a ~2 GB/s; base64.b64decode di Python a ~600 MB/s su un laptop del 2024.

Matrice decisionale

Dove vive il valoreScegli
Percorso URL o query stringbase64url, senza padding
JWT (header / payload / firma)base64url, senza padding (RFC 7519)
OAuth 2.0 PKCE verifierbase64url, senza padding (RFC 7636 §4.1)
Cookie firmato (Rails / Django / Express)base64url, senza padding
URI data: in HTML/CSSBase64 standard con padding
Allegato email MIMEBase64 standard con padding, a capo ogni 76 caratteri (RFC 2045)
Header HTTP Basic AuthBase64 standard (RFC 7617)
Chiavi sottoscrizione WebPushbase64url, senza padding (RFC 8291)

Fonti

Frequently asked questions

Posso decodificare base64url con un decoder Base64 standard?
A volte — Buffer.from di Node è permissivo, b64decode di Python non lo è. L'approccio sicuro per ogni linguaggio: sostituire '-' con '+', '_' con '/', e aggiungere '=' fino a multiplo di 4 prima della decodifica. I runtime moderni offrono decoder base64url espliciti (Node 16+, urlsafe_b64decode di Python) che gestiscono questo direttamente.
Perché base64url elimina il padding?
Tre motivi: è matematicamente ridondante (i decoder possono ricavare la lunghezza originale dalla lunghezza dell'output mod 4), il carattere '=' richiede la percent-encoding negli URL, e i '=' finali confondono alcuni parser di percorso, CDN e chiavi di cache.
I segmenti JWT sono sempre in base64url?
Sì. RFC 7519 impone base64url senza padding per tutti e tre i segmenti JWT (header, payload, firma). Codificare un JWT con Base64 standard produce un token che non verrà verificato da nessuna libreria conforme.
Base64url risparmia byte rispetto a Base64 standard?
Marginalmente — stesso numero di caratteri dell'alfabeto significa stessa lunghezza codificata prima del padding. Eliminare il padding risparmia 0-2 byte per codifica. Il vero risparmio è evitare la percent-encoding (ogni %XX sono 3 byte per 1), che può risparmiare 6-9 byte per stringa Base64 in un URL.

Related

Published May 16, 2026