Skip to content

Glossary

UTF-8

La codifica dei caratteri del web

By Published Updated

UTF-8 (Unicode Transformation Format, 8-bit) è una codifica a larghezza variabile per i caratteri Unicode. Ogni code point viene codificato in 1-4 byte a seconda del suo valore: i caratteri ASCII (da U+0000 a U+007F) occupano un byte; le comuni estensioni latine e i caratteri greci/cirillici due; gli ideogrammi CJK tre; le emoji e i caratteri rari quattro.

Progettato da Ken Thompson e Rob Pike nel 1992, principalmente per Plan 9. Proprietà chiave:

  • Compatibile con ASCII. Il testo ASCII puro è UTF-8 valido byte per byte.
  • Auto-sincronizzante. Se uno stream viene corrotto nel mezzo di un carattere, il decodificatore può trovare il confine del carattere successivo senza tornare indietro.
  • Nessun problema di byte order. I byte vengono elaborati da sinistra a destra; non c’è distinzione tra big-endian e little-endian.
  • Compatto per gli script latini, meno compatto di UTF-16 per i contenuti a dominanza CJK (3 byte per carattere vs 2).

UTF-8 è la codifica dominante sul web — oltre il 98% delle pagine nel 2024. È il default per HTML5, JSON (dove la specifica RFC 8259 impone effettivamente UTF-8) e praticamente ogni protocollo moderno. Le vecchie codifiche (Windows-1252, ISO-8859-1, Shift-JIS) sopravvivono nei sistemi legacy ma dovrebbero essere convertite all’ingresso in qualsiasi stack moderno.

La controversia del BOM (Byte Order Mark): UTF-16 e UTF-32 usano un BOM di 2 o 4 byte all’inizio di un file per dichiarare l’ordine dei byte, ma UTF-8 non ha byte order da marcare. Gli strumenti Microsoft prepongono abitualmente un BOM UTF-8 di 3 byte (EF BB BF) comunque, mentre gli strumenti Unix tipicamente non lo fanno. Il risultato: gli script shell salvati da Notepad si rompono, le importazioni CSV mostrano spazzatura invisibile nella prima cella, e i parser YAML/JSON rifiutano il file. Lo standard Unicode tollera ma non richiede un BOM UTF-8; la raccomandazione moderna è “non aggiungerne uno.” Se si riceve un file con uno, eliminarlo in lettura.

Lunghezza stringa vs lunghezza byte — il problema sempre rilevante: nella maggior parte dei linguaggi, "hello".length restituisce 5 (caratteri) ma Buffer.byteLength("hello", "utf8") restituisce 5 (byte — uguali per ASCII). Per "café", la lunghezza in caratteri è 4 ma la lunghezza in byte è 5 (la é è 2 byte). Per "🎉", la lunghezza in caratteri in JavaScript è 2 (coppia surrogata) ma la lunghezza in byte è 4 e la lunghezza in grafemi è 1. Troncare le stringhe UTF-8 per conteggio di byte senza consapevolezza dei grafemi produce regolarmente mojibake — la soluzione standard è usare l’API Intl.Segmenter (browser moderni) o il pacchetto npm graphemer. Riferimento: RFC 3629 — UTF-8, a transformation format of ISO 10646.

Esempio pratico

Codificare la stringa “A€🎉”. Il code point di ogni carattere e la sequenza di byte UTF-8: A (U+0041) → 1 byte 0x41. € (U+20AC) → 3 byte 0xE2 0x82 0xAC (i bit alti codificano la lunghezza: 1110xxxx 10xxxxxx 10xxxxxx). 🎉 (U+1F389) → 4 byte 0xF0 0x9F 0x8E 0x89. Totale: 8 byte per 3 caratteri. In una colonna di database dichiarata VARCHAR(10) con semantica dei caratteri UTF-8 (PostgreSQL moderno, MySQL con utf8mb4), ci sta comodamente. In una colonna a byte fissi dichiarata VARCHAR(10) BYTES (il vecchio MySQL utf8 che era effettivamente limitato a 3 byte), la codifica a 4 byte dell’emoji non ci sta — la modalità di errore canonica “impossibile memorizzare emoji in MySQL”. La soluzione in MySQL dalla versione 5.5.3 è usare utf8mb4 come charset della colonna e della connessione.

Quando e perché è importante

Ogni byte elaborato sul web moderno è probabilmente UTF-8, ma diversi livelli continuano a sbagliare. Le richieste HTTP senza un esplicito Content-Type: text/...; charset=utf-8 possono avere come default ISO-8859-1 nei proxy più vecchi; i vecchi lavori ETL su mainframe consegnano file EBCDIC che devono essere transcodificati all’ingestion; l’output della console Windows ha come default la code page di sistema (CP-1252 sulla maggior parte delle installazioni in lingua inglese degli USA) e corrompe il testo inviato tramite pipe senza un chcp 65001 prima. La pratica difensiva: dichiarare UTF-8 esplicitamente ovunque (HTML <meta charset="utf-8">, intestazioni HTTP, pragma di codifica dei file, charset di connessione del database), e validare qualsiasi byte in entrata contro la grammatica UTF-8 — le sequenze di byte non valide sono un segnale affidabile di un mismatch di charset a monte. Riferimento: WHATWG Encoding Standard.

Frequently asked questions

Che cos&rsquo;è UTF-8?
UTF-8 è una codifica Unicode a larghezza variabile che rappresenta ogni code point usando da 1 a 4 byte. I caratteri ASCII (da U+0000 a U+007F) usano esattamente 1 byte, rendendo UTF-8 completamente retrocompatibile con ASCII. È la codifica dominante sul web, usata da oltre il 98% delle pagine.
Come funziona la codifica UTF-8 in pratica?
La lettera latina A (U+0041) viene memorizzata come singolo byte 0x41. L&rsquo;emoji faccina sorridente (U+1F600) richiede 4 byte: 0xF0 0x9F 0x98 0x80. Questo design significa che il testo in inglese memorizzato come ASCII è anche UTF-8 valido, e il testo multilingue viene gestito aggiungendo più byte solo quando necessario.
Qual è la differenza tra UTF-8 e UTF-16?
UTF-8 usa da 1 a 4 byte ed è compatibile con ASCII, rendendolo ideale per il web e l&rsquo;archiviazione di file. UTF-16 usa 2 o 4 byte ed è comune negli internals di Windows e Java. UTF-8 è più efficiente in termini di spazio per il testo pesante in ASCII; UTF-16 usa gli stessi 2 byte per la maggior parte dei caratteri CJK comuni mentre UTF-8 ne usa 3.

Related

Published May 14, 2026 · Last reviewed May 31, 2026