Definición
La cabecera Content-Type es una cabecera HTTP que especifica el tipo de medio (tipo MIME) del cuerpo de petición o respuesta. Dice al receptor cómo interpretar los datos que se están enviando.
La cabecera consiste en:
- Tipo/Subtipo - Tipo de medio (ej.
application/json,text/html) - Parámetros Opcionales - Codificación de caracteres, límites (ej.
charset=utf-8)
Valores comunes de Content-Type:
application/json- Datos JSONapplication/xml- Datos XMLtext/html- Documentos HTMLtext/plain- Texto planomultipart/form-data- Subidas de archivosapplication/x-www-form-urlencoded- Envíos de formularios
Content-Type es crítico para APIs REST, ya que determina cómo el servidor parsea peticiones entrantes y cómo los clientes interpretan respuestas.
Ejemplo
Petición JSON:
POST /api/users HTTP/1.1
Host: api.example.com
Content-Type: application/json
Content-Length: 89
{
"name": "Alice Smith",
"email": "[email protected]",
"role": "developer"
}
Respuesta JSON:
HTTP/1.1 200 OK
Content-Type: application/json; charset=utf-8
Content-Length: 142
{
"id": 123,
"name": "Alice Smith",
"email": "[email protected]",
"createdAt": "2026-01-09T10:30:00Z"
}
Subida de Archivo (multipart/form-data):
POST /api/upload HTTP/1.1
Host: api.example.com
Content-Type: multipart/form-data; boundary=----WebKitFormBoundary7MA4YWxkTrZu0gW
------WebKitFormBoundary7MA4YWxkTrZu0gW
Content-Disposition: form-data; name="file"; filename="document.pdf"
Content-Type: application/pdf
[Datos binarios PDF]
------WebKitFormBoundary7MA4YWxkTrZu0gW--
Ejemplo de Código
JavaScript (Fetch API):
// Enviar JSON (establecimiento automático de Content-Type)
const createUser = async (userData) => {
const response = await fetch('https://api.example.com/users', {
method: 'POST',
headers: {
'Content-Type': 'application/json', // Establecer explícitamente
'Authorization': 'Bearer YOUR_TOKEN'
},
body: JSON.stringify(userData) // Debe coincidir con Content-Type
});
// Verificar Content-Type de respuesta
const contentType = response.headers.get('Content-Type');
console.log('Response Content-Type:', contentType);
if (contentType && contentType.includes('application/json')) {
return await response.json();
} else if (contentType && contentType.includes('text/plain')) {
return await response.text();
} else {
throw new Error(`Unexpected Content-Type: ${contentType}`);
}
};
// Enviar Form Data (Content-Type automático con boundary)
const uploadFile = async (file) => {
const formData = new FormData();
formData.append('file', file);
formData.append('description', 'User uploaded file');
const response = await fetch('https://api.example.com/upload', {
method: 'POST',
// NO establecer Content-Type manualmente para FormData
// El navegador lo establece con el boundary correcto
body: formData
});
return await response.json();
};
// Enviar Datos URL-encoded de Formulario
const submitForm = async (formData) => {
const params = new URLSearchParams(formData);
const response = await fetch('https://api.example.com/form', {
method: 'POST',
headers: {
'Content-Type': 'application/x-www-form-urlencoded'
},
body: params.toString()
});
return await response.json();
};
Python (librería requests):
import requests
# Enviar JSON
def create_user(user_data):
response = requests.post(
'https://api.example.com/users',
json=user_data, # Establece automáticamente Content-Type: application/json
headers={'Authorization': 'Bearer YOUR_TOKEN'}
)
# Verificar Content-Type de respuesta
content_type = response.headers.get('Content-Type')
print(f'Response Content-Type: {content_type}')
if content_type and 'application/json' in content_type:
return response.json()
elif content_type and 'text/plain' in content_type:
return response.text
else:
raise ValueError(f'Unexpected Content-Type: {content_type}')
# Enviar Subida de Archivo
def upload_file(file_path):
with open(file_path, 'rb') as file:
files = {'file': ('document.pdf', file, 'application/pdf')}
data = {'description': 'User uploaded file'}
response = requests.post(
'https://api.example.com/upload',
files=files,
data=data
# Content-Type se establece automáticamente con boundary
)
return response.json()
# Enviar Datos URL-encoded de Formulario
def submit_form(form_data):
response = requests.post(
'https://api.example.com/form',
data=form_data, # Establece automáticamente Content-Type: application/x-www-form-urlencoded
headers={'Authorization': 'Bearer YOUR_TOKEN'}
)
return response.json()
Diagrama
graph TB
subgraph "Content-Types de Petición"
REQ1[application/json]
REQ2[application/xml]
REQ3[multipart/form-data]
REQ4[application/x-www-form-urlencoded]
REQ5[text/plain]
end
subgraph "Content-Types de Respuesta"
RES1[application/json]
RES2[text/html]
RES3[application/pdf]
RES4[image/png]
RES5[text/csv]
end
subgraph "Procesamiento del Servidor"
PARSE[Parsear Cuerpo Basado en Content-Type]
VALIDATE[Validar Formato]
PROCESS[Procesar Datos]
end
REQ1 --> PARSE
REQ2 --> PARSE
REQ3 --> PARSE
REQ4 --> PARSE
REQ5 --> PARSE
PARSE --> VALIDATE
VALIDATE --> PROCESS
PROCESS --> RES1
PROCESS --> RES2
PROCESS --> RES3
PROCESS --> RES4
PROCESS --> RES5
Analogía
Piensa en Content-Type como una etiqueta en el empaquetado de alimentos:
- Content-Type: application/json → “Esto es JSON, parsearlo como datos estructurados”
- Content-Type: text/plain → “Esto es texto plano, no se necesita parseo especial”
- Content-Type: multipart/form-data → “Esto contiene múltiples partes (archivos + campos)”
Sin la etiqueta, no sabrías si es sopa, cereal o pizza congelada. Sin Content-Type, el servidor no sabe cómo interpretar los datos.
Mejores Prácticas
- Siempre Establecer Content-Type - Especificar el formato del cuerpo en peticiones y respuestas
- Coincidir Formato del Cuerpo - Asegurar que el contenido real coincide con el Content-Type declarado
- Incluir Charset - Añadir
charset=utf-8para formatos basados en texto - Validar en Servidor - Verificar Content-Type antes de parsear el cuerpo
- Usar Tipos MIME Estándar - Seguir tipos de medio registrados por IANA
- No Sobrescribir FormData - Dejar que el navegador establezca Content-Type con boundary para subidas multipart
- Establecer Tipo Correcto para Descargas - Usar
application/octet-streamo tipos específicos para descargas de archivos
Errores Comunes
- Content-Type Faltante - Enviar JSON sin
Content-Type: application/json - Content-Type Incorrecto - Declarar
application/jsonpero enviar XML o texto plano - Boundary Hardcodeado - Establecer manualmente boundary en
multipart/form-dataen lugar de dejar que el cliente lo genere - Sin Charset - No especificar
charset=utf-8para respuestas de texto/JSON - Ignorar Content-Type - Parsear cuerpo de petición sin verificar Content-Type primero
- Usar application/json para HTML - Devolver HTML con
Content-Type: application/json - Confiar en Cabecera del Cliente - No validar que Content-Type coincide con el contenido real