Skip to main content

The No-Vary-Search HTTP Caching Extension
draft-ietf-httpbis-no-vary-search-08

Document Type Active Internet-Draft (httpbis WG)
Authors Domenic Denicola , Jeremy Roman , Nidhi Jaju
Last updated 2026-08-12
Replaces draft-wicg-http-no-vary-search
RFC stream Internet Engineering Task Force (IETF)
Intended RFC status Proposed Standard
Formats
Reviews
Additional resources Mailing list discussion
Stream WG state Submitted to IESG for Publication
Document shepherd Tommy Pauly
Shepherd write-up Show Last changed 2026-06-03
IESG IESG state IESG Evaluation
Action Holder
Consensus boilerplate Yes
Telechat date On agenda of 2026-08-20 IESG telechat
Needs 4 more YES or NO OBJECTION positions to pass.
Responsible AD Mike Bishop
Send notices to tpauly@apple.com
IANA IANA review state Version Changed - Review Needed
IANA expert review state Expert Reviews OK
draft-ietf-httpbis-no-vary-search-08
HyperText Transfer Protocol                                  D. Denicola
Internet-Draft                                                  J. Roman
Intended status: Standards Track                            N. Jaju, Ed.
Expires: 13 February 2027                                     Google LLC
                                                          12 August 2026

               The No-Vary-Search HTTP Caching Extension
                  draft-ietf-httpbis-no-vary-search-08

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 13 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 13 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  . . . . . . . . . . . . . . . . . . . . . .   8
     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 . . . . . . . . . . . . . . . . . . . . .  18
     10.1.  HTTP Field Names . . . . . . . . . . . . . . . . . . . .  18
     10.2.  No-Vary-Search Dictionary Keys Registry  . . . . . . . .  18
   11. References  . . . . . . . . . . . . . . . . . . . . . . . . .  19
     11.1.  Normative References . . . . . . . . . . . . . . . . . .  19
     11.2.  Informative References . . . . . . . . . . . . . . . . .  20
   Acknowledgments . . . . . . . . . . . . . . . . . . . . . . . . .  20
   Index . . . . . . . . . . . . . . . . . . . . . . . . . . . . . .  21
   Authors' Addresses  . . . . . . . . . . . . . . . . . . . . . . .  21

Denicola, et al.        Expires 13 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 13 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 13 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).  Future extensions to this dictionary MUST NOT restrict the
   set of URIs that are considered equivalent; they can only expand it.
   If a future extension requires restricting equivalence, it MUST be
   deployed as a new HTTP header field to ensure safety.

   The "No-Vary-Search" response header field is set by origin servers.
   Intermediaries MUST NOT insert, delete, or modify the field's value
   unless they are acting as the origin server for that response.

      |  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

Denicola, et al.        Expires 13 February 2027                [Page 5]
Internet-Draft               No-Vary-Search                  August 2026

   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:

   *  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, then
       return the default URL variation config.

   6.  If neither _value_["params"] nor _value_["except"] exists:

       1.  Set _result_'s no-vary params to an empty list.

       2.  Set _result_'s vary params to *wildcard*.

   7.  If _value_["params"] exists:

       1.  If _value_["params"] is not an inner list, then return the
           default URL variation config.

Denicola, et al.        Expires 13 February 2027                [Page 6]
Internet-Draft               No-Vary-Search                  August 2026

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

   8.  Otherwise, if _value_["except"] exists:

       1.  If _value_["except"] is not an inner list, 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*.

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

      |  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]).  If parsing fails or the
       field is absent, let _fieldValue_ be null.

Denicola, et al.        Expires 13 February 2027                [Page 7]
Internet-Draft               No-Vary-Search                  August 2026

   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:

            +=================+==============================+
            | 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 13 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 13 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 13 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 cache produces a non-ASCII result.
   This will result in a URL variation config whose no-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, 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 13 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 13 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 13 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.

Denicola, et al.        Expires 13 February 2027               [Page 14]
Internet-Draft               No-Vary-Search                  August 2026

   This document does not alter the requirements for cache invalidation
   (see Section 4.4 of [HTTP-CACHING]).  A cache MAY invalidate stored
   responses for URIs that are equivalent modulo URL variation config,
   but is not required to do so.  Therefore, state-changing requests
   might not invalidate all conceptually equivalent responses.

   Note that the "No-Vary-Search" response header field operates in
   addition to content negotiation and the Vary header field (see
   Section 4.1 of [HTTP-CACHING]).

   Cache implementations MAY fail to reuse a stored response whose
   target URI matches _only_ modulo URL variation config, if the cache
   has a stored response with a more recent Date header field which:

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

   When a cache has multiple stored responses with conflicting "No-Vary-
   Search" values, preferring the response with the most recent Date
   header field helps ensure caches converge on the origin's latest
   caching policy.

      |  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 target URI path and authority, 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.
      |  

Denicola, et al.        Expires 13 February 2027               [Page 15]
Internet-Draft               No-Vary-Search                  August 2026

      |     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.
      |  
      |     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 target URI path and
   authority 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.

Denicola, et al.        Expires 13 February 2027               [Page 16]
Internet-Draft               No-Vary-Search                  August 2026

   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.  Origin
   servers MUST NOT declare a parameter as no-vary 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.

   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) [HTML] 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.  If an origin were to encode user identifiers
   in its URI, this proposal can reduce user tracking by private caches,
   since preventing server processing of such user IDs bypasses the
   server in favor of the cache.  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.  [NAV-TRACKING-MITIGATIONS]

Denicola, et al.        Expires 13 February 2027               [Page 17]
Internet-Draft               No-Vary-Search                  August 2026

   However, this tracking reduction does not fully apply to shared
   caches (such as content delivery networks and forward proxies), which
   still receive the requests containing the identifiers.  Furthermore,
   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

   Reference:  this document

   Comments:  (none)

10.2.  No-Vary-Search Dictionary Keys Registry

   IANA is requested to create a new registry, "No-Vary-Search
   Dictionary Keys", at https://www.iana.org/assignments/http-fields/
   (https://www.iana.org/assignments/http-fields/).

   The registration policy is "IETF Review" (see Section 4.8 of
   [RFC8126]).

   A registration request MUST include the following fields:

   *  Key: the dictionary key for the "No-Vary-Search" response header
      field

   *  Description: a brief description of the key's purpose

   *  Reference: a pointer to the specification that defines the key

   The initial contents of this registry are:

Denicola, et al.        Expires 13 February 2027               [Page 18]
Internet-Draft               No-Vary-Search                  August 2026

         +===========+==============================+===========+
         | Key       | Description                  | Reference |
         +===========+==============================+===========+
         | key-order | Indicates if query parameter | this      |
         |           | order affects caching        | document  |
         +-----------+------------------------------+-----------+
         | params    | A list of query parameters   | this      |
         |           | that do not affect caching   | document  |
         +-----------+------------------------------+-----------+
         | except    | A list of query parameters   | this      |
         |           | that affect caching          | document  |
         +-----------+------------------------------+-----------+

                                 Table 5

11.  References

11.1.  Normative References

   [HTTP]     Fielding, R., Ed., Nottingham, M., Ed., and J. Reschke,
              Ed., "HTTP Semantics", STD 97, RFC 9110,
              DOI 10.17487/RFC9110, June 2022,
              <https://www.rfc-editor.org/rfc/rfc9110>.

   [HTTP-CACHING]
              Fielding, R., Ed., Nottingham, M., Ed., and J. Reschke,
              Ed., "HTTP Caching", STD 98, RFC 9111,
              DOI 10.17487/RFC9111, June 2022,
              <https://www.rfc-editor.org/rfc/rfc9111>.

   [RFC2119]  Bradner, S., "Key words for use in RFCs to Indicate
              Requirement Levels", BCP 14, RFC 2119,
              DOI 10.17487/RFC2119, March 1997,
              <https://www.rfc-editor.org/rfc/rfc2119>.

   [RFC8174]  Leiba, B., "Ambiguity of Uppercase vs Lowercase in RFC
              2119 Key Words", BCP 14, RFC 8174, DOI 10.17487/RFC8174,
              May 2017, <https://www.rfc-editor.org/rfc/rfc8174>.

   [STRUCTURED-FIELDS]
              Nottingham, M. and P. Kamp, "Structured Field Values for
              HTTP", RFC 9651, DOI 10.17487/RFC9651, September 2024,
              <https://www.rfc-editor.org/rfc/rfc9651>.

   [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,
              <https://www.rfc-editor.org/rfc/rfc3986>.

Denicola, et al.        Expires 13 February 2027               [Page 19]
Internet-Draft               No-Vary-Search                  August 2026

   [WHATWG-ENCODING]
              van Kesteren, A., "Encoding Living Standard", n.d.,
              <https://encoding.spec.whatwg.org/>.  WHATWG

   [WHATWG-INFRA]
              van Kesteren, A. and D. Denicola, "Infra Living Standard",
              n.d., <https://infra.spec.whatwg.org/>.  WHATWG

   [WHATWG-URL]
              van Kesteren, A., "URL Living Standard", n.d.,
              <https://url.spec.whatwg.org/>.  WHATWG

11.2.  Informative References

   [HTML]     van Kesteren, A., "HTML Living Standard", n.d.,
              <https://html.spec.whatwg.org/>.  WHATWG

   [NAV-TRACKING-MITIGATIONS]
              Snyder, P. and J. Yasskin, "Navigational-Tracking
              Mitigations", n.d.,
              <https://privacycg.github.io/nav-tracking-mitigations/>.
              W3C Privacy CG

   [ORIGIN]   Barth, A., "The Web Origin Concept", RFC 6454,
              DOI 10.17487/RFC6454, December 2011,
              <https://www.rfc-editor.org/rfc/rfc6454>.

   [RFC6943]  Thaler, D., Ed., "Issues in Identifier Comparison for
              Security Purposes", RFC 6943, DOI 10.17487/RFC6943, May
              2013, <https://www.rfc-editor.org/rfc/rfc6943>.

   [RFC8126]  Cotton, M., Leiba, B., and T. Narten, "Guidelines for
              Writing an IANA Considerations Section in RFCs", BCP 26,
              RFC 8126, DOI 10.17487/RFC8126, June 2017,
              <https://www.rfc-editor.org/rfc/rfc8126>.

Acknowledgments

   This document benefited from valuable reviews and suggestions by:

   *  Adam Rice

   *  Julian Reschke

   *  Kevin McNee

   *  Liviu Tinta

Denicola, et al.        Expires 13 February 2027               [Page 20]
Internet-Draft               No-Vary-Search                  August 2026

   *  Mark Nottingham

   *  Martin Thomson

   *  Valentin Gosu

Index

   D E O P

      D

         default URL variation config  *_Section 4, Paragraph 3_*;
            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.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
            2.8.2.1.1; Section 5.1, Paragraph 2.8.2.2.1; Section 5.1,
            Paragraph 2.8.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.7.2.3.1; Section 5.1,
            Paragraph 2.8.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

Denicola, et al.        Expires 13 February 2027               [Page 21]
Internet-Draft               No-Vary-Search                  August 2026

   Nidhi Jaju (editor)
   Google LLC
   Email: nidhijaju@chromium.org

Denicola, et al.        Expires 13 February 2027               [Page 22]