What is the 406 Not Acceptable Error?
The 406 Not Acceptable is an HTTP client error status code that indicates the server cannot produce a response matching the list of acceptable values defined in the request’s proactive content negotiation headers. Unlike server errors (5xx) or client errors like 404 (Not Found), 406 Not Acceptable specifically addresses a mismatch between what the client asks for and what the server can actually deliver.
When you encounter a 406 Not Acceptable Error, it means your browser or application has requested content with specific requirements (format, encoding, or language) that the server cannot satisfy with its available resources. In this article, we will understand how to fix 406 Not Acceptable Error.
How Content Negotiation Triggers 406 Errors
Proactive content negotiation happens through specific HTTP headers. The three main headers involved are:
- Accept: Specifies preferred media types (like
application/json,text/html) - Accept-Encoding: Defines acceptable content encodings (like
gzip,br) - Accept-Language: Indicates preferred languages (like
en-US,fr-FR)
Real-World Example: Why 406 Happens
Consider this API request:
GET /api/users/123 HTTP/1.1 Host: api.example.com Accept: application/xml
If the server only supports JSON responses, it should return:
HTTP/1.1 406 Not Acceptable
Content-Type: application/json
{
"error": "Unsupported media type",
"available_formats": ["application/json"],
"message": "This endpoint only supports JSON responses"
}
Step-by-Step: How to Fix 406 Not Acceptable Error
Solution 1: Adjust Client Request Headers (Most Common Fix)
The most common fix for 406 Not Acceptable involves examining the Accept headers sent by your client:
- Browser Requests: Most browsers automatically send Accept headers. You can use browser developer tools (F12 → Network tab) to examine what headers are being sent.
- API Clients: If you’re using tools like Postman, cURL, or custom code, explicitly set Accept headers to match what the server can provide.
- Adjust Headers: Try changing the Accept header to a more generic value like
*/*or to specifically match the server’s capabilities.
For API Consumers and Developers:
If you’re making API calls and receiving 406 Not Acceptable, modify your Accept headers:
// Before: Requesting XML when server only has JSON
fetch('https://api.example.com/data', {
headers: {
'Accept': 'application/xml' // Causes 406 if server doesn't support XML
}
});
// After: Requesting JSON or using wildcard
fetch('https://api.example.com/data', {
headers: {
'Accept': 'application/json' // Specific type server supports
}
});
// OR use wildcard to accept anything
fetch('https://api.example.com/data', {
headers: {
'Accept': '*/*' // Accept any response type
}
});
For Browser Issues:
- Open Developer Tools (F12)
- Go to Network tab
- Reload the page
- Check the request headers being sent
- Use browser extensions to modify headers if needed
Solution 2: Server-Side Configuration for Web Administrators
If you control the server, consider these adjustments to resolve 406 Not Acceptable:
- Configure Content Negotiation: Ensure your web server (Apache, Nginx, IIS) is properly configured to handle the content types your clients are requesting.
- Check MIME Type Settings: Verify that your server has the correct MIME types configured for the files or responses being served.
- Review Application Settings: For applications like WordPress, check plugin conflicts or theme issues that might be affecting content negotiation.
If you control the server, implement proper content negotiation:
Apache (.htaccess):
# Ensure proper MIME types AddType application/json .json AddType text/html .html # Handle Accept header negotiation <IfModule mod_negotiation.c> # Set default to HTML if no Accept header matches Options +MultiViews ForceType text/html </IfModule>
Nginx Configuration:
location /api/ {
# Default to JSON if Accept header doesn't match
if ($http_accept ~* "application/json") {
add_header Content-Type application/json;
}
# Return 406 only for truly unsupported types
if ($http_accept !~* "(application/json|text/html|\*/\*)") {
return 406;
}
# Default response type
default_type application/json;
}
Solution 3: Framework-Specific Implementations
Each web framework handles content negotiation differently. Configure your server-side framework to properly validate Accept headers and provide appropriate fallbacks or detailed 406 responses when clients request unsupported formats. The key is implementing robust content negotiation logic that either satisfies the request or clearly communicates available alternatives.
Express.js Example:
const express = require('express');
const app = express();
// Middleware to handle content negotiation
app.use((req, res, next) => {
const acceptHeader = req.get('Accept') || '*/*';
// Check if we support requested type
const supportedTypes = ['application/json', 'text/html'];
const acceptedTypes = acceptHeader.split(',').map(t => t.trim());
const canServe = acceptedTypes.some(type =>
supportedTypes.includes(type) || type === '*/*'
);
if (!canServe && acceptHeader !== '*/*') {
return res.status(406).json({
error: 'Not Acceptable',
message: 'Supported content types: application/json, text/html',
acceptHeader: acceptHeader
});
}
next();
});
app.get('/api/data', (req, res) => {
const accept = req.get('Accept');
if (accept.includes('text/html')) {
res.send('<html><body>Data: example</body></html>');
} else {
res.json({ data: 'example' });
}
});
Django REST Framework:
# settings.py
REST_FRAMEWORK = {
'DEFAULT_RENDERER_CLASSES': [
'rest_framework.renderers.JSONRenderer',
'rest_framework.renderers.BrowsableAPIRenderer', # HTML for browser
],
'DEFAULT_CONTENT_NEGOTIATION_CLASS':
'rest_framework.negotiation.DefaultContentNegotiation',
}
# views.py
from rest_framework.views import APIView
from rest_framework.response import Response
from rest_framework import status
class UserView(APIView):
def get(self, request):
# Check Accept header
accepted = request.META.get('HTTP_ACCEPT', '*/*')
if 'application/xml' in accepted and 'application/json' not in accepted:
return Response(
{'error': 'XML not supported. Use application/json'},
status=status.HTTP_406_NOT_ACCEPTABLE
)
return Response({'user': 'data'})
Solution 4: Fix ModSecurity False Positives
ModSecurity and other web application firewalls often trigger 406 Not Acceptable errors:
- Temporarily Disable ModSecurity: To test if this is the cause, temporarily disable ModSecurity rules.
- Review Security Logs: Check ModSecurity audit logs for specific rules that might be blocking the request.
- Whitelist Accept Headers: Adjust your security rules to allow the Accept headers your legitimate clients are using.
ModSecurity rules often trigger 406 Not Acceptable Error. To diagnose:
- Check ModSecurity logs:
# Apache tail -f /var/log/apache2/modsec_audit.log # Look for rules like 959100, 959010 which block certain Accept headers
- Temporarily disable to test:
# In .htaccess or virtual host <IfModule mod_security2.c> SecRuleRemoveById 959100 SecRuleRemoveById 959010 </IfModule>
- Whitelist legitimate Accept headers:
SecRule REQUEST_HEADERS:Accept "@rx ^(application/json|text/html|\*/\*|application/xml)" \
"id:1001,phase:1,pass,nolog,ctl:ruleRemoveById=959100"
Solution 5: Implement Proper Error Responses
When your server must return a 406 Not Acceptable Error, don’t just send a generic status code. Transform this error into a helpful conversation by providing detailed, actionable responses that guide clients toward available alternatives. Well-crafted 406 responses should serve as a roadmap, not a dead end—clearly explaining what went wrong, what content types you do support, and how clients can successfully retrieve the resource they need.
When returning 406 Not Acceptable, provide helpful information:
# Python Flask example
from flask import Flask, jsonify, request
app = Flask(__name__)
@app.route('/data')
def get_data():
supported = ['application/json', 'text/plain']
accept = request.headers.get('Accept', '*/*')
# Check if we can satisfy the request
if not any(media_type in accept for media_type in supported) and accept != '*/*':
return jsonify({
"error": "406 Not Acceptable",
"message": "Cannot satisfy Accept header requirements",
"requested": accept,
"supported": supported,
"suggestion": "Try Accept: application/json"
}), 406, {'Content-Type': 'application/json'}
# Normal response handling...
Testing and Debugging Strategies
Using cURL for Diagnosis
# Test different Accept headers curl -H "Accept: application/xml" https://api.example.com/data # Returns 406 curl -H "Accept: application/json" https://api.example.com/data # Returns 200 with JSON curl -H "Accept: */*" https://api.example.com/data # Returns 200 with server's default # Verbose output to see headers curl -v -H "Accept: application/rtf" https://api.example.com/docs/doc1
Browser Developer Tools Approach
- Open Network tab in DevTools
- Find the failing request
- Right-click → Copy → Copy as cURL
- Modify the Accept header in the copied command
- Test in terminal to isolate the issue
Best Practices to Prevent 406 Errors
Client-Side:
- Always specify fallback Accept headers:
Accept: application/json, text/html, */* - Implement retry logic with different Accept headers
- Parse server’s 406 response for supported types
Server-Side:
- Implement graceful fallbacks to default representations
- Provide detailed error messages in 406 responses
- Support common Accept header patterns
- Document supported media types in API documentation
API Design:
# Good: Server returns helpful 406 response
HTTP/1.1 406 Not Acceptable
Content-Type: application/json
{
"error": "unsupported_media_type",
"message": "Requested 'application/rtf' not available",
"supported_types": [
"text/html",
"application/json",
"application/pdf"
],
"links": {
"html": "/docs/doc1.html",
"json": "/api/docs/doc1",
"pdf": "/docs/doc1.pdf"
}
}
When 406 Should (and Shouldn’t) Be Used
Use 406 when:
- You have multiple representations available
- The client explicitly requests an unsupported format
- You want to guide the client to available options
Consider alternatives:
- 200 OK with default representation: When you have a reasonable default
- 300 Multiple Choices: When you want to redirect to available options
- 415 Unsupported Media Type: For request body format issues (not Accept header)
Conclusion: 406 Not Acceptable Error
Understanding and fixing 406 Not Acceptable Error requires attention to the HTTP content negotiation process. Whether you’re a client developer adjusting request headers or a server administrator configuring proper response handling, the key is ensuring alignment between client expectations and server capabilities.
By implementing the solutions outlined in this guide on how to fix 406 Not Acceptable Error, you can transform a frustrating error into a helpful dialogue between client and server, ultimately creating more robust and user-friendly web applications and APIs.
Remember: The 406 Not Acceptable response, when implemented properly, isn’t just an error—it’s an opportunity to communicate clearly with clients about what you can provide and guide them toward successful interactions with your server.
For more technical details and official specifications about the 406 Not Acceptable Error, refer to the MDN Web Docs HTTP 406 documentation.
FAQs: How to Fix 406 Not Acceptable Error
What does a 406 Not Acceptable error mean for a regular website visitor?
It typically means the website received a request from your browser for a specific format (like a document type or language) that the server cannot provide. This is often a technical configuration issue, not a problem with your computer. Refreshing the page, clearing your browser cache, or trying a different browser can sometimes resolve it.
How is a 406 error different from a 404 or 500 error?
A 404 (Not Found) means the requested resource doesn’t exist on the server. A 500 (Internal Server Error) indicates a server-side failure. A 406 (Not Acceptable) is more specific: the resource exists, but the server cannot deliver it in the format your browser requested (e.g., your browser asked for XML, but the server only has JSON).
I’m a user, not a developer. What can I do to fix a 406 error on a site?
Try these simple steps:
- Refresh the page (Ctrl+F5 or Cmd+Shift+R for a hard refresh)
- Clear your browser cache and cookies
- Try a different browser (Chrome, Firefox, Edge)
- Disable browser extensions temporarily, as some modify request headers
- Check your browser’s language settings if the site is multilingual
I’m building an API. When should I return a 406 vs. a 200 with a default format?
Use 406 when the client’s Accept header is specific and intentional (e.g., Accept: application/xml), and you want to enforce strict content negotiation. Return a 200 with a default (like JSON) when you want to be flexible and prioritize successful delivery over strict adherence to the request headers. Your API documentation should state which behavior clients can expect.
Can a 406 error be caused by security software or a firewall?
Yes. Web Application Firewalls (WAFs) like ModSecurity often have rules that block requests with unusual or potentially malicious Accept headers. If you suddenly see a 406 error on a site that worked before, a security rule update might be the cause. Website administrators need to check their WAF logs for rules triggering the block.
What should a helpful 406 error response include?
A good 406 response should be in a format the client can accept (often falling back to JSON or plain text) and contain:
- A clear error message
- The
Acceptheader value you received - A list of media types you do support (e.g.,
application/json,text/html) - Optional: Links to the resource in those supported formats
Is the Accept header the only cause of a 406 error?
No, while Accept is the most common culprit, the 406 Not Acceptable status can also be triggered by other content negotiation headers:
Accept-Language: Requesting a language variant (e.g.,en-GB) not available.Accept-Encoding: Requesting a compression algorithm (e.g.,brfor Brotli) the server doesn’t support.
Always check all relevant headers when debugging.
How can I test for 406 errors as a developer?
Use command-line tools like curl to send requests with specific headers:
curl -H "Accept: application/xml" https://your-api.com/data
Inspect the full response. Browser Developer Tools (Network tab) also show the request headers your browser sends, which you can compare with what the server expects.
Should my web application proactively prevent 406 errors for end-users?
Absolutely. On the server side, implement content negotiation logic with sensible defaults. For instance, if a request has Accept: application/xml but you only serve HTML and JSON, you can either:
- Fall back to serving your default (e.g., HTML) with a 200 status.
- Redirect the user to a supported version of the resource.
Preventing the error from reaching the user is often better than handling it.
Does a 406 error affect SEO?
Indirectly, yes. If search engine crawlers (like Googlebot) encounter 406 errors when trying to access your content with specific Accept headers, they may not be able to index that content properly. Ensure your server can handle common crawler request patterns, often by implementing fallbacks for Accept headers you don’t fully support.

How to Fix 405 Method Not Allowed: Easy Steps