Cabecera Accept

Fundamentos Jan 9, 2026 HTTP
http headers content-negotiation mime rest

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:

  1. Lista de Tipos de Medio - Tipos MIME separados por comas (ej. application/json, text/html)
  2. 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 JSON
  • text/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

  1. Siempre Establecer Accept - Especificar formato de respuesta esperado explícitamente
  2. Usar Valores de Calidad - Añadir prioridades (valores q) cuando se aceptan múltiples formatos
  3. Validar Content-Type - Verificar que el Content-Type de respuesta coincide con tu Accept
  4. Evitar /" - Ser explícito sobre formatos a menos que puedas manejar realmente cualquier cosa
  5. Manejar 406 Not Acceptable - Manejar graciosamente casos donde el servidor no puede proporcionar el formato solicitado
  6. Establecer Accept-Language - Usar para internacionalización junto con Accept
  7. Usar Versionado - Combinar con Accept: application/vnd.api.v2+json para 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/json pero esperar XML
  • Valores por Defecto de Navegador - No sobrescribir Accept: text/html por defecto del navegador en llamadas a API

Estándares & RFCs

Términos Relacionados