Le codifiche del testo spiegate: UTF-8, Base64 e codifica URL
I computer memorizzano e inviano byte, non lettere. Ogni volta che un testo viene salvato, inviato o inserito in un indirizzo web, qualcosa deve decidere quali byte rappresentano quali caratteri, e a volte i byte stessi vanno riscritti perché arrivino intatti. Tre codifiche fanno quasi tutto questo lavoro: UTF-8 trasforma i caratteri in byte, Base64 trasforma qualsiasi byte in lettere e cifre comuni e la codifica percentuale rende un testo sicuro dentro un URL.
Quest’ultima parte della serie spiega ciascuna con esempi verificabili byte per byte e le collega ai problemi visti nelle parti su JSON e CSV: il byte order mark e gli accenti che diventano ã.
Caratteri, punti di codice e byte
Unicode assegna a ogni carattere un numero, detto punto di codice e scritto come U+ seguito da cifre esadecimali: A è U+0041, é è U+00E9, € è U+20AC e l’emoji 😀 è U+1F600. L’intervallo va da U+0000 a U+10FFFF. Una codifica stabilisce come quei numeri vengono memorizzati in byte.
UTF-8, definito nella RFC 3629 (standard Internet da novembre 2003), usa da uno a quattro byte per carattere. I 128 caratteri ASCII mantengono il loro unico byte, così un testo inglese senza accenti è identico in ASCII e in UTF-8; gli altri caratteri occupano due, tre o quattro byte:
A → 41Un byte, come in ASCII.é → C3 A9Due byte. Letti uno alla volta come Windows-1252, appaiono come é.€ → E2 82 ACTre byte.😀 → F0 9F 98 80Quattro byte, come ogni carattere oltre U+FFFF.
Oggi UTF-8 è la scelta predefinita quasi ovunque: W3Techs l’ha trovato sul 99,1% dei siti web di cui ha potuto identificare la codifica nell’ottobre 2026. All’interno dei programmi esistono però ancora altre codifiche. Le stringhe JavaScript, per esempio, sono memorizzate in UTF-16, in unità da 16 bit, e MDN osserva che un carattere oltre U+FFFF ne occupa due. Per questo la stessa emoji conta come 1 carattere sullo schermo, 2 nella lunghezza JavaScript e 4 byte in UTF-8, e per questo i limiti misurati in caratteri e in byte raramente coincidono.
Il byte order mark
Il byte order mark (BOM), U+FEFF, può trovarsi proprio all’inizio di un file. In UTF-8 sono sempre i tre byte EF BB BF. UTF-8 non ha un ordine dei byte da segnalare, quindi lì serve solo come firma che dice che il file è in UTF-8. Il Consorzio Unicode lo sconsiglia quando un protocollo o un programma si aspetta caratteri precisi all’inizio del file.
Le due parti precedenti della serie lo incontrano da lati opposti. Un JSON inviato in rete non deve iniziare con esso, e JSON.parse di JavaScript rifiuta il testo che lo contiene. Excel invece ne ha bisogno per aprire correttamente un CSV in UTF-8 con un doppio clic. Aggiungerlo o no dipende dal programma che leggerà il file.
Base64: qualsiasi byte come testo
Alcuni posti accettano solo testo: il corpo di un’email, una stringa JSON, un attributo HTML. Base64, definito nella RFC 4648 (ottobre 2006), permette a qualsiasi byte, anche un’immagine o un PDF, di passarci. Prende l’input tre byte (24 bit) alla volta e scrive ogni gruppo come quattro caratteri di un alfabeto di 64: A–Z, a–z, 0–9, + e /. Quando l’ultimo gruppo è incompleto, = lo completa. Questi sono i vettori di prova della RFC:
f → Zg==Un byte: due caratteri di dati e due = di riempimento.fo → Zm8=Due byte: tre caratteri e un =.foo → Zm9vTre byte riempiono un gruppo intero: quattro caratteri, nessun riempimento.
Quattro caratteri ogni tre byte significa che Base64 è più grande di un terzo rispetto all’originale: un file di 3.000.000 di byte diventa 4.000.000 di caratteri. L’email (MIME) inoltre spezza il Base64 in righe di al massimo 76 caratteri, il che aggiunge ancora qualcosa.
Base64 è una codifica, non una cifratura. Chiunque può decodificarlo, senza chiave, quindi non protegge nulla. Se una password o un token sembrano illeggibili solo perché sono in Base64, non sono protetti.
Il testo deve diventare byte prima di essere codificato in Base64, quindi il risultato dipende dalla codifica del testo. La lettera é dà w6k= dai suoi due byte UTF-8, ma 6Q== dal suo unico byte in Latin-1. web.dev fa notare che la funzione btoa() del browser accetta solo caratteri che stanno in un byte e dà errore con gli altri, come €; il testo va prima convertito in byte UTF-8. Lo strumento Base64 di nTools codifica il testo in UTF-8 e, in decodifica, indica se i byte erano UTF-8 o Windows-1252.
base64url: la versione per gli indirizzi web
Due dei caratteri di Base64 creano problemi fuori dal testo normale. In un URL, + può essere letto come uno spazio e / separa i segmenti del percorso; in un nome di file, / non è ammesso. Per questo la RFC 4648 definisce un secondo alfabeto, sicuro per URL e nomi di file, di solito chiamato base64url, che usa - e _ al loro posto. Le specifiche che lo usano possono anche omettere il riempimento =, cosa che la RFC 4648 consente quando lo dicono esplicitamente.
😀 → 8J+YgA== / 8J-YgABase64 standard, poi base64url: + diventa - e il riempimento sparisce.??? → Pz8/ / Pz8_/ diventa _.
I JSON Web Token sono l’esempio più noto. La RFC 7515 definisce la loro codifica come base64url senza alcun = finale e senza a capo, ed è per questo che le parti di un token possono contenere - e _ ma mai +, / o =. Un decodificatore che conosce solo il Base64 standard rifiuta queste stringhe; lo strumento di nTools è tra questi, quindi sostituisci - con + e _ con / prima di decodificare.
Codifica percentuale: testo dentro un URL
Un URL può contenere solo un insieme limitato di caratteri ASCII, e alcuni hanno un compito: / separa il percorso, ? apre la query, & separa i parametri, # apre il frammento. La RFC 3986 (gennaio 2005, standard Internet) fissa le regole. Lettere, cifre e - . _ ~ si possono sempre usare così come sono. I caratteri con un compito vengono codificati quando fanno parte di un valore e non fanno da separatore, e ogni byte fuori dall’insieme ammesso si scrive come % seguito da due cifre esadecimali. Il testo viene prima convertito in UTF-8, quindi un carattere fuori dall’ASCII diventa più codici %:
a b&c=d → a%20b%26c%3DdCodificato come un unico valore: lo spazio, & e = non dividono più la query.café → caf%C3%A9I due byte UTF-8 di é, ciascuno come codice %.😀 → %F0%9F%98%80Quattro byte, quattro codici %.100% → 100%25Anche un % letterale va codificato, come %25, altrimenti il decodificatore lo legge come l’inizio di un codice.
Codifica i valori che inserisci in un URL, non l’indirizzo intero: codificare https://example.com/?q=1 come un unico valore trasforma : / ? e = in codici, il che è giusto quando l’indirizzo è a sua volta un parametro di un altro URL e sbagliato quando deve funzionare come link. La funzione encodeURIComponent() di JavaScript fa proprio questa codifica per valore e, come elenca MDN, lascia invariati anche ! ' ( ) e *. Lo strumento URL di nTools la usa.
Un + o %20?
I moduli HTML inviano i dati in un formato leggermente diverso, application/x-www-form-urlencoded, definito dallo standard URL del WHATWG. In questo formato uno spazio si scrive +, quindi una ricerca di a b&c=d viene inviata come q=a+b%26c%3Dd. Altrove in un URL, + è solo un segno più.
Questo spiega un equivoco frequente: decodificare a+b%20c con un decodificatore URL generico dà a+b c, perché lì solo %20 è uno spazio; un decodificatore per moduli dà a b c. Scegli il decodificatore adatto alla provenienza del testo. MDN suggerisce di sostituire %20 con + dopo encodeURIComponent() quando serve il formato dei moduli.
Doppia codifica
La RFC 3986 avverte che una stringa non deve essere codificata o decodificata in percentuale più di una volta. Quando succede, il % di ogni codice viene codificato di nuovo come %25:
a b → a%20b → a%2520bCodificato due volte: dopo una decodifica il testo dice ancora a%20b invece di a b.
Sequenze come %2520 o %25C3%25A9 in un indirizzo indicano che qualcosa ha codificato un testo già codificato. Decodifica una volta, controlla il risultato e codifica solo le parti che ne hanno bisogno.
Quale ti serve?
| Situazione | Usa |
|---|---|
| Salvare o inviare testo: file, pagine web, JSON, CSV | UTF-8 |
| Mettere byte, come un’immagine o un file, dentro un testo: JSON, email, HTML | Base64 |
| Base64 dentro un URL, un nome di file o un token | base64url |
| Un valore dentro un URL: un termine di ricerca, un parametro, un segmento del percorso | Codifica percentuale |
| Dati inviati da un modulo HTML | Codifica dei moduli (spazi come +) |
| Tenere segreti i dati | Nessuna di queste: usa la cifratura |
Domande frequenti
Base64 è una forma di cifratura?
No. È una codifica reversibile che chiunque può decodificare senza chiave. Rende i dati trasportabili come testo, non al sicuro dalla lettura.
Perché il mio Base64 è diverso da quello di un altro strumento?
Di solito perché il testo è stato convertito in byte con un’altra codifica, come Latin-1 invece di UTF-8, perché uno strumento usa base64url od omette il riempimento =, oppure perché uno aggiunge degli a capo.
Perché un’emoji conta come due caratteri?
Molti programmi, tra cui JavaScript, contano unità UTF-16 da 16 bit, e un’emoji come 😀, oltre U+FFFF, ne richiede due. In UTF-8 occupa quattro byte.
Devo salvare i file in UTF-8 con BOM?
Solo quando il programma che legge il file ne ha bisogno, come Excel con i file CSV. Per JSON e la maggior parte dei file web, salva in UTF-8 senza BOM.
Perché il mio link contiene %2520?
È stato codificato due volte: %20, uno spazio, è stato codificato di nuovo e il suo % è diventato %25. Decodificalo una volta e usa il risultato.
Gli strumenti di codifica di nTools caricano il mio testo?
No. Codifica e decodifica avvengono nel tuo browser e il testo non viene inviato da nessuna parte.
Precedente della serie ← I file CSV spiegati: separatori, virgolette, codifica ed Excel
Riferimenti
- 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()
Guide correlate
- Indirizzi IP spiegati: IPv4, IPv6 e gli intervalli riservati
- Sottoreti e CIDR spiegati: prefissi, maschere e host utilizzabili
- Record DNS spiegati: A, AAAA, CNAME, MX, TXT e NS
- Un sito è down o il problema è solo tuo? Come verificarlo, passo per passo
- Codici di stato HTTP ed errori di Cloudflare: cosa significano 403, 404, 429, 500, 503 e 521
- Timestamp Unix e fusi orari spiegati
- Contare le date: giorni tra due date, anni bisestili e settimane ISO
- Formati immagine spiegati: JPEG, PNG, WebP, AVIF e HEIC
- Le dimensioni di un’immagine spiegate: pixel, DPI, peso e qualità
- Le foto del telefono spiegate: HEIC, metadati EXIF e la tua privacy
- Robustezza delle password spiegata: lunghezza, entropia e passphrase
- Funzioni di hash spiegate: SHA-256, checksum e hashing delle password
- JSON Web Token spiegati: claim, firme e validazione sicura
- Gli UUID spiegati: v4, v7 e come scegliere la versione giusta
- I codici QR spiegati: capacità, correzione degli errori e dimensioni di stampa
- Percentuali e IVA spiegate: aggiungere, scorporare e cumulare
- Errori comuni nel JSON e come correggerli
- I file CSV spiegati: separatori, virgolette, codifica ed Excel
- Modificare i PDF nel browser: cosa conservano unione, divisione e conversione