Era Host hosting
EraHost – Free Domain, Cheap Hosting!
Client Area
Support 24/7
Menu

Vary: Accept-Encoding and Content Negotiation

4 min read
07.06.2025

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).

Vary Accept-Encoding Content Negotiation
Vary — server signals "response varies by Accept-Encoding"; caches honor.

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-Encoding in 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

  1. Prevents Cache Mismatches: Ensures that caches store and serve the correct version of a resource based on the client Accept-Encoding header.
  2. Improves Compatibility: Allows clients that do not support compression to receive uncompressed resources, while others get compressed versions.
  3. Enhances SEO and Indexing: Search engines like Google recommend using Vary: Accept-Encoding to 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-Encoding header.
  • 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.
Linux VDS
High performance for your projects
  • Root access and flexible setup
  • Control panel
  • NVMe disks
  • DDR5
Linux VDS

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

  1. Enable Compression: Use gzip or Brotli for compressed resources. Tools like PageSpeed Insights or GTmetrix can confirm if compression is enabled.
  2. Avoid Over-Fragmentation: Overusing the Vary header (e.g., combining it with Accept-Language and User-Agent) can lead to excessive cache fragmentation.
  3. Verify the Implementation: Use tools like curl or browser developer tools to check if the Vary header is being sent:
  4. curl -I https://example.com

    Look for:

    Vary: Accept-Encoding
  5. Test Compression: Test if resources are served in compressed formats when supported.
Frequently asked questions
Same request URL, different response per client. Server picks based on Accept-Encoding (or Accept, Accept-Language). Without Vary, caches don't know to differentiate — return cached response regardless of request's encoding capability. With Vary, caches store per-variant. Vary is the signal; negotiation is the mechanism.
Same. HTTP/2 and HTTP/3 use the same Vary mechanism — they're transport improvements, not negotiation changes. Some newer features (server push, prioritization) interact with cached responses, but Vary semantics stay the same.
Proactive: server picks based on client headers (Accept-*). Most common today. Transparent: client makes follow-up request after server lists options. Rarely used in practice. Vary is for proactive. RFC 7231 has details for the curious.
Yes — set Vary at origin. Cloudflare may normalize Accept-Encoding for its cache, but downstream caches (browser, intermediate proxy) still need the header to behave correctly. Vary at origin is harmless and correct everywhere.
Related articles
Gzip and Vary: Accept-Encoding Header
How to Add a Vary: Accept Header Using PHP
How to Add Vary: Accept Header Using cPanel