Unable to Set the Accept-Encoding Header on Frontend

Website resources are usually returned after being compressed using gzip, which greatly reduces their size. But what about regular API interfaces?

Sometimes the backend API returns oversized responses. The backend team found out that compressing the response with gzip can significantly improve the data packet size. This was the result of communication between backend teams.

After that, the next time we implemented the API, the backend informed me that the Accept-Encoding header could be set to gzip compression when making a frontend request. When I asked if this was a backend service configuration, they replied that configuring it on the backend was not easy.

Then, when debugging this interface, I tried to configure the request with headers:{"Accept-Encoding": "gzip"} (axios), and checked the effect by opening devtool - network. I saw that the value of the request header Accept-Encoding was gzip, deflate, br, and no matter how I switched the case, it had no effect. However, when I changed Accept-Encoding to a custom value such as "Suni", the request header setting would work.

After researching online, the response to an issue in the Axios library from 2016 indicated that this field is indeed forbidden. At first, I thought it might not be allowed to set in XHR, but perhaps it would be allowed in fetch. However, in the specifications for both XHR and Fetch, it is explained that certain headers are not allowed to be set.

The difference is that setting it in XHR will result in an error, while it's not in Fetch, but it still won't work.

So this matter still needs to be reported to the backend, to either adjust the service configuration or perform other actions.

Update (07.01)

I wanna try configuring gzip for the API in Next.js, but found that the data returned by Next.js is already compressed with gzip, even if I set headers: { 'Content-Encoding': 'br', suni: 'suni' } in return's option.

(You can open the devtools to check.)

The result returned is: 580B transfered over network, resource size: 66.5 KB


After some research, I find that, it turns out that the Content-Encoding returned does not necessarily need to be gzip. Returning br means that it has been compressed using Brotli, which is faster to decompress than gzip, while gzip results in a smaller compressed size, but the difference is not significant.

Will the file be compressed multiple times? For example, pre-compressed with gzip and then compressed again with br? Maybe, but it would not be a good experience.

Whether to return gzip or br depends on the deployment service's return strategy. Perhaps the service framework knows better which files to use br and which files to use gzip. On Vercel and Next.js’ documentation, I did not find a way to set the compression method from the server-side, but rather more on the request side by setting Accept-Encoding.

header (name, value) is forbidden request-header if these steps return true:

  1. If name is a byte-case-insensitive match for one of:

    • Accept-Charset
    • Accept-Encoding
    • [Access-Control-Request-Headers](https://fetch.spec.whatwg.org/#http-access-control-request-headers)
    • [Access-Control-Request-Method](https://fetch.spec.whatwg.org/#http-access-control-request-method)
    • Connection
    • Content-Length
    • Cookie
    • Cookie2
    • Date
    • DNT
    • Expect
    • Host
    • Keep-Alive
    • [Origin](https://fetch.spec.whatwg.org/#http-origin)
    • Referer
    • Set-Cookie
    • TE
    • Trailer
    • Transfer-Encoding
    • Upgrade
    • Via

    then return true.

  2. If name when byte-lowercased starts with proxy- or sec-, then return true.

  3. If name is a byte-case-insensitive match for one of:

    • X-HTTP-Method
    • X-HTTP-Method-Override
    • X-Method-Override


    1. Let parsedValues be the result of getting, decoding, and splitting value.
    2. For each method of parsedValues: if the isomorphic encoding of method is a forbidden method, then return true.
  4. Return false.