406 Not Acceptable
Usage
When a 406 Not Acceptable error arrives, the response is triggered by a negotiation-related header such as Accept or Accept-Language. When the client includes one or more of these headers, the server satisfies the requirements when possible.
The most common HTTP Accept headers are:
Accept: Specifies the preferred content type. A server supplies either plain text or an HTML representation. In this example, the client prefers HTML but accepts plain text.
Accept: text/html, text/plain
Accept-Encoding: Specifies encodings the client accepts. In this example, the client indicates support for gzip Compression.
Accept-Encoding: gzip
In practice, this error is rarely used because the server supplies a default representation instead. The rationale assumes the client prefers something over nothing. When the 406 Not Acceptable response is returned, the message body contains a list of available representations the client selects from.
Example
The client requests a resource in French, but the server responds with 406 Not Acceptable because only German and English versions are available.
Request
GET /news HTTP/1.1
Host: example.com
Accept-Language: fr
Response
HTTP/1.1 406 Not Acceptable
Content-Type: text/html
Content-Length: 242
<html>
<head>
<title>French Language Not Available</title>
</head>
<body>
<p>Please choose a supported language:</p>
<p><a href="/news/news-de.html">German</a></p>
<p><a href="/news/news-en.html">English</a></p>
</body>
</html>
How to fix
A 406 Not Acceptable means the server has no representation matching the client’s content negotiation headers.
Review the Accept header. Broaden the accepted media types. For example, add application/json alongside text/html, or use / to accept any format. Use browser DevTools (Network tab) or curl -v to inspect the exact Accept header the client sends.
Check Accept-Language constraints. Requesting a language the server does not support triggers this error. Widen the language list or add a wildcard (*) fallback. Browser language settings control this header automatically. Adjust them in the browser’s language preferences.
Remove overly restrictive Accept-Encoding or Accept-Charset values. A narrow encoding or charset requirement limits the server’s options. Allow common values like gzip, deflate and UTF-8.
Inspect the response body for available alternatives. The server often lists supported representations in the 406 response. Select one and adjust the negotiation headers accordingly.
Check server-side content negotiation configuration. Misconfigured type maps or missing MIME type registrations on the server cause unexpected 406 responses. In Apache, mod_negotiation and MultiViews control type maps. Verify the AddType directives register the required MIME types.
Check mod_security or WAF rules. Apache’s mod_security (and similar WAFs) intercepts requests and returns 406 when a rule triggers on the request content, not the Accept header. Check the server error log for a ModSecurity entry and note the rule ID (e.g., [id “941160”]). Allowlist the specific rule rather than disabling the WAF entirely:
SecRuleRemoveById 941160
Place the exclusion in the virtual host config or .htaccess file.
Test with a minimal request. Strip all negotiation headers and send a bare request with curl to determine whether the server returns a default representation. If the bare request succeeds, add negotiation headers back one at a time to isolate which header triggers the rejection.
Verify API version negotiation. Some APIs use the Accept header for versioning (e.g., application/vnd.api.v2+json). Sending an unsupported version string produces 406. Confirm the version value against the API documentation.
Code references
.NET
HttpStatusCode.NotAcceptable
Rust
http::StatusCode::NOT_ACCEPTABLE
Rails
:not_acceptable
Go
http.StatusNotAcceptable
Symfony
Response::HTTP_NOT_ACCEPTABLE
Python3.5+
http.HTTPStatus.NOT_ACCEPTABLE
Java
java.net.HttpURLConnection.HTTP_NOT_ACCEPTABLE
Apache HttpComponents Core
org.apache.hc.core5.http.HttpStatus.SC_NOT_ACCEPTABLE
Angular
@angular/common/http/HttpStatusCode.NotAcceptable