Skip to main content
4xx Client Error

406 Not Acceptable

The server cannot produce a response matching the list of acceptable values defined in the request's headers.

Meaning & Description

The 406 Not Acceptable status code indicates that the target resource does not have a current representation that would be acceptable to the user agent, according to the proactive negotiation header fields received in the request, and the server is unwilling to supply a default representation.

Common Causes

  • Mismatch between client `Accept` headers and server supported Content-Types
  • Misconfigured HTTP clients sending overly restrictive `Accept` headers
  • Strict content negotiation rules enabled on the web framework

How to fix a 406 error

  1. Check the `Accept` header sent by the client.
  2. Compare it with the content types the server is capable of returning (e.g., application/json).
  3. Update the client request to accept the server's supported formats, or update the server to support the requested format.
  4. Relax server strictness to return a default format if the `Accept` header is unsupported.

Browser & SEO Behaviour

Browser Behavior

Usually not encountered by normal browser navigation, as browsers send very permissive Accept headers (e.g., text/html,application/xhtml+xml,application/xml;q=0.9,*/*;q=0.8).

SEO Impact

No direct SEO impact as crawlers usually accept text/html. If an API returns 406, it does not affect page ranking.

CDN Behavior

Not cached by default.

Code Examples

Node.js (Express)
app.get('/api/data', (req, res) => {
  if (!req.accepts('json')) {
    return res.status(406).send('Not Acceptable: This API only returns JSON.');
  }
  res.json({ message: 'Success' });
});
Python (FastAPI)
from fastapi import FastAPI, Request, HTTPException

app = FastAPI()

@app.get("/data")
def get_data(request: Request):
    accept = request.headers.get("accept", "")
    if "application/json" not in accept and "*/*" not in accept:
        raise HTTPException(status_code=406, detail="Only application/json is supported")
    return {"data": "Success"}
Go (net/http)
func handler(w http.ResponseWriter, r *http.Request) {
    accept := r.Header.Get("Accept")
    if !strings.Contains(accept, "application/json") && accept != "*/*" {
        http.Error(w, "Not Acceptable", http.StatusNotAcceptable)
        return
    }
    w.Header().Set("Content-Type", "application/json")
    w.Write([]byte(`{"message":"ok"}`))
}
C# (ASP.NET Core)
// In ASP.NET Core, if you configure MvcOptions.ReturnHttpNotAcceptable = true,
// the framework automatically returns 406 when the client requests an unsupported format.
builder.Services.AddControllers(options =>
{
    options.ReturnHttpNotAcceptable = true;
});
curl
curl -i -X GET https://api.example.com/data \
  -H "Accept: application/xml"

Raw HTTP Response Example

HTTP Response
HTTP/1.1 406 Not Acceptable
Content-Type: application/json
Content-Length: 51

{
  "error": "This endpoint only supports JSON"
}

Real-world Examples

Spring Boot REST APIs: Often returns 406 if content negotiation fails and no suitable message converter is found.
GitHub API: Can return 406 if you request a custom media type that isn't valid for the endpoint.
Apache ModSecurity: Sometimes uses 406 to block requests that violate security rules regarding HTTP headers.

Frequently Asked Questions

What is the difference between 406 and 415?

415 Unsupported Media Type means the client sent data in a format the server doesn't accept. 406 Not Acceptable means the client requested the response to be in a format the server cannot produce.

Why am I getting a 406 error?

Your HTTP client is sending an `Accept` header (e.g., requesting XML) that the server cannot fulfill (because it only outputs JSON).

Should a server always strictly enforce the Accept header?

No, it is often more pragmatic to ignore the Accept header and return the default format (like JSON) rather than failing with a 406, unless you are building a strict hypermedia API.

How do I fix a 406 Not Acceptable error?

Change the `Accept` header in your request to match what the server provides, or add `*/*` to accept any format.

Does it apply to Accept-Language too?

Yes, theoretically. If a client strictly requests `Accept-Language: fr` and the server only has English, it could return 406. In practice, servers usually just return the default language instead.

Did You Know?

In practice, many servers ignore strict content negotiation and just return their default format instead of a 406, prioritizing usability over strict HTTP compliance.

Security firewalls like ModSecurity sometimes hijack the 406 status code to silently drop malicious requests without giving hackers useful feedback.

Developer Tips

  • Unless you have a specific reason to strictly enforce content negotiation, it is often better to fall back to a default format (like JSON) instead of returning a 406.
  • If you do return a 406, include a payload that lists the available representations (e.g., `["application/json"]`) to help the developer fix their request.
  • Check if your web framework has a setting like `ReturnHttpNotAcceptable`. Many default to false and just send JSON regardless of the Accept header.

Interview Questions

These are questions you might face in a backend or API design interview that touch on HTTP 406.

Explain the difference between 406 Not Acceptable and 415 Unsupported Media Type.

406 is about the *response*: the client wants a format the server can't provide (via the Accept header). 415 is about the *request*: the client sent a payload in a format the server doesn't understand (via the Content-Type header).

If a client requests `Accept: text/csv` and your API only supports JSON, what should you do?

Strictly speaking, return 406 Not Acceptable. Pragmatically, many APIs just return JSON anyway, but returning 406 is the most standards-compliant approach.

Which HTTP headers are involved in a 406 error?

Primarily the `Accept` header, but it can also apply to `Accept-Charset`, `Accept-Encoding`, and `Accept-Language`.

Common Interview Mistakes

  • Confusing 406 with 415.
  • Thinking 406 means the payload data was invalid (that is 400 or 422).
  • Assuming browsers frequently trigger this error during normal web surfing.