Vary: Accept-Encoding and Content Negotiation
The Vary: Accept-Encoding HTTP response header is crucial in content negotiation, a mechanism that allows servers to serve different versions of a resource based on client capabilities (e.g., compression methods).
For the broader Vary: Accept-Encoding cluster, see Gzip and Vary: Accept-Encoding, cPanel Vary: Accept Header, How to Specify Vary: Accept-Encoding in Nginx, Vary: Accept-Encoding and Caching, and Vary: Accept-Encoding and Content Negotiation.
What is Content Negotiation?
Content negotiation is the process where a client and server work together to determine the most appropriate version of a resource based on specific criteria, such as:
- Language (
Accept-Language) - Media type (
Accept) - Encoding (
Accept-Encoding)
When it comes to compression, the Accept-Encoding header in the HTTP request plays a key role.
How Accept-Encoding Works in Content Negotiation
Client Request
The client (e.g., browser) sends an HTTP request with an Accept-Encoding header, specifying supported compression formats.
Example:
GET /example.html HTTP/1.1
Host: www.example.com
Accept-Encoding: gzip, deflate, br
Server Response
The server evaluates the Accept-Encoding header and serves the resource in a compatible encoding format.
- If compression is enabled: The server compresses the resource using gzip, br (Brotli), or another method. Includes
Content-Encodingin the response to indicate the applied encoding. - If compression is not supported: The server sends the resource uncompressed.
Example Response (with gzip):
HTTP/1.1 200 OK
Content-Encoding: gzip
Vary: Accept-Encoding
Role of the Vary: Accept-Encoding Header
The Vary header ensures that caching mechanisms (like CDNs, proxies, and browsers) store different versions of a resource for each supported encoding type.
Without Vary: Accept-Encoding, caches may store and serve a single version of the resource:
- This could result in compressed content being served to clients that do not support compression, causing errors.
Why Vary: Accept-Encoding is Important
- Prevents Cache Mismatches: Ensures that caches store and serve the correct version of a resource based on the client
Accept-Encodingheader. - Improves Compatibility: Allows clients that do not support compression to receive uncompressed resources, while others get compressed versions.
- Enhances SEO and Indexing: Search engines like Google recommend using
Vary: Accept-Encodingto ensure proper indexing of compressed and uncompressed content.
Example: Behavior Without Vary: Accept-Encoding
Scenario:
- A server sends compressed content (gzip) without the
Vary: Accept-Encodingheader. - A caching proxy stores this compressed version.
- A client that does not support gzip requests the resource.
Result:
- The proxy serves the cached compressed version.
- The client cannot process the resource, leading to errors or broken pages.
How to Implement Vary: Accept-Encoding
In Apache
Enable mod_headers and mod_deflate:
<IfModule mod_headers.c>
Header append Vary: Accept-Encoding
</IfModule>
<IfModule mod_deflate.c>
AddOutputFilterByType DEFLATE text/html text/plain text/css
</IfModule>
Restart Apache:
sudo systemctl restart apache2
In Nginx
Enable gzip and specify the Vary header:
gzip on;
gzip_vary on;
gzip_types text/plain text/css application/json application/javascript;
Reload Nginx:
sudo systemctl reload nginx
In PHP
Add the Vary header dynamically:
header("Vary: Accept-Encoding");
Best Practices for Using Vary: Accept-Encoding
- Enable Compression: Use gzip or Brotli for compressed resources. Tools like PageSpeed Insights or GTmetrix can confirm if compression is enabled.
- Avoid Over-Fragmentation: Overusing the
Varyheader (e.g., combining it withAccept-LanguageandUser-Agent) can lead to excessive cache fragmentation. - Verify the Implementation: Use tools like
curlor browser developer tools to check if theVaryheader is being sent: - Test Compression: Test if resources are served in compressed formats when supported.
curl -I https://example.com
Look for:
Vary: Accept-Encoding


