Content-Type est un en-tête HTTP qui spécifie le format des données transmises entre un client et un serveur. Sans le type MIME correct, le navigateur ne peut pas traiter correctement la réponse : un fichier texte s'affiche comme du code brut et une image ne s'ouvre pas. Selon MDN Web Docs, 2025, Content-Type est obligatoire pour la transmission correcte de données de tout type dans le protocole HTTP et détermine comment le destinataire interprète le corps du message.
Points clés
Content-Type est un en-tête HTTP du groupe des en-têtes de représentation qui informe le destinataire du format des données dans le corps du message. Il est obligatoire pour les requêtes et réponses HTTP qui contiennent un corps, et sans lui le client ne peut pas interpréter correctement les octets reçus. En fonction de Content-Type, le navigateur ou l'application mobile sélectionne un analyseur : pour text/html il lance le moteur HTML, pour image/png — le décodeur PNG, pour application/json — l'analyseur JSON.
La valeur de Content-Type est un type MIME — un identifiant standardisé pour les formats de données. L'acronyme MIME signifie Multipurpose Internet Mail Extensions, car cette norme a été créée à l'origine pour les pièces jointes des e-mails. Cependant, elle est devenue la base de HTTP et est aujourd'hui utilisée partout — de la transmission de pages web à l'échange de données dans les API REST. Chaque type MIME se compose de deux parties : une catégorie principale et un sous-type qualificatif, séparés par une barre oblique.
Le paramètre charset complète Content-Type pour les formats texte. Par exemple, Content-Type: text/html; charset=utf-8 indique qu'un document HTML est transmis en encodage UTF-8. Selon l'IETF RFC 7231, section 3.1.1.5, l'en-tête Content-Type est obligatoire pour les messages HTTP contenant un corps, et son absence est traitée comme application/octet-stream ou conduit à du MIME sniffing.
Le protocole HTTP/0.9, publié en 1991, ne transmettait que des pages HTML, donc le type de données était implicite par défaut. Avec l'introduction de HTTP/1.0 dans la RFC 1945, les développeurs ont réalisé la nécessité de transmettre des images, des feuilles de style et des scripts. Ils ont adapté la norme MIME du protocole de messagerie, et Content-Type est devenu une partie intégrante de HTTP. Depuis lors, le registre IANA s'est étendu à des centaines de valeurs — du familier text/html aux modernes image/avif et application/manifest+json.
Content-Type joue un rôle critique dans la protection contre les attaques. Si un serveur envoie un fichier HTML avec le type MIME text/plain, le navigateur n'exécutera pas JavaScript ni ne construira le DOM — cela prévient les attaques XSS. L'en-tête X-Content-Type-Options: nosniff, recommandé par OWASP, interdit complètement au navigateur de deviner le type MIME en fonction du contenu. Selon PortSwigger Research, les attaques de MIME sniffing étaient particulièrement répandues dans Internet Explorer 6-9, où le navigateur ignorait Content-Type et déterminait le type à partir des premiers octets du fichier.
Un type MIME est spécifié au format type/subtype, où type est la catégorie générale des données et subtype est le format spécifique à l'intérieur de celle-ci. Par exemple, dans image/png, la catégorie image indique une image et le sous-type png spécifie le format Portable Network Graphics. Il n'existe que quelques catégories : text, image, audio, video, application, multipart et message. Le reste de la diversité provient des sous-types, dont il existe des centaines.
Les paramètres supplémentaires sont transmis par un point-virgule après le sous-type. Le paramètre le plus courant est charset pour spécifier l'encodage. Content-Type: application/json; charset=utf-8 indique qu'un document JSON est transmis en encodage UTF-8. Formellement, charset pour application/json est redondant car JSON est toujours en UTF-8 selon la RFC 8259, mais la spécification explicite améliore la compatibilité avec les anciens clients HTTP.
| Catégorie | Exemples de sous-types | Description |
|---|---|---|
| text | html, plain, css, javascript, csv | Formats texte lisibles par l'homme |
| image | jpeg, png, gif, webp, svg+xml, avif | Images raster et vectorielles |
| audio | mpeg, ogg, wav, mp4, webm | Formats audio pour la lecture en streaming |
| video | mp4, webm, ogg, x-msvideo, 3gpp | Formats vidéo et conteneurs multimédia |
| application | json, xml, pdf, zip, octet-stream, protobuf | Données binaires et structurées |
| multipart | form-data, mixed, alternative, byteranges | Documents composites à plusieurs parties |
Les types MIME standard sont enregistrés dans le registre IANA et ont un préfixe de catégorie principale. Les types non standard (spécifiques au fournisseur) utilisent le préfixe x- ou le format vnd.company.type — par exemple, application/vnd.google-earth.kml+xml pour le format KML de Google. Les navigateurs peuvent ne pas reconnaître les types non standard, donc pour les pièces jointes inconnues, on utilise application/octet-stream — un flux binaire universel que le navigateur n'essaie pas d'afficher mais propose de télécharger comme fichier.
Le paramètre charset est essentiel pour l'affichage correct du texte. Sans lui, le navigateur peut mal interpréter les caractères, conduisant à du mojibake. La norme pour le web est UTF-8, mais on trouve également ISO-8859-1 (Latin-1) pour les langues d'Europe occidentale et windows-1251 pour le cyrillique sur les anciens sites. La recommandation du W3C est de toujours spécifier charset=utf-8 pour text/html et text/plain, tandis que charset n'est pas nécessaire pour application/json.
En pratique, les développeurs web et mobiles travaillent avec un ensemble limité de types MIME. La connaissance de ces types est essentielle pour configurer correctement les serveurs, écrire des clients HTTP et gérer les fichiers statiques. text/html est le type principal pour les pages web, retourné par les serveurs Apache et Nginx par défaut pour les fichiers HTML. application/xhtml+xml est moins utilisé et uniquement pour les documents XHTML.
application/json est devenu la norme pour les API REST. Les serveurs retournent des données JSON avec ce type MIME, et les clients l'envoient dans les requêtes POST et PUT. text/javascript (obsolète) et application/javascript sont utilisés pour les fichiers JavaScript. Selon l'enquête W3Techs, 2025, JSON est le format de données qui connaît la croissance la plus rapide sur le web, dépassant XML en 2018. Pour les services SOAP, text/xml ou application/soap+xml sont encore utilisés.
Pour les images, le type MIME est déterminé par le format du fichier : image/jpeg pour JPEG, image/png pour PNG, image/gif pour GIF, image/webp pour le format moderne WebP. image/svg+xml est utilisé pour les graphiques vectoriels et prend en charge les styles et scripts intégrés. video/mp4, audio/mpeg et application/pdf sont d'autres types fréquemment rencontrés. Pour les polices web, on utilise font/woff2, font/woff et font/ttf.
Lors du téléchargement de fichiers via un formulaire HTML, on utilise multipart/form-data — un type MIME composite qui divise la requête en plusieurs parties. Chaque partie a son propre en-tête Content-Type et Content-Disposition spécifiant le nom du champ et le nom original du fichier. Le serveur reçoit le fichier avec son type MIME réel déterminé par le navigateur et peut le vérifier côté backend. application/octet-stream est utilisé pour les fichiers de type inconnu — le navigateur n'essaie pas d'afficher le contenu mais propose de le sauvegarder sur le disque.
Le type MIME affecte la politique de mise en cache des CDN et des navigateurs. Les images avec des URL stables sont généralement mises en cache pour une longue durée (un an ou plus), tandis que les pages HTML sont mises en cache pour des minutes ou des secondes. Les serveurs CDN comme Cloudflare et Akamai utilisent Content-Type pour sélectionner l'algorithme de compression : text/* est compressé avec gzip ou brotli, image/* ne l'est pas, car les images sont déjà compressées. La configuration correcte de Content-Type sur le serveur impacte directement les performances de chargement des pages web et des applications mobiles.
Le serveur définit l'en-tête Content-Type dans la réponse HTTP en fonction du type du fichier demandé ou du contenu généré dynamiquement. Les serveurs web populaires comme Nginx et Apache ont des tables de types MIME intégrées qui associent les extensions de fichier au Content-Type correspondant. Par exemple, index.html reçoit text/html et style.css reçoit text/css. Pour les réponses dynamiques, le développeur définit Content-Type dans le code de l'application en PHP, Python, Java ou Kotlin.
Le client utilise Content-Type pour sélectionner un gestionnaire. Si le serveur retourne text/html, le navigateur lance l'analyseur HTML et construit l'arbre DOM. Si image/png — il lance le décodeur PNG. Si Content-Type est absent ou incorrect, le client applique le MIME sniffing — il essaie de deviner le type par la signature (octets magiques) au début du fichier. JPEG commence par les octets FF D8 FF, PNG commence par 89 50 4E 47, et PDF commence par 25 50 44 46. Ce processus est potentiellement dangereux et est désactivé par l'en-tête X-Content-Type-Options: nosniff.
Dans les applications mobiles, Content-Type est géré par les clients HTTP. OkHttp sur Android analyse automatiquement l'en-tête Content-Type de la réponse et le fournit via la méthode Response.header("Content-Type"). Le client URLSession d'iOS fait de même via la propriété URLResponse.mimeType. Sur les deux plateformes, Content-Type est utilisé pour sélectionner un analyseur : JSON — via Moshi ou Gson sur Android, via Codable sur iOS ; images — via Glide, Coil ou SDWebImage.
La négociation de contenu est un mécanisme HTTP où le client spécifie le format de réponse souhaité via l'en-tête Accept, et le serveur sélectionne le format approprié et le retourne avec le Content-Type correspondant. Par exemple, le client envoie Accept: application/json, le serveur répond avec Content-Type: application/json. Si le serveur ne peut pas fournir le format demandé, il retourne 406 Not Acceptable. Dans les API REST, ce mécanisme permet à un seul point de terminaison de retourner des données en JSON, XML ou HTML.
L'en-tête Content-Type est utilisé à la fois dans les requêtes HTTP et les réponses HTTP. Dans les requêtes, il spécifie le format du corps de la requête, par exemple lors de l'envoi de JSON via POST. Dans les réponses, il spécifie le format des données retournées. La différence clé est que le Content-Type de la requête est défini par le client, tandis que le Content-Type de la réponse est défini par le serveur. Définir incorrectement Content-Type dans une requête empêche le serveur d'analyser le corps, retournant une erreur 400 Bad Request ou 415 Unsupported Media Type.
Dans les requêtes HTTP, Content-Type est obligatoire pour les méthodes POST, PUT et PATCH si la requête contient un corps. GET, HEAD et DELETE n'utilisent généralement pas de corps, donc Content-Type n'est pas spécifié ou est ignoré pour eux. Lors de la soumission d'un formulaire HTML avec l'attribut enctype="multipart/form-data", le navigateur définit automatiquement Content-Type: multipart/form-data avec une chaîne de limite unique qui sépare les parties de la requête composite. Chaque partie est séparée par --boundary, et la fin de la requête est marquée par --boundary--.
Dans les réponses HTTP, Content-Type est défini par le serveur. Si le serveur ne spécifie pas Content-Type, le client active le MIME sniffing ou traite la réponse comme application/octet-stream. La méthode HTTP HEAD permet d'obtenir les en-têtes de réponse, y compris Content-Type, sans transmettre le corps. Ceci est utile pour vérifier le type de ressource avant de la charger complètement. Les serveurs CDN peuvent remplacer Content-Type lors de la transformation du contenu — par exemple, lors de la conversion d'images en 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("Type : ${mediaType?.type}, Sous-type : ${mediaType?.subtype}")
}
}
Dans le développement mobile, l'en-tête Content-Type est géré automatiquement par les clients HTTP. Dans OkHttp sur Android, Content-Type est défini via RequestBody : val body = "{}".toRequestBody("application/json".toMediaType()). Retrofit gère Content-Type via des annotations : @Body pour JSON, @Part pour multipart. Sur iOS, URLSession définit Content-Type pour HTTPBody, et Alamofire le fait via le paramètre encoding : JSONEncoding.default ou URLEncoding.default. La définition manuelle de Content-Type est nécessaire lors du travail avec des sockets bruts ou des protocoles personnalisés.
Un Content-Type incorrect est l'un des problèmes les plus courants dans le développement et l'intégration de services web. L'erreur la plus fréquente est lorsque le serveur retourne text/html au lieu de application/json. Le client reçoit JSON comme une chaîne HTML, ne peut pas l'analyser et lève une exception. Cela se produit lorsque le framework web est configuré pour HTML par défaut et que le développeur oublie de remplacer Content-Type pour les points de terminaison d'API. En PHP, cela se manifeste par l'absence de header('Content-Type: application/json'), dans Spring Boot — par l'absence de l'annotation produces.
La deuxième erreur la plus courante est un charset incorrect ou manquant. Si le serveur envoie text/html; charset=iso-8859-1 et que le navigateur attend UTF-8, les caractères cyrilliques s'affichent comme du mojibake. Ce problème est typique des anciens sites qui n'ont pas migré vers UTF-8. Pour JSON, cette erreur est moins courante car la RFC 8259 prescrit UTF-8 sans négociation supplémentaire. La solution est de toujours spécifier explicitement charset=utf-8 pour les types MIME texte dans la configuration du serveur.
Le troisième problème est la non-concordance entre Content-Type et le contenu réel. Si le serveur envoie Content-Type: image/png mais que le corps de la réponse contient une image WebP, le navigateur peut ne pas la décoder. Les serveurs CDN compriment parfois les images en changeant le format mais sans mettre à jour l'en-tête Content-Type. Vérifier la correspondance de Content-Type avec le contenu réel est une étape obligatoire dans les tests d'API et les tests d'intégration des applications mobiles.
Pour le débogage, utilisez les outils de développement du navigateur (onglet Network), curl avec le drapeau -I pour vérifier les en-têtes de réponse, ou des analyseurs de trafic comme Charles Proxy et Wireshark. Nginx est configuré via la directive include mime.types, Apache — via AddType et AddDefaultCharset. Pour les fichiers statiques, vérifiez toujours que l'extension du fichier correspond à son type MIME. Pour les réponses dynamiques dans tous les langages de programmation, définissez explicitement Content-Type avant de générer les données — cela prévient la grande majorité des problèmes.
Questions fréquentes
Sans Content-Type, le navigateur active le MIME sniffing — analyse des premiers octets de la réponse pour déterminer automatiquement le type de données. Cela peut entraîner un traitement incorrect du contenu et des vulnérabilités de sécurité. Les navigateurs modernes avec l'en-tête X-Content-Type-Options: nosniff bloquent complètement la devinette.
Content-Type spécifie le format des données transmises dans le message actuel (corps de la requête ou de la réponse). Accept est un en-tête de requête qui indique au serveur quel format de réponse le client préfère. Content-Type est défini par l'expéditeur des données, tandis qu'Accept est défini par le destinataire, et ils participent tous deux au mécanisme de négociation de contenu.
Le type MIME officiel pour JSON est application/json selon la RFC 8259. Auparavant, text/x-json était utilisé, mais ce type est obsolète. Le paramètre charset pour application/json n'est pas nécessaire car JSON est toujours transmis en encodage UTF-8, UTF-16 ou UTF-32 avec détection automatique de l'ordre des octets (BOM) selon la spécification.
Cela se produit lorsque le framework web ne remplace pas le Content-Type par défaut pour les points de terminaison d'API. En PHP, cela se corrige en appelant header('Content-Type: application/json'), dans Spring Boot — avec l'annotation @GetMapping(produces = "application/json"), dans Express.js — avec la méthode res.set('Content-Type', 'application/json').
application/octet-stream est un type MIME universel pour les données binaires dont le format est inconnu. Le navigateur n'essaie pas d'afficher un tel fichier dans la fenêtre mais propose de le sauvegarder sur le disque. Il est utilisé pour les téléchargements de fichiers, les pièces jointes d'e-mails et les données en streaming lorsque le serveur ne peut pas déterminer le type exact du contenu transmis.
Résumé
Nous développerons une application mobile clé en main
IT Sectr crée des applications iOS et Android pour les startups et les entreprises depuis 2017. Nous vous conseillerons et vous proposerons la meilleure solution.
Lisez aussi