In This Article

Back to blog

406 Not Acceptable: What This HTTP Status Code Means and How to Fix It

Errors

What the 406 Not Acceptable error means, what causes it, and how to fix it as a user, a developer, or a site owner, including when scraping.

Kazys Toleikis

Last updated - ‐ 9 min read

Key Takeaways

  • You can fix the 406 Not Acceptable error by updating your Accept header to match the content types the server actually supports.

  • Security modules like ModSecurity can also return a 406 status code when they block a request, so it doesn't always mean a format mismatch.

  • In scraping, a complete and consistent set of realistic headers fixes header-related 406 errors, while IP-level blocks need a separate fix.

A 406 Not Acceptable error happens when the server has the resource you need, but your client asks for a format the server cannot provide. Although this can point to a simple file format mismatch, on websites it more often occurs when a security module, such as a web application firewall, flags your request and rejects it.

What Is the 406 Not Acceptable Error?

The 406 Not Acceptable error means the server found your requested resource but couldn’t return it in the format your client demanded. RFC 9110 calls it a representation problem, not a missing resource: nothing matches the Accept headers, and the server won’t use a default.

Web browsers and HTTP clients use headers like Accept, Accept-Language, and Accept-Encoding to tell the server which content types, languages, and encodings they handle. They also assign quality values like q=0.9 to rank these preferences from best to worst.

Status code Meaning What goes wrong Who fixes it
415 Unsupported Media Type The client sends data the server cannot read The request payload format is wrong Developer
406 Not Acceptable The client asks for data the server cannot send The requested response format is unavailable Developer or server owner
400 Bad Request The server cannot process the request due to malformed syntax The request structure is invalid Developer
403 Forbidden The server refuses to authorize the request The client lacks permission to access the resource Developer or server owner
404 Not Found The server cannot find the requested URL The resource does not exist Server owner or user
429 Too Many Requests The client exceeds the rate limit The request volume is too high Developer

Negotiation succeeds when the client offers one or more formats and the server matches one of its supported content types.

GET /api/data HTTP/1.1
Host: api.example.com
Accept: application/json, text/html;q=0.9, */*;q=0.8

HTTP/1.1 200 OK
Content-Type: application/json

{"status": "success"}

Failure occurs when the client demands a specific format the server lacks, and the server doesn't send an alternative that works.

GET /api/data HTTP/1.1
Host: api.example.com
Accept: application/xml

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

{"error": "Not Acceptable", "available": ["application/json", "text/html"]}

What Causes a 406 Not Acceptable Error?

Content negotiation usually fails because the client sends a strict header without a wildcard fallback. You see this when REST APIs drop legacy content types like XML or old API versions, or when a client requests a language the server lacks.

Security Modules and Web Application Firewalls

Security modules like ModSecurity can answer a blocked request with a 406 status code instead of the usual 403, and some shared hosts set them up that way. CDNs work differently: Cloudflare doesn't generate 406 errors itself and shows pages like Error 1005 or Error 1015 .

Since these systems scan traffic for anomalies, they flag missing or malformed headers as malicious bots and reject the request with a 406 error instead of serving the file.

To tell the causes apart, change one thing at a time. A negotiation 406 follows the Accept headers or the URL's format extension, so it disappears when you send Accept: */*, drop Accept-Language, and remove the extension.

A security block survives those changes, often shows a block page, not a list of content types, and may change with your IP or User-Agent.

Ready to get started?
Register now

How to Fix a 406 Not Acceptable Error

For Users

Standard web browsers rarely trigger the 406 error during everyday browsing because they automatically send a comprehensive Accept header with a */* fallback.

If you see the 406 Not Acceptable error, temporarily disable browser extensions that modify network traffic. If that doesn't work, you can also switch to a different network connection to check if a security firewall is blocking your current IP address.

Clearing your cache rarely helps, since the error depends on the headers your browser sends. Clearing the site's cookies can help, though, because cookies travel in a request header and firewalls inspect them too.

For Developers

When building applications, inspect your raw network requests. Standard HTTP libraries send short default header sets, such as Accept: */* with a library User-Agent, which some firewalls treat as bot traffic.

You diagnose the problem by printing the raw headers and the server's reply. If your script sends a strict Accept header, add a wildcard fallback. If a request with Accept: */* still gets a 406, check the firewall instead.

cURL

# Diagnosis: -v shows the headers curl sends (Accept: */* by default) and the reply
curl -v https://api.example.com/data

# Fix: if your script sends a strict Accept header, add a wildcard fallback
curl -H "Accept: application/json, */*;q=0.8" https://api.example.com/data

Python

import requests

url = 'https://api.example.com/data'

# Diagnosis: print the headers requests sent and what the server answered
response = requests.get(url, timeout=10)
print(response.request.headers)
print(response.status_code, response.headers.get('Content-Type'))
print(response.text[:200])

# Fix: if your script sends a strict Accept header, add a wildcard fallback
headers = {'Accept': 'application/json, text/plain;q=0.9, */*;q=0.8'}
response = requests.get(url, headers=headers, timeout=10)
print(response.status_code, response.headers.get('Content-Type'))

JavaScript

// Diagnosis: the fetch() function sends Accept: */* by default, so log the reply
fetch('https://api.example.com/data')
  .then(res => console.log('Default:', res.status, res.headers.get('Content-Type')));

// Fix: if your code sends a strict Accept header, add a wildcard fallback
fetch('https://api.example.com/data', {
  headers: {
    'Accept': 'application/json, text/html;q=0.9, */*;q=0.8'
  }
}).then(res => console.log('With Accept:', res.status, res.headers.get('Content-Type')));

Go

package main

import (
    "fmt"
    "log"
    "net/http"
    "net/http/httputil"
)

func main() {
    client := &http.Client{}
    req, err := http.NewRequest("GET", "https://api.example.com/data", nil)
    if err != nil {
        log.Fatal(err)
    }

    // Diagnosis: Go sends no Accept header by default, so print what goes out
    dump, _ := httputil.DumpRequestOut(req, false)
    fmt.Println(string(dump))

    // Fix: set the Accept header before sending the request
    req.Header.Set("Accept", "application/json, */*;q=0.8")
    resp, err := client.Do(req)
    if err != nil {
        log.Fatal(err)
    }
    defer resp.Body.Close()
    fmt.Println(resp.Status)
}

For Server Owners

Web frameworks like Ruby on Rails return a 406 status code when the requested format, from the URL extension or Accept header, isn't one the controller action responds to, so check the formats your actions handle first. If you manage the infrastructure, review your Apache or Nginx configuration files.

On the web server, Apache's MultiViews and type maps return a 406 when no variant matches, unless ForceLanguagePriority Fallback picks a default language. Nginx doesn't negotiate on the Accept header, so a 406 there usually comes from ModSecurity or the app behind it.

Instead of blindly disabling security rules to find the issue, check your firewall audit logs to see exactly which rule flagged the legitimate traffic. You can then test your setup by sending a standard browser request from a remote machine to see if the security software still returns a 406 error.

Once you know the rule ID, exclude that one rule for the affected path, for example, with SecRuleRemoveById in ModSecurity, instead of switching the firewall off. Then repeat the request that failed to confirm the fix.

406 Errors in Web Scraping and Automation

Automated scrapers are among the most common culprits for this error code since HTTP libraries send minimal headers: the Python requests library sends five, including User-Agent: python-requests, while a browser also sends Accept-Language and Sec-Fetch headers.

To solve it, open your target website in a real browser, click the request in the developer tools' Network tab, and copy the primary headers into your script. Keep the whole set consistent, not just the Accept header, so every value matches the same browser.

Sometimes a website blocks your IP address entirely, so even realistic headers fail to load the page. Keep in mind that IP bans usually trigger timeouts or 403 errors rather than 406 status codes.

Headers and IP addresses are separate problems with separate fixes. If the block is tied to your IP address or its location, route your traffic through residential , mobile , or datacenter proxies .

Preventing 406 Errors

Pick one primary format as your default, and consider serving it when nothing in the Accept header matches, which RFC 9110 allows instead of a 406. Make sure you document all supported content types clearly so clients know what to request.

Always set the Vary header to prevent intermediate caches from serving the wrong format to the next visitor. If a client makes an incompatible request, return a small payload listing the available content types.

Your client should send realistic headers with a broad wildcard fallback. While you don't need perfect network signatures, you should still avoid sending empty headers. When your client receives a 406 error, read the server response to see the available content types and change your next request so it fits properly.

Treat 406 errors as critical technical defects and monitor them in Search Console and your server logs. Search engines do not apply a specific ranking penalty for a 406, but they cannot index a page they cannot read. If search engines receive this error, they drop the page from search results: Google doesn't index URLs that return a 4xx status code.

Conclusion

A 406 Not Acceptable error means the server can't send the resource in any format your Accept header allows. Adding a */*;q=0.8 fallback or asking for a format the server supports usually fixes it.

If a request with Accept: */* still gets a 406, a security module is the more likely cause, so check its audit logs for the rule that flagged the request. On your own server, a default format keeps 406 errors rare, the Vary header keeps caches from serving the wrong format, and a 406 body that lists the available content types tells clients what to ask for.

FAQ

What causes a 406 error?

The 406 Not Acceptable error appears when there's a format mismatch between the client and the server. Firewalls also throw the error response when they detect suspicious traffic patterns.

How do I fix a 406 Not Acceptable error?

You can fix the 406 Not Acceptable error by expanding the content types your Accept header allows, for example with a */*;q=0.8 fallback. You may also need to check audit logs to adjust firewall rules or correct the formats your application handles.

What is the difference between 406 and 415?

The 415 error happens when a client sends data in a format the server cannot read. The 406 error happens when the client requests data in a format the server cannot produce.

Is a 406 error my fault or the website's?

For scripts and API clients, the reason for the 406 Not Acceptable error usually lies with a strict Accept header or a minimal header set. In a browser, which accepts any format, it more often means the site's firewall flagged a valid request by mistake.

Does a 406 error mean the site is down?

No. The server remains fully operational and processes requests for other visitors normally. The error only means the server rejected your specific request.

Can a VPN or proxy cause a 406 Not Acceptable error?

Blocks aimed at VPN or proxy IP addresses typically trigger 403 Forbidden errors, unless the site's firewall answers blocks with a 406. A proxy itself usually only causes a 406 Not Acceptable error if it modifies or strips standard browser headers from your outgoing request.

Are 406 responses cached?

Only if the server allows it. A 406 isn't cacheable by default, so browsers, proxies, and CDNs store a 406 Not Acceptable error response only when it has explicit cache headers, such as Cache-Control: max-age. Then they can serve the error even after you fix the problem.

Create Account
Share on
Article by IPRoyal
Meet our writers
Data News in Your Inbox

No spam whatsoever, just pure data gathering news, trending topics and useful links. Unsubscribe anytime.

No spam. Unsubscribe anytime.

Related articles