Developer Tools
Vary Header Builder
Build, parse, and test the HTTP Vary response header in your browser. Validate cache key behavior across requests with full server snippets.
Quick presets
Tap a preset to load a common Vary pattern.
Fields
Pick the request headers that change the response. Vary: * tells shared caches not to store the response at all.
Use this for fields not in the catalog. Each name must use ASCII letters, digits, and the characters ! # $ % & ' * + - . ^ _ ` | ~
Generated header
Vary: Accept-EncodingCaches will use the request Accept-Encoding value as part of the cache key, storing one copy per distinct value.
Server snippets
Drop into your server config or framework. Customize the path matcher to match your routing.
Raw header line
Vary: Accept-Encoding
Nginx
add_header Vary "Accept-Encoding" always;
Apache (.htaccess / VirtualHost)
<IfModule mod_headers.c> Header set Vary "Accept-Encoding" </IfModule>
Caddy
header Vary "Accept-Encoding"
Express.js
app.use((req, res, next) => {
res.setHeader("Vary", "Accept-Encoding");
next();
});Next.js Route Handler
export async function GET() {
return new Response(body, {
headers: { Vary: "Accept-Encoding" },
});
}Next.js (next.config.js headers)
async headers() {
return [
{
source: "/:path*",
headers: [{ key: "Vary", value: "Accept-Encoding" }],
},
];
}Cloudflare Worker
const response = await fetch(request);
const headers = new Headers(response.headers);
headers.set("Vary", "Accept-Encoding");
return new Response(response.body, { status: response.status, headers });Vercel (vercel.json)
{
"headers": [
{
"source": "/(.*)",
"headers": [
{
"key": "Vary",
"value": "Accept-Encoding"
}
]
}
]
}Netlify (_headers)
/* Vary: Accept-Encoding
FastAPI
from fastapi import Response
@app.get("/")
async def root(response: Response):
response.headers["Vary"] = "Accept-Encoding"
return {"ok": True}Go net/http
func handler(w http.ResponseWriter, r *http.Request) {
w.Header().Set("Vary", `Accept-Encoding`)
// ... write body
}Quick reference
Why Vary matters
Without Vary a cache stores one response per URL. If the response actually depends on a request header, every client gets the wrong copy until the cache expires.
Vary: *
Tells shared caches the response varies on details they cannot inspect. The response is never stored by a shared cache.
Cardinality
Each unique combination of listed header values creates a new cache entry. Avoid high-cardinality fields like User-Agent and Referer.
Cookie vs Authorization
Vary: Cookie or Vary: Authorization usually means the response is per-user. Pair with Cache-Control: private or split the value out of the header.
Always include Accept-Encoding
If your server can gzip, brotli, or zstd-encode responses you should send Vary: Accept-Encoding so gzipped responses are not served to clients that did not request them.
Sec-CH-UA over User-Agent
Client hints have far lower cardinality than the User-Agent string and let you vary cleanly on mobile, brand, or platform.
How to use
- Pick a tab at the top: Build header to assemble a value, Parse and explain to inspect an existing one, or Cache key tester to compare two requests against a Vary value.
- In Build mode, tap any preset or toggle individual fields. Each field shows a cardinality badge so you can avoid high-cardinality choices like User-Agent and Referer.
- Add custom field names in the Custom field names input as a comma separated list, then copy the generated header value or any of the server snippets at the bottom.
- In Parse mode, paste a Vary header value (the Vary: prefix is optional). The tool normalizes the order, deduplicates, flags illegal characters, and explains each field.
- In Cache key tester mode, enter the server Vary value and edit the two request header lists. The result panel shows whether both requests resolve to the same cache key or store two separate cached entries.
About this tool
Vary Header Builder is a browser workbench for the HTTP Vary response header defined by RFC 9110 Section 12.5.5. The Vary header lists the request headers a shared cache must include in its cache key, so two requests that produce different responses get stored under different keys instead of one client receiving another client's cached body. The tool covers three jobs that map to the three real tasks developers have. First, build. Pick from a curated catalog of fields (Accept-Encoding, Accept, Accept-Language, Origin, Cookie, Authorization, User-Agent, Sec-CH-UA, Sec-CH-UA-Mobile, Sec-CH-UA-Platform, DPR, Save-Data, Viewport-Width, Referer, X-Forwarded-Proto) plus your own custom field names; the tool emits a normalized Vary value with stable token ordering, plus ready-to-paste snippets for Nginx, Apache, Caddy, Express.js, Next.js Route Handlers, Next.js next.config.js, Cloudflare Workers, Vercel vercel.json, Netlify _headers, FastAPI, and Go net/http. Each field carries a cardinality badge so you can spot high-cardinality choices (User-Agent, Cookie, Authorization, Referer) before they multiply your CDN storage. Quick presets cover the most common shapes: compression only, compression plus language, content negotiation, modern client hints, CORS with dynamic Origin, and the Vary: * uncacheable case. Second, parse. Paste any Vary header value (with or without the Vary: prefix) and the tool tokenizes per the RFC 9110 grammar 1#field-name, checks each token against the field-name token grammar (ASCII letters, digits, and ! # $ % & ' * + - . ^ _ ` | ~), deduplicates case-insensitively, and explains each named field. The Vary: * wildcard is flagged separately as a directive that tells shared caches not to store the response. Third, test the cache key. Enter a server Vary value and two sets of client request headers, and the tool builds the conservative cache key for each request (lowercase field name, trimmed value, absent fields treated as empty), compares them, and reports whether the two requests would resolve to the same shared cache entry or store two separate copies. Useful for debugging why a CDN serves wrong content to one country but not another, why an A/B test bleeds across cohorts, why gzipped responses reach clients that did not send Accept-Encoding: gzip, why Vary: Cookie made your hit rate collapse to zero, and why Vary: Origin is required when Access-Control-Allow-Origin mirrors the request Origin. Everything runs in your browser. The header value, the request headers, and the computed cache keys never leave the tab.
Free to use. Works in your browser. No signup, no login.
Related tools
You may also like
Cache-Control Header Builder
Build and parse Cache-Control headers with directive flags, max-age presets, conflict checks, and ready-to-paste server snippets.
Open tool
DeveloperETag Generator
Build, parse, and test HTTP ETag headers with strong vs weak comparison and conditional GET prediction.
Open tool
DeveloperHTTP Headers Parser
Parse, classify, and decode HTTP headers, with a missing security headers audit.
Open tool
DeveloperAccept-Language Header Parser
Parse, build, and run RFC 4647 lookup matching against an Accept-Language header.
Open tool
DeveloperContent-Disposition Header Builder
Build RFC 6266 download headers with UTF-8 filenames; parse and explain existing values.
Open tool
DeveloperCORS Headers Generator
Build Access-Control headers with live validation and Apache, Nginx, Vercel, Netlify, Next.js, Worker, and Express snippets.
Open tool