Definición
La cabecera Accept es una cabecera de petición HTTP que dice al servidor qué tipos de medio (tipos MIME) el cliente puede entender y procesar en la respuesta. Habilita la negociación de contenido, permitiendo a servidores devolver datos en el formato preferido por el cliente.
La cabecera consiste en:
- Lista de Tipos de Medio - Tipos MIME separados por comas (ej.
application/json, text/html) - Valores de Calidad (q) - Pesos de prioridad de 0 a 1 (ej.
application/json;q=0.9)
Valores comunes de Accept:
application/json- Preferir respuestas JSONtext/html- Preferir HTML (navegadores)application/xml- Preferir XML*/*- Aceptar cualquier formato (por defecto si no se especifica)
El servidor selecciona el mejor formato coincidente basado en lo que soporta y las preferencias del cliente.
Ejemplo
Preferencia JSON:
GET /api/users/123 HTTP/1.1
Host: api.example.com
Accept: application/json
Authorization: Bearer YOUR_TOKEN
Múltiples Formatos con Prioridades:
GET /api/users/123 HTTP/1.1
Host: api.example.com
Accept: application/json;q=0.9, application/xml;q=0.7, text/plain;q=0.5, */*;q=0.1
Authorization: Bearer YOUR_TOKEN
Petición de Navegador (HTML preferido):
GET /page HTTP/1.1
Host: example.com
Accept: text/html,application/xhtml+xml,application/xml;q=0.9,image/webp,*/*;q=0.8
Accept-Language: en-US,en;q=0.9
User-Agent: Mozilla/5.0
Respuesta del Servidor (coincidiendo con Accept):
HTTP/1.1 200 OK
Content-Type: application/json; charset=utf-8
Content-Length: 142
{
"id": 123,
"name": "Alice Smith"
}
Ejemplo de Código
JavaScript (Fetch API):
// Solicitar JSON específicamente
const fetchUser = async (userId) => {
const response = await fetch(`https://api.example.com/users/${userId}`, {
headers: {
'Accept': 'application/json', // Solo aceptar JSON
'Authorization': 'Bearer YOUR_TOKEN'
}
});
// Verificar si el servidor devolvió JSON
const contentType = response.headers.get('Content-Type');
if (!contentType || !contentType.includes('application/json')) {
throw new Error(`Expected JSON, got ${contentType}`);
}
return await response.json();
};
// Aceptar múltiples formatos con prioridades
const fetchData = async (resourceId, format = 'json') => {
const acceptHeaders = {
'json': 'application/json',
'xml': 'application/xml',
'html': 'text/html',
'any': '*/*'
};
const response = await fetch(`https://api.example.com/resource/${resourceId}`, {
headers: {
'Accept': acceptHeaders[format] || 'application/json',
'Authorization': 'Bearer YOUR_TOKEN'
}
});
const contentType = response.headers.get('Content-Type');
// Parsear basado en Content-Type real devuelto
if (contentType.includes('application/json')) {
return await response.json();
} else if (contentType.includes('application/xml')) {
return await response.text(); // Parsear XML como texto
} else if (contentType.includes('text/html')) {
return await response.text();
} else {
throw new Error(`Unsupported Content-Type: ${contentType}`);
}
};
// Ejemplo: Accept con valores de calidad
const fetchWithPriorities = async (userId) => {
const response = await fetch(`https://api.example.com/users/${userId}`, {
headers: {
'Accept': 'application/json;q=0.9, application/xml;q=0.7, text/plain;q=0.5',
'Authorization': 'Bearer YOUR_TOKEN'
}
});
return await response.json();
};
Python (librería requests):
import requests
# Solicitar JSON específicamente
def fetch_user(user_id):
response = requests.get(
f'https://api.example.com/users/{user_id}',
headers={
'Accept': 'application/json', # Solo aceptar JSON
'Authorization': 'Bearer YOUR_TOKEN'
}
)
# Verificar si el servidor devolvió JSON
content_type = response.headers.get('Content-Type', '')
if 'application/json' not in content_type:
raise ValueError(f'Expected JSON, got {content_type}')
response.raise_for_status()
return response.json()
# Aceptar múltiples formatos con prioridades
def fetch_data(resource_id, format='json'):
accept_headers = {
'json': 'application/json',
'xml': 'application/xml',
'html': 'text/html',
'any': '*/*'
}
response = requests.get(
f'https://api.example.com/resource/{resource_id}',
headers={
'Accept': accept_headers.get(format, 'application/json'),
'Authorization': 'Bearer YOUR_TOKEN'
}
)
content_type = response.headers.get('Content-Type', '')
# Parsear basado en Content-Type real devuelto
response.raise_for_status()
if 'application/json' in content_type:
return response.json()
elif 'application/xml' in content_type:
return response.text # Parsear XML como texto
elif 'text/html' in content_type:
return response.text
else:
raise ValueError(f'Unsupported Content-Type: {content_type}')
# Ejemplo: Accept con valores de calidad
def fetch_with_priorities(user_id):
response = requests.get(
f'https://api.example.com/users/{user_id}',
headers={
'Accept': 'application/json;q=0.9, application/xml;q=0.7, text/plain;q=0.5',
'Authorization': 'Bearer YOUR_TOKEN'
}
)
response.raise_for_status()
return response.json()
Diagrama
sequenceDiagram
participant Client
participant Server
Note over Client: Establecer Cabecera Accept
Client->>Client: Accept: application/json;q=0.9,
application/xml;q=0.7
Client->>Server: GET /api/users/123
Accept: application/json;q=0.9, application/xml;q=0.7
Note over Server: Negociación de Contenido
Server->>Server: Verificar formatos soportados
Server->>Server: Coincidir con preferencias de Accept
Server->>Server: Seleccionar mejor formato (JSON - q=0.9)
Server->>Client: HTTP 200 OK
Content-Type: application/json
Body: {"id": 123, ...}
Note over Client: Verificar Content-Type
Client->>Client: Parsear como JSON
Client->>Client: Actualizar UI
Analogía
Piensa en la cabecera Accept como ordenar en un restaurante:
- Accept: application/json → “Quiero formato JSON, nada más”
- Accept: application/json;q=0.9, application/xml;q=0.7 → “Prefiero JSON, pero XML también está bien”
- Accept: /" → “Tomaré lo que tengas”
El camarero (servidor) verifica qué está disponible y te da el plato (formato) que mejor coincide con tus preferencias.
Mejores Prácticas
- Siempre Establecer Accept - Especificar formato de respuesta esperado explícitamente
- Usar Valores de Calidad - Añadir prioridades (valores q) cuando se aceptan múltiples formatos
- Validar Content-Type - Verificar que el Content-Type de respuesta coincide con tu Accept
- Evitar /" - Ser explícito sobre formatos a menos que puedas manejar realmente cualquier cosa
- Manejar 406 Not Acceptable - Manejar graciosamente casos donde el servidor no puede proporcionar el formato solicitado
- Establecer Accept-Language - Usar para internacionalización junto con Accept
- Usar Versionado - Combinar con
Accept: application/vnd.api.v2+jsonpara versionado de API
Errores Comunes
- No Establecer Accept - Confiar en valores por defecto del servidor en lugar de ser explícito
- Ignorar Content-Type - Asumir formato de respuesta sin verificar cabecera Content-Type
- Usar / Siempre - No especificar preferencias, haciendo la negociación de contenido inútil
- Valores de Calidad Incorrectos - Usar q > 1.0 o valores negativos (q debe ser 0.0 a 1.0)
- No Manejar 406 - Fallar al manejar “406 Not Acceptable” cuando el servidor no puede proporcionar el formato solicitado
- Cabeceras Conflictivas - Establecer
Accept: application/jsonpero esperar XML - Valores por Defecto de Navegador - No sobrescribir
Accept: text/htmlpor defecto del navegador en llamadas a API