Content-Type è un'intestazione HTTP che specifica il formato dei dati trasmessi tra un client e un server. Senza il tipo MIME corretto, il browser non può elaborare correttamente la risposta: un file di testo viene visualizzato come codice grezzo e un'immagine non si apre. Secondo MDN Web Docs, 2025, Content-Type è obbligatorio per la corretta trasmissione di dati di qualsiasi tipo nel protocollo HTTP e determina come il destinatario interpreta il corpo del messaggio.
Punti chiave
Content-Type è un'intestazione HTTP del gruppo delle intestazioni di rappresentazione che informa il destinatario sul formato dei dati nel corpo del messaggio. È obbligatoria per richieste e risposte HTTP che contengono un corpo, e senza di essa il client non può interpretare correttamente i byte ricevuti. In base a Content-Type, il browser o l'app mobile seleziona un parser: per text/html avvia il motore HTML, per image/png — il decodificatore PNG, per application/json — il parser JSON.
Il valore di Content-Type è un tipo MIME — un identificatore standardizzato per i formati di dati. L'acronimo MIME sta per Multipurpose Internet Mail Extensions, poiché questo standard è stato originariamente creato per gli allegati email. Tuttavia, è diventato il fondamento di HTTP e oggi è utilizzato ovunque — dalla trasmissione di pagine web allo scambio di dati nelle API REST. Ogni tipo MIME è composto da due parti: una categoria principale e un sottotipo qualificante, separati da una barra.
Il parametro charset completa Content-Type per i formati di testo. Ad esempio, Content-Type: text/html; charset=utf-8 indica che un documento HTML viene trasmesso in codifica UTF-8. Secondo IETF RFC 7231, sezione 3.1.1.5, l'intestazione Content-Type è obbligatoria per i messaggi HTTP che contengono un corpo e la sua assenza viene trattata come application/octet-stream o porta a MIME sniffing.
Il protocollo HTTP/0.9, rilasciato nel 1991, trasmetteva solo pagine HTML, quindi il tipo di dati era implicito per impostazione predefinita. Con l'introduzione di HTTP/1.0 nella RFC 1945, gli sviluppatori hanno capito la necessità di trasmettere immagini, fogli di stile e script. Hanno adattato lo standard MIME dal protocollo email e Content-Type è diventato parte integrante di HTTP. Da allora, il registro IANA si è espanso fino a centinaia di valori — dal familiare text/html ai moderni image/avif e application/manifest+json.
Content-Type gioca un ruolo critico nella protezione contro gli attacchi. Se un server invia un file HTML con tipo MIME text/plain, il browser non eseguirà JavaScript né costruirà il DOM — questo previene gli attacchi XSS. L'intestazione X-Content-Type-Options: nosniff, raccomandata da OWASP, vieta completamente al browser di indovinare il tipo MIME in base al contenuto. Secondo PortSwigger Research, gli attacchi di MIME sniffing erano particolarmente diffusi in Internet Explorer 6-9, dove il browser ignorava Content-Type e determinava il tipo dai primi byte del file.
Un tipo MIME è specificato nel formato type/subtype, dove type è la categoria generale dei dati e subtype è il formato specifico al suo interno. Ad esempio, in image/png, la categoria image indica un'immagine e il sottotipo png specifica il formato Portable Network Graphics. Esistono solo poche categorie: text, image, audio, video, application, multipart e message. Il resto della diversità proviene dai sottotipi, di cui ce ne sono centinaia.
I parametri aggiuntivi vengono passati tramite un punto e virgola dopo il sottotipo. Il parametro più comune è charset per specificare la codifica. Content-Type: application/json; charset=utf-8 indica che un documento JSON viene trasmesso in codifica UTF-8. Formalmente, charset per application/json è ridondante poiché JSON è sempre in UTF-8 secondo RFC 8259, ma la specifica esplicita migliora la compatibilità con i vecchi client HTTP.
| Categoria | Esempi di sottotipi | Descrizione |
|---|---|---|
| text | html, plain, css, javascript, csv | Formati di testo leggibili dall'uomo |
| image | jpeg, png, gif, webp, svg+xml, avif | Immagini raster e vettoriali |
| audio | mpeg, ogg, wav, mp4, webm | Formati audio per riproduzione in streaming |
| video | mp4, webm, ogg, x-msvideo, 3gpp | Formati video e contenitori multimediali |
| application | json, xml, pdf, zip, octet-stream, protobuf | Dati binari e strutturati |
| multipart | form-data, mixed, alternative, byteranges | Documenti compositi con più parti |
I tipi MIME standard sono registrati nel registro IANA e hanno un prefisso di categoria principale. I tipi non standard (specifici del fornitore) usano il prefisso x- o il formato vnd.company.type — ad esempio, application/vnd.google-earth.kml+xml per il formato KML di Google. I browser potrebbero non riconoscere i tipi non standard, quindi per gli allegati sconosciuti si usa application/octet-stream — un flusso binario universale che il browser non tenta di visualizzare ma offre di scaricare come file.
Il parametro charset è fondamentale per la corretta visualizzazione del testo. Senza di esso, il browser potrebbe interpretare male i caratteri, portando a mojibake. Lo standard per il web è UTF-8, ma si trovano anche ISO-8859-1 (Latin-1) per le lingue dell'Europa occidentale e windows-1251 per il cirillico nei siti vecchi. La raccomandazione W3C è di specificare sempre charset=utf-8 per text/html e text/plain, mentre charset non è necessario per application/json.
In pratica, gli sviluppatori web e mobili lavorano con un insieme limitato di tipi MIME. Conoscere questi tipi è essenziale per configurare correttamente i server, scrivere client HTTP e gestire file statici. text/html è il tipo principale per le pagine web, restituito dai server Apache e Nginx per impostazione predefinita per i file HTML. application/xhtml+xml è usato meno frequentemente e solo per documenti XHTML.
application/json è diventato lo standard per le API REST. I server restituiscono dati JSON con questo tipo MIME e i client lo inviano nelle richieste POST e PUT. text/javascript (obsoleto) e application/javascript sono usati per i file JavaScript. Secondo il Sondaggio W3Techs, 2025, JSON è il formato di dati in più rapida crescita sul web, superando XML nel 2018. Per i servizi SOAP, vengono ancora usati text/xml o application/soap+xml.
Per le immagini, il tipo MIME è determinato dal formato del file: image/jpeg per JPEG, image/png per PNG, image/gif per GIF, image/webp per il moderno formato WebP. image/svg+xml è usato per la grafica vettoriale e supporta stili e script incorporati. video/mp4, audio/mpeg e application/pdf sono altri tipi frequentemente incontrati. Per i font web, si usano font/woff2, font/woff e font/ttf.
Quando si caricano file tramite un modulo HTML, si usa multipart/form-data — un tipo MIME composito che divide la richiesta in più parti. Ogni parte ha la propria intestazione Content-Type e Content-Disposition che specifica il nome del campo e il nome originale del file. Il server riceve il file con il suo tipo MIME effettivo determinato dal browser e può verificarlo sul lato backend. application/octet-stream è usato per file di tipo sconosciuto — il browser non tenta di visualizzare il contenuto ma offre di salvarlo su disco.
Il tipo MIME influenza la politica di caching di CDN e browser. Le immagini con URL stabili vengono solitamente memorizzate nella cache per un lungo periodo (un anno o più), mentre le pagine HTML vengono memorizzate nella cache per minuti o secondi. I server CDN come Cloudflare e Akamai usano Content-Type per selezionare l'algoritmo di compressione: text/* viene compresso con gzip o brotli, image/* no, poiché le immagini sono già compresse. La corretta configurazione di Content-Type sul server impatta direttamente le prestazioni di caricamento delle pagine web e delle applicazioni mobili.
Il server imposta l'intestazione Content-Type nella risposta HTTP in base al tipo di file richiesto o al contenuto generato dinamicamente. I server web popolari come Nginx e Apache hanno tabelle di tipi MIME integrate che mappano le estensioni dei file al Content-Type corrispondente. Ad esempio, index.html riceve text/html e style.css riceve text/css. Per le risposte dinamiche, lo sviluppatore imposta Content-Type nel codice dell'applicazione in PHP, Python, Java o Kotlin.
Il client usa Content-Type per selezionare un gestore. Se il server restituisce text/html, il browser avvia il parser HTML e costruisce l'albero DOM. Se image/png — avvia il decodificatore PNG. Se Content-Type è assente o errato, il client applica MIME sniffing — tenta di indovinare il tipo dalla firma (byte magici) all'inizio del file. JPEG inizia con i byte FF D8 FF, PNG inizia con 89 50 4E 47 e PDF inizia con 25 50 44 46. Questo processo è potenzialmente pericoloso e viene disabilitato dall'intestazione X-Content-Type-Options: nosniff.
Nelle applicazioni mobili, Content-Type è gestito dai client HTTP. OkHttp su Android analizza automaticamente l'intestazione Content-Type dalla risposta e la fornisce tramite il metodo Response.header("Content-Type"). Il client URLSession di iOS fa lo stesso tramite la proprietà URLResponse.mimeType. Su entrambe le piattaforme, Content-Type viene utilizzato per selezionare un parser: JSON — tramite Moshi o Gson su Android, tramite Codable su iOS; immagini — tramite Glide, Coil o SDWebImage.
La content negotiation è un meccanismo HTTP in cui il client specifica il formato di risposta desiderato tramite l'intestazione Accept e il server seleziona il formato appropriato e lo restituisce con il Content-Type corrispondente. Ad esempio, il client invia Accept: application/json, il server risponde con Content-Type: application/json. Se il server non può fornire il formato richiesto, restituisce 406 Not Acceptable. Nelle API REST, questo meccanismo consente a un singolo endpoint di restituire dati in JSON, XML o HTML.
L'intestazione Content-Type è utilizzata sia nelle richieste HTTP che nelle risposte HTTP. Nelle richieste, specifica il formato del corpo della richiesta, ad esempio quando si invia JSON tramite POST. Nelle risposte, specifica il formato dei dati restituiti. La differenza principale è che il Content-Type della richiesta è impostato dal client, mentre il Content-Type della risposta è impostato dal server. Impostare erroneamente Content-Type in una richiesta impedisce al server di analizzare il corpo, restituendo un errore 400 Bad Request o 415 Unsupported Media Type.
Nelle richieste HTTP, Content-Type è obbligatorio per i metodi POST, PUT e PATCH se la richiesta contiene un corpo. GET, HEAD e DELETE tipicamente non usano un corpo, quindi Content-Type non viene specificato o viene ignorato per essi. Quando si invia un modulo HTML con l'attributo enctype="multipart/form-data", il browser imposta automaticamente Content-Type: multipart/form-data con una stringa di confine unica che separa le parti della richiesta composita. Ogni parte è separata da --boundary e la fine della richiesta è contrassegnata da --boundary--.
Nelle risposte HTTP, Content-Type è impostato dal server. Se il server non specifica Content-Type, il client attiva MIME sniffing o elabora la risposta come application/octet-stream. Il metodo HTTP HEAD consente di ottenere le intestazioni di risposta, incluso Content-Type, senza trasmettere il corpo. Questo è utile per verificare il tipo di risorsa prima di caricarla completamente. I server CDN possono sovrascrivere Content-Type durante la trasformazione del contenuto — ad esempio, durante la conversione di immagini in WebP.
import okhttp3.*
fun checkContentType() {
val client = OkHttpClient()
val request = Request.Builder()
.url("https://api.example.com/resource")
.head()
.build()
client.newCall(request).execute().use { response ->
val contentType = response.header("Content-Type")
val mediaType = MediaType.parse(contentType)
println("Tipo: ${mediaType?.type}, Sottotipo: ${mediaType?.subtype}")
}
}
Nello sviluppo mobile, l'intestazione Content-Type viene gestita automaticamente dai client HTTP. In OkHttp su Android, Content-Type viene impostato tramite RequestBody: val body = "{}".toRequestBody("application/json".toMediaType()). Retrofit gestisce Content-Type tramite annotazioni: @Body per JSON, @Part per multipart. Su iOS, URLSession imposta Content-Type per HTTPBody e Alamofire lo fa tramite il parametro encoding: JSONEncoding.default o URLEncoding.default. L'impostazione manuale di Content-Type è necessaria quando si lavora con socket grezzi o protocolli personalizzati.
Content-Type errato è uno dei problemi più comuni nello sviluppo e integrazione di servizi web. L'errore più frequente è quando il server restituisce text/html invece di application/json. Il client riceve JSON come stringa HTML, non può analizzarlo e lancia un'eccezione. Questo accade quando il framework web è configurato per HTML per impostazione predefinita e lo sviluppatore dimentica di sovrascrivere Content-Type per gli endpoint API. In PHP si manifesta quando manca header('Content-Type: application/json'), in Spring Boot — quando manca l'annotazione produces.
Il secondo errore più comune è un charset errato o mancante. Se il server invia text/html; charset=iso-8859-1 e il browser si aspetta UTF-8, i caratteri cirillici vengono visualizzati come mojibake. Questo problema è tipico dei vecchi siti che non sono passati a UTF-8. Per JSON, questo errore è meno comune poiché RFC 8259 prescrive UTF-8 senza negoziazione aggiuntiva. La soluzione è specificare sempre esplicitamente charset=utf-8 per i tipi MIME di testo nella configurazione del server.
Il terzo problema è la discrepanza tra Content-Type e il contenuto effettivo. Se il server invia Content-Type: image/png ma il corpo della risposta contiene un'immagine WebP, il browser potrebbe non decodificarla. I server CDN a volte comprimono le immagini cambiando il formato ma senza aggiornare l'intestazione Content-Type. Verificare la corrispondenza di Content-Type con il contenuto effettivo è un passaggio obbligatorio nei test API e nei test di integrazione delle applicazioni mobili.
Per il debug, usa gli strumenti di sviluppo del browser (scheda Network), curl con il flag -I per verificare le intestazioni di risposta o sniffer di traffico come Charles Proxy e Wireshark. Nginx viene configurato tramite la direttiva include mime.types, Apache — tramite AddType e AddDefaultCharset. Per i file statici, verifica sempre che l'estensione del file corrisponda al suo tipo MIME. Per le risposte dinamiche in tutti i linguaggi di programmazione, imposta esplicitamente Content-Type prima di generare i dati — questo previene la stragrande maggioranza dei problemi.
Domande frequenti
Senza Content-Type, il browser attiva il MIME sniffing — analisi dei primi byte della risposta per determinare automaticamente il tipo di dati. Ciò può portare a un'elaborazione errata del contenuto e a vulnerabilità di sicurezza. I browser moderni con l'intestazione X-Content-Type-Options: nosniff bloccano completamente l'indovinamento.
Content-Type specifica il formato dei dati trasmessi nel messaggio corrente (corpo della richiesta o risposta). Accept è un'intestazione di richiesta che comunica al server quale formato di risposta preferisce il client. Content-Type è impostato dal mittente dei dati, mentre Accept è impostato dal destinatario, ed entrambi partecipano al meccanismo di content negotiation.
Il tipo MIME ufficiale per JSON è application/json secondo RFC 8259. In precedenza veniva usato text/x-json, ma questo tipo è obsoleto. Il parametro charset per application/json non è necessario perché JSON viene sempre trasmesso in codifica UTF-8, UTF-16 o UTF-32 con rilevamento automatico dell'ordine dei byte (BOM) secondo la specifica.
Ciò accade quando il framework web non sovrascrive il Content-Type predefinito per gli endpoint API. In PHP si risolve chiamando header('Content-Type: application/json'), in Spring Boot — con l'annotazione @GetMapping(produces = "application/json"), in Express.js — con il metodo res.set('Content-Type', 'application/json').
application/octet-stream è un tipo MIME universale per dati binari il cui formato è sconosciuto. Il browser non tenta di visualizzare tale file nella finestra ma offre di salvarlo su disco. Viene utilizzato per download di file, allegati email e dati in streaming quando il server non può determinare il tipo esatto del contenuto trasmesso.
Riepilogo
Svilupperemo un'applicazione mobile chiavi in mano
IT Sectr crea applicazioni iOS e Android per startup e aziende dal 2017. Ti consulteremo e ti proporremo la soluzione migliore.
Leggi anche