406 Not Acceptable
Unsatisfiable content negotiation preferences from the client produce the 406 Not Acceptable status code. The resource exists but the server has no representation matching the requested format, language, or encoding.
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/plainAccept-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.
Note
406 Not Acceptable means the server cannot produce a response matching the client's Accept headers (output format problem). 415 Unsupported Media Type means the server does not understand the Content-Type of the request body (input format problem). 406 is about what the client wants to receive while 415 is about what the client sent.
SEO impact
Search engines like Google do not index a URL returning a 406 Not Acceptable status. Previously indexed URLs returning this status code are removed from search results.
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: www.example.re
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/jsonalongsidetext/html, or use*/*to accept any format. Use browser DevTools (Network tab) orcurl -vto 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, deflateandUTF-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_negotiationandMultiViewscontrol type maps. Verify theAddTypedirectives 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 aModSecurityentry and note the rule ID (e.g.,[id "941160"]). Allowlist the specific rule rather than disabling the WAF entirely:SecRuleRemoveById 941160Place the exclusion in the virtual host config or
.htaccessfile.Test with a minimal request. Strip all negotiation headers and send a bare request with
curlto 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
See also
- RFC 9110: HTTP Semantics
- Google: HTTP status codes and network errors
- Accept
- Accept-Language
- Accept-Encoding
- Content negotiation
- HTTP status codes