The Vary Header and Caching for SEO: Avoiding Cloaking and Stale Pages
- March 17, 2022
- Technical SEO

The Vary HTTP header tells caches when a single URL can legitimately return different responses depending on the request. Get it right and your CDN serves the correct variant to humans and Googlebot alike. Get it wrong and you either poison your cache, hand crawlers a stale or mobile-only page, or trip Google's cloaking detection. This is one of the quietest sources of indexing problems because nothing looks broken in a browser.
What the Vary header actually does
When a cache stores a response, it keys that entry by URL. The Vary header adds request headers to that cache key, so the cache knows the response is conditional on them. The classic example:
Vary: Accept-EncodingThis says "the gzip'd version and the uncompressed version are different responses for the same URL, don't serve a compressed body to a client that can't decode it." Caches respect this at every layer: the browser cache, your CDN, and intermediate proxies.
The SEO relevance starts the moment your server changes content (not just encoding) based on a request header. If you serve different HTML by device, language, or cookie and you don't declare it in Vary, a shared cache will happily serve the first variant it stored to everyone who follows, including Googlebot.
Vary and Googlebot: the dynamic serving case
Google's official guidance for "dynamic serving", serving different HTML on the same URL to mobile vs. desktop user agents, is to send:
Vary: User-AgentThis is a signal to Google that the URL's content depends on the requesting user agent, prompting it to crawl with both its smartphone and (legacy) desktop agents. With mobile-first indexing now universal, the mobile Googlebot is the one that matters: it is what indexes your site. So the failure mode that hurts you is serving desktop-only or degraded HTML to a mobile user agent.
A critical caveat: Vary: User-Agent is a hint, not a cloaking exemption. If the content you serve to Googlebot differs materially from what a real user on the same device sees, that's cloaking regardless of the header. Vary manages caches; it does not grant permission to show search engines something different.
The cloaking trap built into caching
The most common way teams accidentally cloak has nothing to do with intent. It's a caching misconfiguration:
- Geo or A/B logic with no Vary. Your edge serves different HTML by country or experiment bucket but doesn't vary the cache key. The CDN caches whatever variant Googlebot's crawl produced and serves it to everyone, or caches a user's variant and serves it to Googlebot.
- Cookie-driven personalization cached publicly. A logged-in or personalized response gets stored in a shared cache because the response was marked
public. Now Googlebot indexes a personalized page, or users get someone else's session view. - Bot-specific rendering paths. An SSR layer that detects Googlebot's user agent and serves a prerendered snapshot. If that snapshot drifts from the user experience, you've built a cloaking machine, and it's invisible until a manual action or ranking collapse surfaces it.
The tell is almost always that the page looks fine when you load it, because your request headers happen to match the cached variant. The discrepancy only exists for a different header combination, which is exactly what a crawler sends.
Why Vary: User-Agent destroys cache efficiency
Here's the tension nobody warns you about. Varying on User-Agent is technically correct for dynamic serving, but the User-Agent string has near-infinite cardinality, every browser version, OS build, and bot produces a distinct value. A CDN that honors Vary: User-Agent literally will store a separate cache entry per unique string, shredding your hit rate to almost nothing.
In practice this is why the industry moved away from dynamic serving toward responsive design (one HTML payload, CSS handles layout) and toward edge logic that normalizes the user agent into a small number of buckets before it becomes part of the cache key. If you must serve device-specific HTML behind a CDN, your options are:
- Normalize
User-Agentat the edge intomobile/desktop/botand vary the cache key on that derived value, not the raw header. - Split content onto separate URLs (e.g., an
m.subdomain) with proper bidirectional annotations, though this is legacy and discouraged. - Go responsive and stop varying content by user agent entirely. This is the recommendation for almost every site.
Vary and Cache-Control: read them together
Neither header is safe in isolation. Vary defines the cache key; Cache-Control defines whether and how long anything is stored. The combinations that bite SEO:
- Personalized HTML must not be publicly cacheable. Use
Cache-Control: private, no-store(orprivate) for any response whose body depends on a logged-in cookie.privatepermits the browser cache but forbids shared CDN/proxy caches from storing it. - If you vary on a cookie, you almost never want public caching.
Vary: Cookieon a publicly cacheable response is a footgun, cookie cardinality is unbounded and you'll leak variants. Strip cookies at the edge for cacheable pages instead. - Stale variants outlive their welcome. A long
max-agecombined with content that changes by header means an old variant can be served to a crawler for hours after the page changed. If a page is meant to be fresh for crawlers, keep its TTL short or revalidate.
How to diagnose it
You can't trust a normal browser load, it sends your headers, not a crawler's. Test the way a cache and a crawler actually behave:
- Fetch with Googlebot's mobile user agent and compare the rendered HTML to a real mobile browser load. Use the URL Inspection tool's "View crawled page" in Search Console as ground truth for what Google actually received.
- Curl the URL with different
User-AgentandAccept-Languagevalues and diff the bodies. Any meaningful difference that isn't declared inVaryis a latent cloaking/caching bug. - Inspect response headers at the edge. Look for the CDN's cache-status header (e.g.,
x-cache: HIT) alongsideVaryandCache-Control. AHITon a personalized page is a red flag. - Check whether your CDN honors
Varyat all. Some CDNs ignore mostVaryheaders by default (respecting onlyAccept-Encoding) and require explicit configuration. If yours ignoresVary: User-Agent, your dynamic serving is silently broken at the edge.
Common mistakes
- Assuming
Vary: User-Agentmakes dynamic serving "safe." It manages caches; it does not authorize content differences that constitute cloaking. - Sending
Vary: *. This makes every response uncacheable by design. Occasionally intentional, usually an accident that crushes performance. - Letting a CDN cache cookie- or geo-personalized HTML as
public. The single most frequent cause of "Googlebot indexed the wrong page" reports. - Forgetting
Vary: Accept-Encoding. Rare now, but omitting it can deliver gzip'd bytes to a client expecting plain text, a hard failure, not a soft one. - Trusting your own browser as the test. Your headers match the cached variant; the bug lives in the header combinations you never send.
The defensible setup
For the overwhelming majority of sites: go responsive, serve one HTML payload per URL, mark public pages public with a sensible TTL, mark anything personalized private and strip cookies before caching. Reserve Vary for Accept-Encoding and let device differences live in CSS. If business requirements genuinely force header-dependent HTML, normalize that header into a tiny set of buckets at the edge and vary the cache key on the derived value, never the raw, high-cardinality string. Do that, and caching speeds your site up without ever showing a crawler something a user wouldn't see.
Want this handled properly on your site?
It is exactly the kind of work an advanced technical SEO audit covers. See how an advanced SEO audit works →
Claude Vincent is a technical SEO consultant focused on crawlability, rendering, and AI-search visibility. He writes the field guides and case studies at SEO ProCheck, with a bias toward the durable, unglamorous work that decides whether search engines and AI answer engines can actually read and cite a site.
About SEO ProCheck
Technical SEO consulting and GEO strategy with 20 years of enterprise experience. Case studies, resources, and tools for search and AI visibility.
Work With Me
Technical SEO audits, GEO strategy, site migrations, and international SEO. Hourly consulting for teams who need hands-on support, not just reports.







