406 Not Acceptable
The HTTP 406 Not Acceptable status code is a client error returned by the server to indicate the resource exists but the proactive content negotiation engaged in by the client was not satisfiable, and the server does not supply a default representation.
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.
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
Takeaway
The 406 Not Acceptable status code is a client error returned when the client-specified proactive negotiation requirements are not satisfiable and the server is unwilling to send a default representation.
See also
- RFC 9110: HTTP Semantics
- Google: HTTP status codes and network errors
- Accept
- Accept-Language
- Accept-Encoding
- Content negotiation
- HTTP status codes