Definition
The Accept header is an HTTP request header that tells the server which media types (MIME types) the client can understand and process in the response. It enables content negotiation, allowing servers to return data in the format preferred by the client.
The header consists of:
- Media Type List - Comma-separated MIME types (e.g.,
application/json, text/html) - Quality Values (q) - Priority weights from 0 to 1 (e.g.,
application/json;q=0.9)
Common Accept values:
application/json- Prefer JSON responsestext/html- Prefer HTML (browsers)application/xml- Prefer XML*/*- Accept any format (default if not specified)
The server selects the best matching format based on what it supports and the client’s preferences.
Example
JSON Preference:
GET /api/users/123 HTTP/1.1
Host: api.example.com
Accept: application/json
Authorization: Bearer YOUR_TOKEN
Multiple Formats with Priorities:
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
Browser Request (HTML preferred):
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
Server Response (matching Accept):
HTTP/1.1 200 OK
Content-Type: application/json; charset=utf-8
Content-Length: 142
{
"id": 123,
"name": "Alice Smith"
}
Code Example
JavaScript (Fetch API):
// Request JSON specifically
const fetchUser = async (userId) => {
const response = await fetch(`https://api.example.com/users/${userId}`, {
headers: {
'Accept': 'application/json', // Only accept JSON
'Authorization': 'Bearer YOUR_TOKEN'
}
});
// Check if server returned 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();
};
// Accept multiple formats with priorities
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');
// Parse based on actual Content-Type returned
if (contentType.includes('application/json')) {
return await response.json();
} else if (contentType.includes('application/xml')) {
return await response.text(); // Parse XML as text
} else if (contentType.includes('text/html')) {
return await response.text();
} else {
throw new Error(`Unsupported Content-Type: ${contentType}`);
}
};
// Example: Accept with quality values
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 (requests library):
import requests
# Request JSON specifically
def fetch_user(user_id):
response = requests.get(
f'https://api.example.com/users/{user_id}',
headers={
'Accept': 'application/json', # Only accept JSON
'Authorization': 'Bearer YOUR_TOKEN'
}
)
# Check if server returned 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()
# Accept multiple formats with priorities
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', '')
# Parse based on actual Content-Type returned
response.raise_for_status()
if 'application/json' in content_type:
return response.json()
elif 'application/xml' in content_type:
return response.text # Parse XML as text
elif 'text/html' in content_type:
return response.text
else:
raise ValueError(f'Unsupported Content-Type: {content_type}')
# Example: Accept with quality values
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()
Diagram
sequenceDiagram
participant Client
participant Server
Note over Client: Set Accept Header
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: Content Negotiation
Server->>Server: Check supported formats
Server->>Server: Match with Accept preferences
Server->>Server: Select best format (JSON - q=0.9)
Server->>Client: HTTP 200 OK
Content-Type: application/json
Body: {"id": 123, ...}
Note over Client: Verify Content-Type
Client->>Client: Parse as JSON
Client->>Client: Update UI
Analogy
Think of the Accept header like ordering at a restaurant:
- Accept: application/json β “I want JSON format, nothing else”
- Accept: application/json;q=0.9, application/xml;q=0.7 β “I prefer JSON, but XML is also fine”
- **Accept: /" β “I’ll take whatever you’ve got”
The waiter (server) checks what’s available and gives you the dish (format) that best matches your preferences.
Best Practices
- Always Set Accept - Specify expected response format explicitly
- Use Quality Values - Add priorities (q values) when accepting multiple formats
- Validate Content-Type - Check the response Content-Type matches your Accept
- **Avoid /" - Be explicit about formats unless you can truly handle anything
- Handle 406 Not Acceptable - Gracefully handle cases where server can’t provide requested format
- Set Accept-Language - Use for internationalization alongside Accept
- Use Versioning - Combine with
Accept: application/vnd.api.v2+jsonfor API versioning
Common Mistakes
- Not Setting Accept - Relying on server defaults instead of being explicit
- Ignoring Content-Type - Assuming response format without checking Content-Type header
- Using / Always - Not specifying preferences, making content negotiation useless
- Wrong Quality Values - Using q > 1.0 or negative values (q must be 0.0 to 1.0)
- Not Handling 406 - Failing to handle “406 Not Acceptable” when server can’t provide requested format
- Conflicting Headers - Setting
Accept: application/jsonbut expecting XML - Browser Defaults - Not overriding browser’s default
Accept: text/htmlin API calls