Content-Type es un encabezado HTTP que especifica el formato de los datos transmitidos entre un cliente y un servidor. Sin el tipo MIME correcto, el navegador no puede procesar la respuesta adecuadamente: un archivo de texto se muestra como código fuente y una imagen no se abre. Según MDN Web Docs, 2025, Content-Type es obligatorio para la transmisión correcta de datos de cualquier tipo en el protocolo HTTP y determina cómo el destinatario interpreta el cuerpo del mensaje.
Puntos clave
Content-Type es un encabezado HTTP del grupo de encabezados de representación que informa al destinatario sobre el formato de los datos en el cuerpo del mensaje. Es obligatorio para solicitudes y respuestas HTTP que contienen un cuerpo, y sin él el cliente no puede interpretar correctamente los bytes recibidos. Basándose en Content-Type, el navegador o la aplicación móvil selecciona un analizador: para text/html inicia el motor HTML, para image/png — el decodificador PNG, para application/json — el analizador JSON.
El valor de Content-Type es un tipo MIME — un identificador estandarizado para formatos de datos. El acrónimo MIME significa Multipurpose Internet Mail Extensions, ya que este estándar fue creado originalmente para archivos adjuntos de correo electrónico. Sin embargo, se convirtió en la base de HTTP y hoy se utiliza en todas partes — desde la transmisión de páginas web hasta el intercambio de datos en API REST. Cada tipo MIME consta de dos partes: una categoría principal y un subtipo calificativo, separados por una barra.
El parámetro charset complementa Content-Type para formatos de texto. Por ejemplo, Content-Type: text/html; charset=utf-8 indica que se está transmitiendo un documento HTML en codificación UTF-8. Según IETF RFC 7231, sección 3.1.1.5, el encabezado Content-Type es obligatorio para mensajes HTTP que contienen un cuerpo, y su ausencia se trata como application/octet-stream o conduce a MIME sniffing.
El protocolo HTTP/0.9, lanzado en 1991, solo transmitía páginas HTML, por lo que el tipo de datos se sobreentendía. Con la introducción de HTTP/1.0 en RFC 1945, los desarrolladores comprendieron la necesidad de transmitir imágenes, hojas de estilo y scripts. Adaptaron el estándar MIME del protocolo de correo electrónico, y Content-Type se convirtió en una parte integral de HTTP. Desde entonces, el registro IANA se ha expandido a cientos de valores — desde el familiar text/html hasta los modernos image/avif y application/manifest+json.
Content-Type desempeña un papel crítico en la protección contra ataques. Si un servidor envía un archivo HTML con tipo MIME text/plain, el navegador no ejecutará JavaScript ni construirá el DOM — esto previene ataques XSS. El encabezado X-Content-Type-Options: nosniff, recomendado por OWASP, prohíbe completamente que el navegador adivine el tipo MIME según el contenido. Según PortSwigger Research, los ataques de MIME sniffing fueron especialmente frecuentes en Internet Explorer 6-9, donde el navegador ignoraba Content-Type y determinaba el tipo a partir de los primeros bytes del archivo.
Un tipo MIME se especifica en el formato type/subtype, donde type es la categoría general de datos y subtype es el formato específico dentro de ella. Por ejemplo, en image/png, la categoría image indica una imagen y el subtipo png especifica el formato Portable Network Graphics. Solo hay unas pocas categorías: text, image, audio, video, application, multipart y message. El resto de la diversidad proviene de los subtipos, de los cuales hay cientos.
Los parámetros adicionales se pasan mediante un punto y coma después del subtipo. El parámetro más común es charset para especificar la codificación. Content-Type: application/json; charset=utf-8 indica que se está transmitiendo un documento JSON en codificación UTF-8. Formalmente, charset para application/json es redundante ya que JSON siempre está en UTF-8 según RFC 8259, pero la especificación explícita mejora la compatibilidad con clientes HTTP antiguos.
| Categoría | Ejemplos de subtipos | Descripción |
|---|---|---|
| text | html, plain, css, javascript, csv | Formatos de texto legibles por humanos |
| image | jpeg, png, gif, webp, svg+xml, avif | Imágenes rasterizadas y vectoriales |
| audio | mpeg, ogg, wav, mp4, webm | Formatos de audio para reproducción en streaming |
| video | mp4, webm, ogg, x-msvideo, 3gpp | Formatos de video y contenedores multimedia |
| application | json, xml, pdf, zip, octet-stream, protobuf | Datos binarios y estructurados |
| multipart | form-data, mixed, alternative, byteranges | Documentos compuestos de varias partes |
Los tipos MIME estándar están registrados en el registro IANA y tienen un prefijo de categoría principal. Los tipos no estándar (específicos de proveedor) usan el prefijo x- o el formato vnd.company.type — por ejemplo, application/vnd.google-earth.kml+xml para el formato KML de Google. Los navegadores pueden no reconocer los tipos no estándar, por lo que para archivos adjuntos desconocidos se utiliza application/octet-stream — un flujo binario universal que el navegador no intenta mostrar sino que ofrece descargar como archivo.
El parámetro charset es fundamental para la visualización correcta del texto. Sin él, el navegador puede interpretar mal los caracteres, lo que provoca mojibake. El estándar para la web es UTF-8, pero también se encuentran ISO-8859-1 (Latin-1) para idiomas de Europa occidental y windows-1251 para cirílico en sitios antiguos. La recomendación de W3C es especificar siempre charset=utf-8 para text/html y text/plain, mientras que charset no es necesario para application/json.
En la práctica, los desarrolladores web y móviles trabajan con un conjunto limitado de tipos MIME. Conocer estos tipos es esencial para configurar correctamente los servidores, escribir clientes HTTP y manejar archivos estáticos. text/html es el tipo principal para páginas web, devuelto por los servidores Apache y Nginx por defecto para archivos HTML. application/xhtml+xml se usa con menos frecuencia y solo para documentos XHTML.
application/json se ha convertido en el estándar para las API REST. Los servidores devuelven datos JSON con este tipo MIME, y los clientes lo envían en solicitudes POST y PUT. text/javascript (obsoleto) y application/javascript se utilizan para archivos JavaScript. Según la Encuesta W3Techs, 2025, JSON es el formato de datos de más rápido crecimiento en la web, superando a XML en 2018. Para servicios SOAP, todavía se utilizan text/xml o application/soap+xml.
Para las imágenes, el tipo MIME está determinado por el formato del archivo: image/jpeg para JPEG, image/png para PNG, image/gif para GIF, image/webp para el formato moderno WebP. image/svg+xml se usa para gráficos vectoriales y admite estilos y scripts incrustados. video/mp4, audio/mpeg y application/pdf son otros tipos que se encuentran con frecuencia. Para fuentes web se utilizan font/woff2, font/woff y font/ttf.
Al cargar archivos a través de un formulario HTML, se utiliza multipart/form-data — un tipo MIME compuesto que divide la solicitud en varias partes. Cada parte tiene su propio encabezado Content-Type y Content-Disposition que especifica el nombre del campo y el nombre original del archivo. El servidor recibe el archivo con su tipo MIME real determinado por el navegador y puede verificarlo en el lado del backend. application/octet-stream se usa para archivos de tipo desconocido — el navegador no intenta mostrar el contenido sino que ofrece guardarlo en disco.
El tipo MIME afecta la política de almacenamiento en caché de CDN y navegadores. Las imágenes con URL estables generalmente se almacenan en caché por un período prolongado (un año o más), mientras que las páginas HTML se almacenan en caché por minutos o segundos. Los servidores CDN como Cloudflare y Akamai utilizan Content-Type para seleccionar el algoritmo de compresión: text/* se comprime con gzip o brotli, image/* no, ya que las imágenes ya están comprimidas. La configuración correcta de Content-Type en el servidor impacta directamente en el rendimiento de carga de páginas web y aplicaciones móviles.
El servidor establece el encabezado Content-Type en la respuesta HTTP según el tipo de archivo solicitado o el contenido generado dinámicamente. Los servidores web populares como Nginx y Apache tienen tablas de tipos MIME integradas que asignan las extensiones de archivo al Content-Type correspondiente. Por ejemplo, index.html recibe text/html y style.css recibe text/css. Para respuestas dinámicas, el desarrollador establece Content-Type en el código de la aplicación en PHP, Python, Java o Kotlin.
El cliente utiliza Content-Type para seleccionar un controlador. Si el servidor devuelve text/html, el navegador inicia el analizador HTML y construye el árbol DOM. Si es image/png, inicia el decodificador PNG. Si Content-Type falta o es incorrecto, el cliente aplica MIME sniffing — intenta adivinar el tipo mediante la firma (bytes mágicos) al inicio del archivo. JPEG comienza con los bytes FF D8 FF, PNG comienza con 89 50 4E 47 y PDF comienza con 25 50 44 46. Este proceso es potencialmente peligroso y se desactiva con el encabezado X-Content-Type-Options: nosniff.
En aplicaciones móviles, Content-Type es manejado por los clientes HTTP. OkHttp en Android analiza automáticamente el encabezado Content-Type de la respuesta y lo proporciona mediante el método Response.header("Content-Type"). El cliente URLSession de iOS hace lo mismo a través de la propiedad URLResponse.mimeType. En ambas plataformas, Content-Type se utiliza para seleccionar un analizador: JSON — mediante Moshi o Gson en Android, mediante Codable en iOS; imágenes — mediante Glide, Coil o SDWebImage.
La negociación de contenido es un mecanismo HTTP donde el cliente especifica el formato de respuesta deseado mediante el encabezado Accept, y el servidor selecciona el formato adecuado y lo devuelve con el Content-Type correspondiente. Por ejemplo, el cliente envía Accept: application/json, el servidor responde con Content-Type: application/json. Si el servidor no puede proporcionar el formato solicitado, devuelve 406 Not Acceptable. En las API REST, este mecanismo permite que un solo endpoint devuelva datos en JSON, XML o HTML.
El encabezado Content-Type se utiliza tanto en solicitudes HTTP como en respuestas HTTP. En las solicitudes, especifica el formato del cuerpo de la solicitud, por ejemplo al enviar JSON mediante POST. En las respuestas, especifica el formato de los datos devueltos. La diferencia clave es que el Content-Type de la solicitud lo establece el cliente, mientras que el Content-Type de la respuesta lo establece el servidor. Establecer incorrectamente Content-Type en una solicitud hace que el servidor no pueda analizar el cuerpo, devolviendo un error 400 Bad Request o 415 Unsupported Media Type.
En solicitudes HTTP, Content-Type es obligatorio para los métodos POST, PUT y PATCH si la solicitud contiene un cuerpo. GET, HEAD y DELETE típicamente no usan un cuerpo, por lo que Content-Type no se especifica o se ignora para ellos. Al enviar un formulario HTML con el atributo enctype="multipart/form-data", el navegador establece automáticamente Content-Type: multipart/form-data con una cadena de límite única que separa las partes de la solicitud compuesta. Cada parte se separa por --boundary, y el final de la solicitud se marca con --boundary--.
En respuestas HTTP, Content-Type lo establece el servidor. Si el servidor no especifica Content-Type, el cliente activa MIME sniffing o procesa la respuesta como application/octet-stream. El método HTTP HEAD permite obtener los encabezados de respuesta, incluido Content-Type, sin transmitir el cuerpo. Esto es útil para verificar el tipo de recurso antes de cargarlo completamente. Los servidores CDN pueden sobrescribir Content-Type al transformar el contenido — por ejemplo, al convertir imágenes a 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}, Subtipo: ${mediaType?.subtype}")
}
}
En el desarrollo móvil, el encabezado Content-Type es manejado automáticamente por los clientes HTTP. En OkHttp en Android, Content-Type se establece mediante RequestBody: val body = "{}".toRequestBody("application/json".toMediaType()). Retrofit gestiona Content-Type mediante anotaciones: @Body para JSON, @Part para multipart. En iOS, URLSession establece Content-Type para HTTPBody, y Alamofire lo hace mediante el parámetro encoding: JSONEncoding.default o URLEncoding.default. La configuración manual de Content-Type es necesaria al trabajar con sockets sin procesar o protocolos personalizados.
Un Content-Type incorrecto es uno de los problemas más comunes en el desarrollo e integración de servicios web. El error más frecuente es cuando el servidor devuelve text/html en lugar de application/json. El cliente recibe JSON como una cadena HTML, no puede analizarlo y lanza una excepción. Esto ocurre cuando el framework web está configurado para HTML por defecto y el desarrollador olvida sobrescribir Content-Type para los endpoints de API. En PHP esto se manifiesta cuando falta header('Content-Type: application/json'), en Spring Boot — cuando falta la anotación produces.
El segundo error más común es charset incorrecto o faltante. Si el servidor envía text/html; charset=iso-8859-1 y el navegador espera UTF-8, los caracteres cirílicos se muestran como mojibake. Este problema es típico de sitios antiguos que no han migrado a UTF-8. Para JSON, este error es menos común ya que RFC 8259 prescribe UTF-8 sin negociación adicional. La solución es especificar siempre explícitamente charset=utf-8 para tipos MIME de texto en la configuración del servidor.
El tercer problema es la discrepancia entre Content-Type y el contenido real. Si el servidor envía Content-Type: image/png pero el cuerpo de la respuesta contiene una imagen WebP, el navegador puede no decodificarla. Los servidores CDN a veces comprimen imágenes cambiando el formato pero sin actualizar el encabezado Content-Type. Verificar Content-Type contra el contenido real es un paso obligatorio en las pruebas de API y en las pruebas de integración de aplicaciones móviles.
Para depurar, use las herramientas de desarrollo del navegador (pestaña Network), curl con el indicador -I para verificar los encabezados de respuesta, o analizadores de tráfico como Charles Proxy y Wireshark. Nginx se configura mediante la directiva include mime.types, Apache — mediante AddType y AddDefaultCharset. Para archivos estáticos, siempre verifique que la extensión del archivo coincida con su tipo MIME. Para respuestas dinámicas en todos los lenguajes de programación, establezca explícitamente Content-Type antes de generar los datos — esto previene la gran mayoría de los problemas.
Preguntas frecuentes
Sin Content-Type, el navegador activa MIME sniffing — análisis de los primeros bytes de la respuesta para determinar automáticamente el tipo de datos. Esto puede provocar un procesamiento incorrecto del contenido y vulnerabilidades de seguridad. Los navegadores modernos con el encabezado X-Content-Type-Options: nosniff bloquean completamente la adivinación.
Content-Type especifica el formato de los datos que se transmiten en el mensaje actual (cuerpo de la solicitud o respuesta). Accept es un encabezado de solicitud que indica al servidor qué formato de respuesta prefiere el cliente. Content-Type lo establece el remitente de los datos, mientras que Accept lo establece el destinatario, y ambos participan en el mecanismo de negociación de contenido.
El tipo MIME oficial para JSON es application/json según RFC 8259. Anteriormente se usaba text/x-json, pero este tipo está obsoleto. El parámetro charset para application/json no es necesario porque JSON siempre se transmite en codificación UTF-8, UTF-16 o UTF-32 con detección automática del orden de bytes (BOM) según la especificación.
Esto ocurre cuando el framework web no sobrescribe el Content-Type predeterminado para los endpoints de API. En PHP se soluciona llamando a header('Content-Type: application/json'), en Spring Boot — con la anotación @GetMapping(produces = "application/json"), en Express.js — con el método res.set('Content-Type', 'application/json').
application/octet-stream es un tipo MIME universal para datos binarios cuyo formato se desconoce. El navegador no intenta mostrar dicho archivo en la ventana sino que ofrece guardarlo en disco. Se utiliza para descargas de archivos, archivos adjuntos de correo electrónico y datos en streaming cuando el servidor no puede determinar el tipo exacto del contenido transmitido.
Resumen
Desarrollaremos una aplicación móvil llave en mano
IT Sectr crea aplicaciones para iOS y Android para startups y empresas desde 2017. Le asesoraremos y le propondremos la mejor solución.
Lea también