HyperText Transfer Protocol D. Denicola
Internet-Draft J. Roman
Intended status: Standards Track N. Jaju, Ed.
Expires: 4 February 2027 Google LLC
3 August 2026
The No-Vary-Search HTTP Caching Extension
draft-ietf-httpbis-no-vary-search-07
Abstract
This specification defines an extension to HTTP Caching, changing how
the URI query component impacts caching. It introduces the "No-Vary-
Search" response header field, which allows origin servers to signal
to caches that certain parts of the query component do not
semantically affect the served response and can be ignored for cache
matching purposes.
About This Document
This note is to be removed before publishing as an RFC.
The latest revision of this draft can be found at https://httpwg.org/
http-extensions/draft-ietf-httpbis-no-vary-search.html. Status
information for this document may be found at
https://datatracker.ietf.org/doc/draft-ietf-httpbis-no-vary-search/.
Discussion of this document takes place on the HTTP Working Group
mailing list (mailto:ietf-http-wg@w3.org), which is archived at
https://lists.w3.org/Archives/Public/ietf-http-wg/. Working Group
information can be found at https://httpwg.org/.
Source for this draft and an issue tracker can be found at
https://github.com/httpwg/http-extensions/labels/no-vary-search.
Status of This Memo
This Internet-Draft is submitted in full conformance with the
provisions of BCP 78 and BCP 79.
Internet-Drafts are working documents of the Internet Engineering
Task Force (IETF). Note that other groups may also distribute
working documents as Internet-Drafts. The list of current Internet-
Drafts is at https://datatracker.ietf.org/drafts/current/.
Denicola, et al. Expires 4 February 2027 [Page 1]
Internet-Draft No-Vary-Search August 2026
Internet-Drafts are draft documents valid for a maximum of six months
and may be updated, replaced, or obsoleted by other documents at any
time. It is inappropriate to use Internet-Drafts as reference
material or to cite them other than as "work in progress."
This Internet-Draft will expire on 4 February 2027.
Copyright Notice
Copyright (c) 2026 IETF Trust and the persons identified as the
document authors. All rights reserved.
This document is subject to BCP 78 and the IETF Trust's Legal
Provisions Relating to IETF Documents (https://trustee.ietf.org/
license-info) in effect on the date of publication of this document.
Please review these documents carefully, as they describe your rights
and restrictions with respect to this document. Code Components
extracted from this document must include Revised BSD License text as
described in Section 4.e of the Trust Legal Provisions and are
provided without warranty as described in the Revised BSD License.
Table of Contents
1. Introduction . . . . . . . . . . . . . . . . . . . . . . . . 3
2. Conventions and Definitions . . . . . . . . . . . . . . . . . 4
3. HTTP header field definition . . . . . . . . . . . . . . . . 5
4. Data model . . . . . . . . . . . . . . . . . . . . . . . . . 5
5. Parsing . . . . . . . . . . . . . . . . . . . . . . . . . . . 6
5.1. Parse a URL variation config . . . . . . . . . . . . . . 6
5.2. Obtain a URL variation config . . . . . . . . . . . . . . 7
5.2.1. Examples . . . . . . . . . . . . . . . . . . . . . . 7
5.3. Parse a key . . . . . . . . . . . . . . . . . . . . . . . 10
5.3.1. Examples . . . . . . . . . . . . . . . . . . . . . . 10
6. Comparing . . . . . . . . . . . . . . . . . . . . . . . . . . 11
6.1. Examples . . . . . . . . . . . . . . . . . . . . . . . . 13
7. Caching . . . . . . . . . . . . . . . . . . . . . . . . . . . 14
8. Security Considerations . . . . . . . . . . . . . . . . . . . 16
9. Privacy Considerations . . . . . . . . . . . . . . . . . . . 17
10. IANA Considerations . . . . . . . . . . . . . . . . . . . . . 17
10.1. HTTP Field Names . . . . . . . . . . . . . . . . . . . . 17
11. References . . . . . . . . . . . . . . . . . . . . . . . . . 18
11.1. Normative References . . . . . . . . . . . . . . . . . . 18
11.2. Informative References . . . . . . . . . . . . . . . . . 19
Acknowledgments . . . . . . . . . . . . . . . . . . . . . . . . . 19
Index . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 19
Authors' Addresses . . . . . . . . . . . . . . . . . . . . . . . 20
Denicola, et al. Expires 4 February 2027 [Page 2]
Internet-Draft No-Vary-Search August 2026
1. Introduction
HTTP caching [HTTP-CACHING] is based on reusing resources which match
across a number of cache keys, with the most important one being the
presented target URI (Section 7.1 of [HTTP]). However, sometimes
multiple URIs can represent the same resource. This leads to caches
not always being as helpful as they could be: if the cache contains a
response under one URI, but the response is then requested under
another, the cached version will be ignored.
The "No-Vary-Search" response header field defines a caching
extension, as described in Section 4 of [HTTP-CACHING], that tackles
a specific subset of this general problem, for when different URIs
that differ only in their query component identify the same resource.
It allows resources to declare that some or all parts of the query
component do not semantically affect the served response, and thus
can be ignored for cache matching purposes. This is achieved by
interpreting the query component as a sequence of parameters encoded
using the application/x-www-form-urlencoded format [WHATWG-URL]. For
example, if the order of the parameters within the query component
does not affect which resource is identified, this is indicated using
No-Vary-Search: key-order
If specific query parameters (e.g., ones indicating something for
analytics) do not semantically affect the served resource, this is
indicated using
No-Vary-Search: params=("utm_source" "utm_medium" "utm_campaign")
And if the resource instead wants to take an allowlist-based
approach, where only certain known query parameters semantically
affect the served response, they can use
No-Vary-Search: except=("productId")
Note that "cache busting", the practice of changing a part of the
query component to create a distinct cache key and force retrieval of
a newer response, can be made ineffective by the "No-Vary-Search"
response header field.
Section 3 defines the new "No-Vary-Search" response header field,
using the [STRUCTURED-FIELDS] framework. Section 4 and Section 5
illustrate the data model for how the field value can be represented
in specifications, and the process for parsing the raw output from
the structured field parser into that data model. Section 6 gives
the key algorithm for comparing if two URLs are equivalent under the
influence of the header field; notably, it leans on the decomposition
Denicola, et al. Expires 4 February 2027 [Page 3]
Internet-Draft No-Vary-Search August 2026
of the query component into keys and values given by the application/
x-www-form-urlencoded (https://url.spec.whatwg.org/#concept-
urlencoded) format specified in [WHATWG-URL]. (As such, this header
field is not useful for URLs whose query component does not follow
that format.) Finally, Section 7 explains how to extend Section 4 of
[HTTP-CACHING] to take this new equivalence into account.
From a deployment perspective, this extension is implemented by HTTP
caches, including browser caches, content delivery networks, and
forward proxies. Origin servers send the "No-Vary-Search" response
header field to provide instructions to these caches. Caches that
implement this extension use these instructions to determine when a
previously stored response can be safely reused for a new request,
even if the query components of the target URIs differ.
2. Conventions and Definitions
The key words "MUST", "MUST NOT", "REQUIRED", "SHALL", "SHALL NOT",
"SHOULD", "SHOULD NOT", "RECOMMENDED", "NOT RECOMMENDED", "MAY", and
"OPTIONAL" in this document are to be interpreted as described in
BCP 14 [RFC2119] [RFC8174] when, and only when, they appear in all
capitals, as shown here.
In this document, the terms "URI" and "URL" are used interchangeably,
depending on context. "URI" is used in the context of [URI], [HTTP],
and [HTTP-CACHING], whereas "URL" is used in the context of the
algorithms specified in [WHATWG-URL].
The term "query parameters" in this document refers to the keys and
values resulting from parsing a URL's query component using the
application/x-www-form-urlencoded
(https://url.spec.whatwg.org/#concept-urlencoded) format
[WHATWG-URL].
This document also adopts some conventions and notation typical in
WHATWG and W3C usage, especially as it relates to algorithms. See
[WHATWG-INFRA], and in particular:
* its definition of lists, including the list literal notation « 1,
2, 3 ».
* its definition of strings, including their representation as code
units.
(Other concepts used are called out using inline references.)
Denicola, et al. Expires 4 February 2027 [Page 4]
Internet-Draft No-Vary-Search August 2026
3. HTTP header field definition
The "No-Vary-Search" response header field is a structured field
[STRUCTURED-FIELDS] whose value MUST be a dictionary (Section 3.2 of
[STRUCTURED-FIELDS]).
It has the following constraints:
* If present, the key-order entry's value MUST be a boolean
(Section 3.3.6 of [STRUCTURED-FIELDS]).
* If present, the params entry's value MUST be an inner list of
strings (Section 3.1.1 of [STRUCTURED-FIELDS]).
* If present, the except entry's value MUST be an inner list of
strings (Section 3.1.1 of [STRUCTURED-FIELDS]).
* The except entry MUST NOT be present if the params entry is also
present.
The dictionary MAY contain entries whose keys are not one of key-
order, params, and except, but their meaning is not defined by this
specification. Implementations of this specification will ignore
such entries (but future documents might assign meaning to such
entries).
| A parsing algorithm is defined in Section 5.2.
4. Data model
A _URL variation config_ consists of the following:
no-vary params
either the special value *wildcard* or a list of strings
vary params
either the special value *wildcard* or a list of strings
vary on key order
a boolean
The _default URL variation config_ is a URL variation config whose
no-vary params is an empty list, vary params is *wildcard*, and vary
on key order is true.
The obtain a URL variation config algorithm (Section 5.2) ensures
that all URL variation configs obey the following constraints:
Denicola, et al. Expires 4 February 2027 [Page 5]
Internet-Draft No-Vary-Search August 2026
* vary params is a list if and only if the no-vary params is
*wildcard*; and
* no-vary params is a list if and only if the vary params is
*wildcard*.
5. Parsing
5.1. Parse a URL variation config
To _parse a URL variation config_ given _value_:
1. If _value_ is null, then return the default URL variation config.
2. Let _result_ be a new URL variation config.
3. Set _result_'s vary on key order to true.
4. If _value_["key-order"] exists:
1. If _value_["key-order"] is not a boolean, then return the
default URL variation config.
2. Set _result_'s vary on key order to the boolean negation of
_value_["key-order"].
5. If both _value_["params"] and _value_["except"] exist or neither
exists, then return the default URL variation config.
6. If _value_["params"] exists:
1. If _value_["params"] is not an array, then return the default
URL variation config.
2. If any item in _value_["params"] is not a string, then return
the default URL variation config.
3. Set _result_'s no-vary params to the result of applying parse
a key (Section 5.3) to each item in _value_["params"].
4. If any item in _result_'s no-vary params is an error, then
return the default URL variation config.
5. Set _result_'s vary params to *wildcard*.
7. Otherwise, if _value_["except"] exists:
Denicola, et al. Expires 4 February 2027 [Page 6]
Internet-Draft No-Vary-Search August 2026
1. If _value_["except"] is not an array, then return the default
URL variation config.
2. If any item in _value_["except"] is not a string, then return
the default URL variation config.
3. Set _result_'s vary params to the result of applying parse a
key (Section 5.3) to each item in _value_["except"].
4. If any item in _result_'s vary params is an error, then
return the default URL variation config.
5. Set _result_'s no-vary params to *wildcard*.
8. Return _result_.
| In general, this algorithm is strict and tends to return the
| default URL variation config whenever it sees something it
| doesn't recognize. This is because the default URL variation
| config behavior will just cause fewer cache hits, which is an
| acceptable fallback behavior.
|
| However, unrecognized keys at the top level are ignored, to
| make it easier to extend this specification in the future. To
| avoid misbehavior with existing client software, such
| extensions will likely expand, rather than reduce, the set of
| requests that a cached response can match.
| The input to this algorithm is generally obtained by parsing a
| structured field (Section 4.2 of [STRUCTURED-FIELDS]) using
| field_type "dictionary".
5.2. Obtain a URL variation config
To _obtain a URL variation config_ given an HTTP response
(Section 3.4 of [HTTP]) _response_:
1. Let _fieldValue_ be the result of parsing the "No-Vary-Search"
response header field from _response_ as a Dictionary
(Section 4.2 of [STRUCTURED-FIELDS]).
2. Return the result of parsing a URL variation config (Section 5.1)
given _fieldValue_.
5.2.1. Examples
The following illustrates how various inputs are parsed, in terms of
their impact on the resulting no-vary params and vary params:
Denicola, et al. Expires 4 February 2027 [Page 7]
Internet-Draft No-Vary-Search August 2026
+=================+==============================+
| Input | Result |
+=================+==============================+
| No-Vary-Search: | no-vary params: (empty list) |
| key-order | vary params: *wildcard* |
| | vary on key order: false |
+-----------------+------------------------------+
| No-Vary-Search: | no-vary params: « "a" » |
| params=("a") | vary params: *wildcard* |
+-----------------+------------------------------+
| No-Vary-Search: | no-vary params: *wildcard* |
| except=("x") | vary params: « "x" » |
+-----------------+------------------------------+
| No-Vary-Search: | no-vary params: (empty list) |
| params=() | vary params: *wildcard* |
+-----------------+------------------------------+
| No-Vary-Search: | no-vary params: *wildcard* |
| except=() | vary params: (empty list) |
+-----------------+------------------------------+
Table 1
The following inputs are all invalid and will cause the default URL
variation config to be returned:
Denicola, et al. Expires 4 February 2027 [Page 8]
Internet-Draft No-Vary-Search August 2026
+============================+==============================+
| Input | Explanation |
+============================+==============================+
| No-Vary-Search: key- | key-order expects a boolean, |
| order="not a boolean" | not a string |
+----------------------------+------------------------------+
| No-Vary-Search: | params expects an inner |
| params="not an inner list" | list, not a string |
+----------------------------+------------------------------+
| No-Vary-Search: | params items must be strings |
| params=(not-a-string) | (tokens are invalid) |
+----------------------------+------------------------------+
| No-Vary-Search: params=?0 | params expects an inner |
| | list, not a boolean |
+----------------------------+------------------------------+
| No-Vary-Search: params=?1 | params expects an inner |
| | list, not a boolean |
+----------------------------+------------------------------+
| No-Vary-Search: params=?1, | params and except cannot |
| except=("x") | both be present |
+----------------------------+------------------------------+
| No-Vary-Search: | params and except cannot |
| params=("a"), except=("x") | both be present |
+----------------------------+------------------------------+
| No-Vary-Search: params=(), | params and except cannot |
| except=() | both be present |
+----------------------------+------------------------------+
| No-Vary-Search: | except expects an inner |
| except="not an inner list" | list, not a string |
+----------------------------+------------------------------+
| No-Vary-Search: | except items must be strings |
| except=(not-a-string) | (tokens are invalid) |
+----------------------------+------------------------------+
| No-Vary-Search: except=?1 | except expects an inner |
| | list, not a boolean |
+----------------------------+------------------------------+
Table 2
The following inputs are valid, but somewhat unconventional. They
are shown alongside their more conventional form.
Denicola, et al. Expires 4 February 2027 [Page 9]
Internet-Draft No-Vary-Search August 2026
+==============================+===========================+
| Input | Conventional form |
+==============================+===========================+
| No-Vary-Search: key-order=?1 | No-Vary-Search: key-order |
+------------------------------+---------------------------+
| No-Vary-Search: | No-Vary-Search: key- |
| except=("x"), key-order | order, except=("x") |
+------------------------------+---------------------------+
| No-Vary-Search: params=() | (omit the header field) |
+------------------------------+---------------------------+
| No-Vary-Search: key-order=?0 | (omit the header field) |
+------------------------------+---------------------------+
Table 3
5.3. Parse a key
To _parse a key_ given an ASCII string _keyString_:
1. Let _keyBytes_ be the isomorphic encoding
(https://infra.spec.whatwg.org/#isomorphic-encode) [WHATWG-INFRA]
of _keyString_.
2. Replace any 0x2B (+) in _keyBytes_ with 0x20 (SP).
3. Let _keyBytesDecoded_ be the percent-decoding
(https://url.spec.whatwg.org/#percent-decode) [WHATWG-URL] of
_keyBytes_.
4. Let _keyStringDecoded_ be the UTF-8 decoding without BOM
(https://encoding.spec.whatwg.org/#utf-8-decode-without-bom)
[WHATWG-ENCODING] of _keyBytesDecoded_.
5. Return _keyStringDecoded_.
5.3.1. Examples
The parse a key algorithm allows encoding non-ASCII key strings in
the ASCII structured header field format, similar to how the
application/x-www-form-urlencoded
(https://url.spec.whatwg.org/#concept-urlencoded) format [WHATWG-URL]
allows encoding an entire entry list of keys and values in a URI
(which is restricted to ASCII characters). For example:
No-Vary-Search: params=("%C3%A9+%E6%B0%97")
Denicola, et al. Expires 4 February 2027 [Page 10]
Internet-Draft No-Vary-Search August 2026
Notice that while the input string "%C3%A9+%E6%B0%97" consists
entirely of ASCII characters (as required at the HTTP layer), the
percent-decoding step used by the User Agent produces a non-ASCII
result. This will result in a URL variation config whose vary params
are « "é 気" ». Note that the "+" character in the encoded string is
mapped to a space (SP). As explained in a later example, the
canonicalization process during equivalence testing means this will
treat as equivalent URIs such as:
* https://example.com/?é 気=1
* https://example.com/?é+気=2
* https://example.com/?%C3%A9%20気=3
* https://example.com/?%C3%A9+%E6%B0%97=4
and so on, since they all are parsed
(https://url.spec.whatwg.org/#concept-urlencoded-parser) [WHATWG-URL]
to having the same key "é 気".
6. Comparing
Two URLs (https://url.spec.whatwg.org/#concept-url) [WHATWG-URL]
_urlA_ and _urlB_ are _equivalent modulo variation config_ given a
URL variation config _variationConfig_ if the following algorithm
returns true:
1. If the scheme, username, password, host, port, or path of _urlA_
and _urlB_ differ, then return false.
2. If _variationConfig_ is equivalent to the default URL variation
config, then:
1. If _urlA_'s query equals _urlB_'s query, then return true.
2. Return false.
In this case, even URL pairs that might appear the same after
running the application/x-www-form-urlencoded parser
(https://url.spec.whatwg.org/#concept-urlencoded-parser)
[WHATWG-URL] on their queries, such as https://example.com/a and
https://example.com/a?, or https://example.com/foo?a=b&&&c and
https://example.com/foo?a=b&c=, will be treated as inequivalent.
3. Let _searchParamsA_ and _searchParamsB_ be empty lists.
Denicola, et al. Expires 4 February 2027 [Page 11]
Internet-Draft No-Vary-Search August 2026
4. If _urlA_'s query is not null, then set _searchParamsA_ to the
result of running the application/x-www-form-urlencoded parser
(https://url.spec.whatwg.org/#concept-urlencoded-parser)
[WHATWG-URL] given the isomorphic encoding
(https://infra.spec.whatwg.org/#isomorphic-encode)
[WHATWG-INFRA] of _urlA_'s query.
5. If _urlB_'s query is not null, then set _searchParamsB_ to the
result of running the application/x-www-form-urlencoded parser
(https://url.spec.whatwg.org/#concept-urlencoded-parser)
[WHATWG-URL] given the isomorphic encoding
(https://infra.spec.whatwg.org/#isomorphic-encode)
[WHATWG-INFRA] of _urlB_'s query.
6. If _variationConfig_'s no-vary params is a list, then:
1. Set _searchParamsA_ to a list containing those items _pair_
in _searchParamsA_ where _variationConfig_'s no-vary params
does not contain _pair_[0].
2. Set _searchParamsB_ to a list containing those items _pair_
in _searchParamsB_ where _variationConfig_'s no-vary params
does not contain _pair_[0].
7. Otherwise, if _variationConfig_'s vary params is a list, then:
1. Set _searchParamsA_ to a list containing those items _pair_
in _searchParamsA_ where _variationConfig_'s vary params
contains _pair_[0].
2. Set _searchParamsB_ to a list containing those items _pair_
in _searchParamsB_ where _variationConfig_'s vary params
contains _pair_[0].
8. If _variationConfig_'s vary on key order is false, then:
1. Let _keyLessThan_ be an algorithm taking as inputs two pairs
(_keyA_, _valueA_) and (_keyB_, _valueB_), which returns
whether _keyA_ is code unit less than
(https://infra.spec.whatwg.org/#code-unit-less-than)
[WHATWG-INFRA] _keyB_.
2. Set _searchParamsA_ to the result of sorting
(https://infra.spec.whatwg.org/#list-sort-in-ascending-
order) [WHATWG-INFRA] _searchParamsA_ in ascending order
with _keyLessThan_.
Denicola, et al. Expires 4 February 2027 [Page 12]
Internet-Draft No-Vary-Search August 2026
3. Set _searchParamsB_ to the result of sorting
(https://infra.spec.whatwg.org/#list-sort-in-ascending-
order) [WHATWG-INFRA] _searchParamsB_ in ascending order
with _keyLessThan_.
9. If _searchParamsA_'s size is not equal to _searchParamsB_'s
size, then return false.
10. Let _i_ be 0.
11. While _i_ < _searchParamsA_'s size:
1. If _searchParamsA_[_i_][0] does not equal
_searchParamsB_[_i_][0], then return false.
2. If _searchParamsA_[_i_][1] does not equal
_searchParamsB_[_i_][1], then return false.
3. Set _i_ to _i_ + 1.
12. Return true.
6.1. Examples
Due to how the application/x-www-form-urlencoded parser canonicalizes
query strings, there are some cases where query strings which do not
appear obviously equivalent, will end up being treated as equivalent
after parsing.
So, for example, given any non-default value for the "No-Vary-Search"
response header field, such as No-Vary-Search: key-order, we will
have the following equivalences:
Denicola, et al. Expires 4 February 2027 [Page 13]
Internet-Draft No-Vary-Search August 2026
+=============+==============+============================+
| First Query | Second Query | Explanation |
+=============+==============+============================+
| null | ? | A null query is parsed the |
| | | same as an empty string |
+-------------+--------------+----------------------------+
| ?a=x | ?%61=%78 | Parsing performs percent- |
| | | decoding |
+-------------+--------------+----------------------------+
| ?a=é | ?a=%C3%A9 | Parsing performs percent- |
| | | decoding |
+-------------+--------------+----------------------------+
| ?a=%f6 | ?a=%ef%bf%bd | Both values are parsed as |
| | | U+FFFD (�) |
+-------------+--------------+----------------------------+
| ?a=x&&&& | ?a=x | Parsing splits on & and |
| | | discards empty strings |
+-------------+--------------+----------------------------+
| ?a= | ?a | Both parse as having an |
| | | empty string value for a |
+-------------+--------------+----------------------------+
| ?a=%20 | ?a= & | %20 is parsed as U+0020 |
| | | SPACE |
+-------------+--------------+----------------------------+
| ?a=+ | ?a= & | + is parsed as U+0020 |
| | | SPACE |
+-------------+--------------+----------------------------+
Table 4
Note that no Unicode normalization is performed during this
comparison. For example, a query string of ?a=%C3%A9 (using the NFC
encoding of é) and ?a=e%CC%81 (using the NFD encoding of é) will not
be treated as equivalent.
7. Caching
To reuse a stored response, Section 4 of [HTTP-CACHING] requires that
the presented target URI and that of the stored response match. If a
cache implements the No-Vary-Search extension, this matching
requirement is also satisfied if the URIs are equivalent modulo URL
variation config (Section 6) given the stored response's No-Vary-
Search header.
Cache implementations MAY fail to reuse a stored response whose
target URI matches _only_ modulo URL variation config, if the cache
has more recently stored a response which:
Denicola, et al. Expires 4 February 2027 [Page 14]
Internet-Draft No-Vary-Search August 2026
* has a target URI which is equal to the presented target URI,
excluding the query, and
* has a non-empty value for the "No-Vary-Search" response header
field, and
* has a "No-Vary-Search" response header field value different from
the stored response being considered for reuse.
| Caches aren't required to reuse stored responses, generally.
| However, the above expressly empowers caches to, if it is
| advantageous for performance or other reasons, search a smaller
| number of stored responses.
|
| That is, because caches might store more than one response for
| a given pathname, they need a way to efficiently look up the
| "No-Vary-Search" response header field value without accessing
| all cached responses. Such a cache might take steps like the
| following to identify a stored response in a performant way,
| before checking the other conditions in Section 4 of
| [HTTP-CACHING]:
|
| 1. Let exactMatch be cache[presentedTargetURI]. If it is a
| stored response that can be reused, return it.
|
| 2. Let targetPath be presentedTargetURI, with query
| parameters removed.
|
| 3. Let lastNVS be mostRecentNVS[targetPath]. If it does
| not exist, return null.
|
| 4. Let simplifiedURL be the result of simplifying
| presentedTargetURI according to lastNVS (by removing
| query parameters which are not significant, and sorting
| (https://infra.spec.whatwg.org/#list-sort-in-ascending-
| order) [WHATWG-INFRA] parameters in ascending order by
| key, if key order is to be ignored).
|
| 5. Let nvsMatch be cache[simplifiedURL]. If it does not
| exist, return null. (It is assumed that this was
| written when storing in the cache, in addition to the
| exact URL.)
|
| 6. Let variationConfig be obtained (Section 5.2) from
| nvsMatch.
|
Denicola, et al. Expires 4 February 2027 [Page 15]
Internet-Draft No-Vary-Search August 2026
| 7. If nvsMatch's target URI and presentedTargetURI are not
| equivalent modulo URL variation config (Section 6) given
| variationConfig, then return null.
|
| 8. If nvsMatch is a stored response that can be reused,
| return it. Otherwise, return null.
To aid cache implementation efficiency, servers SHOULD NOT send
different non-empty values for the "No-Vary-Search" response header
field in response to requests for a given pathname over time, unless
there is a need to update how they handle the query component. Doing
so would cause cache implementations that use a strategy like the
above to miss some stored responses that could otherwise have been
reused.
8. Security Considerations
The main risk to be aware of is a cache returning a response that was
originally fetched from a URL different from the one requested. In a
web browser, this could cause the user to see a response fetched from
a URL different from the one displayed when they hovered a link, or
the URL displayed in the URL bar.
For shared caches, such as CDNs or forward proxies, returning a
response for a different URL carries the risk of cross-user state
leakage. If a server incorrectly declares that a query parameter
does not affect the response, but that parameter actually dictates
user-specific or sensitive content, the shared cache might serve one
user's personalized response to another user. However, because the
origin strictly controls the "No-Vary-Search" response header field,
it is the origin's responsibility to ensure that ignored parameters
are safe to disregard for all users.
The "No-Vary-Search" response header field alters the algorithm that
caches use for URI identifier comparison. As discussed in [RFC6943],
altering identifier comparison logic can lead to security issues,
primarily through "false positives" where two identifiers are
incorrectly deemed equivalent.
Incorrect configuration of this field can exacerbate cache poisoning
or data leakage risks by causing such false positives. Parameters
MUST NOT be ignored if doing so would bypass server processing
required for safe response reuse. This includes parameters used for
authorization, user identification, signature verification, user
consent, routing, auditing, revocation, or any other security-
sensitive operations.
Denicola, et al. Expires 4 February 2027 [Page 16]
Internet-Draft No-Vary-Search August 2026
However, since the impact is limited to query parameters, this does
not cross the relevant security boundary, which is the origin
([ORIGIN]). (See also the host
(https://url.spec.whatwg.org/#concept-url-host) from the perspective
of web browser security UI (https://url.spec.whatwg.org/#url-
rendering-simplification). [WHATWG-URL]) Indeed, origins already
have complete control over how they present URLs and response bodies,
including on the client side via technology such as
history.replaceState() (https://html.spec.whatwg.org/multipage/nav-
history-apis.html#dom-history-replacestate) or service workers.
9. Privacy Considerations
This proposal is adjacent to the highly-privacy-relevant space of
navigational tracking (https://privacycg.github.io/nav-tracking-
mitigations/#terminology), which often uses query parameters to pass
along user identifiers. However, we believe this proposal itself
does not have privacy impacts. It does not interfere with existing
navigational tracking mitigations (https://privacycg.github.io/nav-
tracking-mitigations/#deployed-mitigations), or any known future ones
being contemplated. Indeed, if a page were to encode user
identifiers in its URI, the only ability this proposal gives is to
_reduce_ such user tracking by preventing server processing of such
user IDs (since the server is bypassed in favor of the cache).
[NAV-TRACKING-MITIGATIONS]
However, an errant configuration that incorrectly ignores parameters
related to user identity or private state could expose cached content
meant for one user to another. While this mistake can occur with
standard caching, the "No-Vary-Search" response header field
increases the surface area for such misconfigurations, making it
critical that origins accurately classify their query parameters.
10. IANA Considerations
10.1. HTTP Field Names
IANA is requested to enter the following into the Hypertext Transfer
Protocol (HTTP) Field Name Registry
(https://www.iana.org/assignments/http-fields/http-fields.xhtml
(https://www.iana.org/assignments/http-fields/http-fields.xhtml)):
Field Name: No-Vary-Search
Status: permanent
Structured Type: Dictionary
Denicola, et al. Expires 4 February 2027 [Page 17]
Internet-Draft No-Vary-Search August 2026
Reference: this document
Comments: (none)
11. References
11.1. Normative References
[FETCH] van Kesteren, A., "Fetch Living Standard", n.d.,
. WHATWG
[HTTP] Fielding, R., Ed., Nottingham, M., Ed., and J. Reschke,
Ed., "HTTP Semantics", STD 97, RFC 9110,
DOI 10.17487/RFC9110, June 2022,
.
[HTTP-CACHING]
Fielding, R., Ed., Nottingham, M., Ed., and J. Reschke,
Ed., "HTTP Caching", STD 98, RFC 9111,
DOI 10.17487/RFC9111, June 2022,
.
[RFC2119] Bradner, S., "Key words for use in RFCs to Indicate
Requirement Levels", BCP 14, RFC 2119,
DOI 10.17487/RFC2119, March 1997,
.
[RFC8174] Leiba, B., "Ambiguity of Uppercase vs Lowercase in RFC
2119 Key Words", BCP 14, RFC 8174, DOI 10.17487/RFC8174,
May 2017, .
[STRUCTURED-FIELDS]
Nottingham, M. and P. Kamp, "Structured Field Values for
HTTP", RFC 9651, DOI 10.17487/RFC9651, September 2024,
.
[URI] Berners-Lee, T., Fielding, R., and L. Masinter, "Uniform
Resource Identifier (URI): Generic Syntax", STD 66,
RFC 3986, DOI 10.17487/RFC3986, January 2005,
.
[WHATWG-ENCODING]
van Kesteren, A., "Encoding Living Standard", n.d.,
. WHATWG
[WHATWG-INFRA]
van Kesteren, A. and D. Denicola, "Infra Living Standard",
n.d., . WHATWG
Denicola, et al. Expires 4 February 2027 [Page 18]
Internet-Draft No-Vary-Search August 2026
[WHATWG-URL]
van Kesteren, A., "URL Living Standard", n.d.,
. WHATWG
11.2. Informative References
[HTML] van Kesteren, A., "HTML Living Standard", n.d.,
. WHATWG
[NAV-TRACKING-MITIGATIONS]
Snyder, P. and J. Yasskin, "Navigational-Tracking
Mitigations", n.d.,
.
W3C Privacy CG
[ORIGIN] Barth, A., "The Web Origin Concept", RFC 6454,
DOI 10.17487/RFC6454, December 2011,
.
[RFC6943] Thaler, D., Ed., "Issues in Identifier Comparison for
Security Purposes", RFC 6943, DOI 10.17487/RFC6943, May
2013, .
Acknowledgments
This document benefited from valuable reviews and suggestions by:
* Adam Rice
* Julian Reschke
* Kevin McNee
* Liviu Tinta
* Mark Nottingham
* Martin Thomson
* Valentin Gosu
Index
D E O P
D
default URL variation config *_Section 4, Paragraph 3_*;
Denicola, et al. Expires 4 February 2027 [Page 19]
Internet-Draft No-Vary-Search August 2026
Section 5.1, Paragraph 2.1.1; Section 5.1, Paragraph
2.4.2.1.1; Section 5.1, Paragraph 2.5.1; Section 5.1,
Paragraph 2.6.2.1.1; Section 5.1, Paragraph 2.6.2.2.1;
Section 5.1, Paragraph 2.6.2.4.1; Section 5.1, Paragraph
2.7.2.1.1; Section 5.1, Paragraph 2.7.2.2.1; Section 5.1,
Paragraph 2.7.2.4.1; Section 5.1, Paragraph 3.1;
Section 5.2.1, Paragraph 3; Section 6, Paragraph 2.2.1
E
equivalent modulo variation config *_Section 6, Paragraph 1_*
O
obtain a URL variation config Section 4, Paragraph 4;
*_Section 5.2, Paragraph 1_*
P
parse a key Section 5.1, Paragraph 2.6.2.3.1; Section 5.1,
Paragraph 2.7.2.3.1; *_Section 5.3, Paragraph 1_*;
Section 5.3.1, Paragraph 1
parse a URL variation config *_Section 5.1, Paragraph 1_*;
Section 5.2, Paragraph 2.2.1
Authors' Addresses
Domenic Denicola
Google LLC
Email: d@domenic.me
Jeremy Roman
Google LLC
Email: jbroman@chromium.org
Nidhi Jaju (editor)
Google LLC
Email: nidhijaju@chromium.org
Denicola, et al. Expires 4 February 2027 [Page 20]