RFC 9842

Compression Dictionary Transport

πŸ“… published September 2025, from ietf

RFC 9842: Compression Dictionary Transport πŸŽ€

Okay bestie, this one is an IETF doc (the Internet Engineering Task Force, the crew that writes the rules for how the internet talks 🌐). It's RFC 9842, dated September 2025, and its category is Standards Track πŸ’…. The ISSN is 2070-1721. Two editors put it together: P. Meenan, Ed. from Google LLC and Y. Weiss, Ed. from Shopify Inc. 🫢 The title block doesn't list any obsoletes or updates lines, so this one's standing on its own ✨

Abstract ✨

This doc is all about dictionary-based compression in HTTP πŸ“ The trick is that clients and servers can shrink the data they send, which means faster pages and less bandwidth eaten up πŸ“‰ It extends the compression methods HTTP already has, and it gives guidelines for delivering compression dictionaries and actually using them πŸ’–

Status of This Memo πŸ“œ

This is an Internet Standards Track document.

This document is a product of the Internet Engineering Task Force (IETF). It represents the consensus of the IETF community. It went through public review and was approved for publication by the Internet Engineering Steering Group (IESG). If you want more on Internet Standards, check Section 2 of RFC 7841.

Info about the current status of this document, any errata, and how to send feedback lives at https://www.rfc-editor.org/info/rfc9842 πŸ”—

Copyright (c) 2025 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) as they stand on the date of publication. Please actually read these, because they spell out your rights and restrictions for this document πŸ“– Code Components pulled out of this document must include Revised BSD License text, as described in Section 4.e of the Trust Legal Provisions, and they come without warranty, as described in the Revised BSD License.

Table of Contents πŸ—ΊοΈ

1.  Introduction
  1.1.  Use Cases
    1.1.1.  Version Upgrade
    1.1.2.  Common Content
  1.2.  Notational Conventions
2.  Dictionary Negotiation
  2.1.  Use-As-Dictionary
    2.1.1.  "match"
    2.1.2.  "match-dest"
    2.1.3.  "id"
    2.1.4.  "type"
    2.1.5.  Examples
  2.2.  Available-Dictionary
    2.2.1.  Dictionary Freshness Requirement
    2.2.2.  Dictionary URL Matching
    2.2.3.  Multiple Matching Dictionaries
  2.3.  Dictionary-ID
3.  The "compression-dictionary" Link Relation Type
4.  Dictionary-Compressed Brotli
5.  Dictionary-Compressed Zstandard
6.  Negotiating the Content Encoding
  6.1.  Accept-Encoding
  6.2.  Content-Encoding
7.  IANA Considerations
  7.1.  Content Encoding Registration
  7.2.  Header Field Registration
  7.3.  Link Relation Registration
8.  Compatibility Considerations
9.  Security Considerations
  9.1.  Changing Content
  9.2.  Reading Content
  9.3.  Security Mitigations
    9.3.1.  Cross-Origin Protection
    9.3.2.  Response Readability
    9.3.3.  Server Responsibility
10. Privacy Considerations
11. References
  11.1.  Normative References
  11.2.  Informative References
Authors' Addresses

1. Introduction πŸ’«

So here's the big idea: any designated HTTP [HTTP] response can be used as an external dictionary for future HTTP responses 🧚 This works for compression schemes that support external dictionaries, like Brotli [RFC7932] and Zstandard [ZSTD] 🌈

This document describes the HTTP headers used to negotiate dictionary usage. It also registers content-encoding values for compressing with Brotli and Zstandard when a negotiated dictionary is in play πŸŽ€

Negotiating dictionary usage uses HTTP's content negotiation (see Section 12 of [HTTP]), and it works with all versions of HTTP πŸ¦‹

1.1. Use Cases

Any HTTP response can be specified as a compression dictionary for future HTTP requests, which gives you a ton of flexibility πŸ’… Two common use cases show up a lot, so here they are.

1.1.1. Version Upgrade

Use a previous version of a resource as the dictionary for a newer version, and the server can send a delta-compressed version of just the changes πŸ”₯ That usually comes out way smaller than what compression alone could do.

For example:

Client                                        Server
|                                                  |
| GET /app.v1.js                                   |
|------------------------------------------------->|
|                                                  |
|     200 OK                                       |
|     Use-As-Dictionary: match="/app*js"           |
|     <full app.v1.js resource - 100KB compressed> |
|<-------------------------------------------------|
|                                                  |

Some time later ...

Client                                        Server
|                                                  |
| GET /app.v2.js                                   |
| Available-Dictionary: :pZGm1A...2a2fFG4=:        |
| Accept-Encoding: gzip, br, zstd, dcb, dcz        |
|------------------------------------------------->|
|                                                  |
|      200 OK                                      |
|      Content-Encoding: dcb                       |
|      <delta-compressed app.v2.js resource - 1KB> |
|<-------------------------------------------------|
|                                                  |

Figure 1: Version Upgrade Example

1.1.2. Common Content

If several resources share common patterns in their responses, you can point at an external dictionary holding those patterns and basically compress them right out of the responses 🧹 Think common template HTML across pages on a site, or common keys and values in API calls.

For example:

Client                                          Server
|                                                    |
| GET /index.html                                    |
|--------------------------------------------------->|
|                                                    |
|     200 OK                                         |
|     Link: <.../dict>; rel="compression-dictionary" |
|     <full index.html resource - 100KB compressed>  |
|<---------------------------------------------------|
|                                                    |
| GET /dict                                          |
|--------------------------------------------------->|
|                                                    |
|                  200 OK                            |
|                  Use-As-Dictionary: match="/*html" |
|<---------------------------------------------------|
|                                                    |

Some time later ...

Client                                          Server
|                                                    |
| GET /page2.html                                    |
| Available-Dictionary: :pZGm1A...2a2fFG4=:          |
| Accept-Encoding: gzip, br, zstd, dcb, dcz          |
|--------------------------------------------------->|
|                                                    |
|      200 OK                                        |
|      Content-Encoding: dcb                         |
|      <delta-compressed page2.html resource - 10KB> |
|<---------------------------------------------------|
|                                                    |

Figure 2: Common Content Example

1.2. Notational Conventions πŸ“

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.

This document uses the following terminology from Section 3 of [STRUCTURED-FIELDS] to specify syntax and parsing: Dictionary, String, Inner List, Token, and Byte Sequence.

This document uses the line folding strategies described in [FOLDING].

This document also uses terminology from [HTTP] and [HTTP-CACHING].

2. Dictionary Negotiation 🀝

2.1. Use-As-Dictionary πŸͺ„

When a server responds to an HTTP Request, it can advertise that the response works as a dictionary for future requests to URLs that match the rules in the Use-As-Dictionary response header πŸ’–

The Use-As-Dictionary response header is a Structured Field [STRUCTURED-FIELDS] Dictionary with values for match, match-dest, id, and type ✨

2.1.1. "match" 🎯

The match value of the Use-As-Dictionary response header is a String that holds the URL Pattern used for request matching (see [URLPATTERN]).

The URL Pattern matching doesn't support regular expressions πŸ™…β€β™€οΈ

Here's the algorithm to check that a given String is a valid URL Pattern. It can't use regular expressions, and it has to be for the same Origin (Section 4.3.1 of [HTTP]) as the dictionary. It returns TRUE for a valid match pattern and FALSE for an invalid one, and an invalid pattern MUST NOT be used.

  1. Let MATCH be the value of match for the given dictionary.
  2. Let URL be the URL of the dictionary request.
  3. Let PATTERN be a "URL pattern struct" created by running the steps to "create a URL pattern" by setting input=MATCH and baseURL=URL (see Section 1.4 of [URLPATTERN]).
  4. If the result of running the "has regexp groups" steps for PATTERN returns TRUE, then return FALSE (see the last list in Section 1.4 of [URLPATTERN]).
  5. Return TRUE.

The match value is required and MUST be included in the Use-As-Dictionary response header for the dictionary to be considered valid 🚨

Since this happens at the HTTP level, the match patterns work on the percent-encoded version of the URL path (see Section 2 of [URL]) πŸ”

For example, the URL http://www.example.com/dΓΌsseldorf gets encoded as http://www.example.com/d%C3%BCsseldorf, so a relevant match pattern would be:

Use-As-Dictionary: match="/d%C3%BCsseldorf"

2.1.2. "match-dest" πŸŽ€

The match-dest value of the Use-As-Dictionary response header is an Inner List of String values. It lists the Fetch request destinations the dictionary should match (see "RequestDestination" in Section 5.4 of [FETCH]) πŸ“

An empty list for match-dest MUST match all destinations.

For clients that don't support request destinations, the client MUST treat it as an empty list and match all destinations.

The match-dest value is optional and defaults to an empty list.


Part 1 of 4 wraps up here. Part 2 picks up at Section 2.1.3 ("id") 🫢

2.1.3. "id" πŸ’–

Okay so, the id value on the Use-As-Dictionary response header is a String that gives the dictionary a server identifier πŸŽ€. If there's an id and it's longer than zero characters, then it MUST be sent back to the server in a Dictionary-ID request header whenever the client sends an Available-Dictionary request header for that same dictionary (see Section 2.2) πŸ¦‹.

The client MUST treat the server identifier as an opaque string πŸ”’. Bestie, the server MUST NOT rely on that identifier to guarantee what's inside the dictionary πŸ™ˆ. The dictionary hash MUST be validated before use ✨.

The id value can be up to 1024 characters long after any decoding 🌸. And id is optional, defaulting to the empty string πŸ“.

2.1.4. "type" 🧚

The type value of the Use-As-Dictionary response header is a Token that describes the file format of the dictionary you're handing over πŸ“„.

"raw" is the format for an unformatted blob of bytes that any compression scheme can use 🌈. It's giving pure potential πŸ’….

If a client gets a dictionary with a type it doesn't understand, it MUST NOT use that dictionary πŸ™…β€β™€οΈ. And type is optional, defaulting to "raw" πŸ’œ.

2.1.5. Examples πŸ“š

2.1.5.1. Path Prefix πŸ›£οΈ

A response carrying the header below would say to match any document request for a URL whose path starts with /product/, on the same Origin (Section 4.3.1 of [HTTP]) as the original request πŸ’…:

NOTE: '' line wrapping per RFC 8792
Use-As-Dictionary: \
  match="/product/*", match-dest=("document")

2.1.5.2. Versioned Directories πŸ“

A response with this header would match any path that starts with "/app/" and ends with "/main.js" πŸ’«:

Use-As-Dictionary: match="/app/*/main.js"

2.2. Available-Dictionary 🎯

When an HTTP client asks for a resource it has a good dictionary for, it can add an Available-Dictionary request header πŸ™Œ. That's how it lets the server know it has a dictionary ready for compression 🫢.

The Available-Dictionary request header is a Structured Field [STRUCTURED-FIELDS] Byte Sequence holding the SHA-256 [SHA-256] hash of the contents of one single available dictionary πŸ”.

The client MUST only send a single Available-Dictionary request header, with one hash value, for the best available match it has πŸ‘‘. For example:

Available-Dictionary: :pZGm1Av0IEBKARczz7exkNYsZb8LzaMrV7J32a2fFG4=:

2.2.1. Dictionary Freshness Requirement ⏰

To count as a match, the dictionary resource MUST be either fresh [HTTP-CACHING] or allowed to be served stale (see [RFC5861]) ✨.

2.2.2. Dictionary URL Matching πŸ”

When a dictionary gets stored because of a Use-As-Dictionary directive, it comes with a match string and an optional match-dest string 🧩. Those two are what get used to match an outgoing client request against the available dictionaries πŸŽ€.

To check whether an outbound request matches a dictionary, follow this algorithm. It returns TRUE for a successful match and FALSE for no match 🌟:

  1. If the current client supports request destinations and a match-dest string was provided with the dictionary:
    • Let DEST be the value of match-dest for the given dictionary.
    • Let REQUEST_DEST be the value of the destination for the current request.
    • If DEST is not an empty list and if REQUEST_DEST is not in the DEST list of destinations, return FALSE.
  2. Let BASEURL be the URL of the dictionary request.
  3. Let URL represent the URL of the outbound request being checked.
  4. If the Origin of BASEURL and the Origin of URL are not the same, return FALSE (see Section 4.3.1 of [HTTP]).
  5. Let MATCH be the value of match for the given dictionary.
  6. Let PATTERN be a "URL pattern struct" created by running the steps to "create a URL pattern" by setting input=MATCH and baseURL=URL (see Section 1.4 of [URLPATTERN]).
  7. Return the result of running the "match" steps on PATTERN with input=URL, which will check for a match between the request URL and the supplied match string (see "Match" in Section 1.4 of [URLPATTERN]).

2.2.3. Multiple Matching Dictionaries πŸ₯‡

Sometimes several dictionaries match one request URL. When that happens, the client MUST pick a single dictionary using these rules πŸ‘―:

  1. For clients that support request destinations, a dictionary that specifies and matches a match-dest takes precedence over a match that doesn't use a destination 🎯.
  2. Given equivalent destination precedence, the dictionary with the longest match takes precedence πŸ“.
  3. Given equivalent destination and match length precedence, the most recently fetched dictionary takes precedence πŸ•°οΈ.

2.3. Dictionary-ID πŸͺͺ

When an HTTP client asks for a resource it has a suitable dictionary for, and that dictionary was stored with a server-provided id in the Use-As-Dictionary response header, the client MUST echo the stored id back in a Dictionary-ID request header πŸ”.

The Dictionary-ID request header is a Structured Field [STRUCTURED-FIELDS] String of up to 1024 characters (after any decoding). It MUST be identical to the server-provided id πŸ’―.

For example, say an HTTP response set a dictionary ID like this:

Use-As-Dictionary: match="/app/*/main.js", id="dictionary-12345"

A future request that matches that dictionary will include both the hash and the ID 🫧:

Available-Dictionary: :pZGm1Av0IEBKARczz7exkNYsZb8LzaMrV7J32a2fFG4=:
Dictionary-ID: "dictionary-12345"

This specification defines the "compression-dictionary" link relation type [WEB-LINKING] πŸ’•. It gives an HTTP response a way to point at a URL for a compression dictionary that's related to the response but isn't used by it directly 🌷.

The "compression-dictionary" link relation type says that fetching and caching the specified resource is likely to pay off for future requests πŸ’°. Some of those future responses will probably be able to use that resource as a compression dictionary πŸ¦„.

Clients can fetch the resource whenever they decide it's a good time πŸ•“.

To make the fetched resource usable as a compression dictionary, its response needs a Use-As-Dictionary response header and a caching response header πŸ“¦. The link relation only triggers the fetch. That's it, that's the tea 🍡.

Here's an example linking to a resource at https://example.org/dict.dat that's expected to produce a compression dictionary 🌈:

Link: <https://example.org/dict.dat>; rel="compression-dictionary"

4. Dictionary-Compressed Brotli πŸ₯¦

The "dcb" content encoding identifies a resource that's a "Dictionary-Compressed Brotli" stream ✨.

A "Dictionary-Compressed Brotli" stream starts with a fixed header, and then comes a Shared Brotli [SHARED-BROTLI] stream 🧁. The header is a fixed 4-byte sequence plus a 32-byte hash of the external dictionary that was used πŸ”’. The Shared Brotli stream is built using that referenced external dictionary and a compression window that's at most 16 MB in size πŸͺŸ.

The dictionary used for "dcb" is a "raw" dictionary type, as defined in Section 2.1.4, and it's treated as a prefix dictionary as defined in Section 8.2 of [SHARED-BROTLI] πŸŽ€.

The 36-byte fixed header looks like this πŸ‘€:

Magic_Number:  4 fixed bytes -- 0xff, 0x44, 0x43, 0x42.

SHA_256_Hash:  32 bytes.  SHA-256 hash digest of the dictionary
   [SHA-256].

Clients that announce support for "dcb" content encoding MUST be able to decompress resources that were compressed with a window size of up to 16 MB πŸ’ͺ.

With Brotli compression, the full dictionary is available during both compression and decompression, no matter the compression window. That means you can do delta-compression on resources that are bigger than the window 🀯.

5. Dictionary-Compressed Zstandard ⚑

The "dcz" content encoding identifies a resource that's a "Dictionary-Compressed Zstandard" stream πŸ’«.

A "Dictionary-Compressed Zstandard" stream is a binary stream. It starts with a 40-byte fixed header, followed by a Zstandard [ZSTD] stream of the response, compressed with an external dictionary 🫧.

The dictionary used for "dcz" is a "raw" dictionary type, as defined in Section 2.1.4, and it's treated as a raw dictionary per Section 5 of [ZSTD] 🌸.

The 40-byte header is a fixed 8-byte sequence followed by the 32-byte SHA-256 hash of the external dictionary used to compress the resource πŸ”:

Magic_Number:  8 fixed bytes -- 0x5e, 0x2a, 0x4d, 0x18, 0x20, 0x00,
   0x00, 0x00.

SHA_256_Hash:  32 bytes.  SHA-256 hash digest of the dictionary
   [SHA-256].

The 40-byte header is a Zstandard skippable frame (little-endian 0x184D2A5E) with a 32-byte length (little-endian 0x00000020), and it stays compatible with existing Zstandard decoders 🧩.

Clients that announce support for "dcz" content encoding MUST be able to decompress resources compressed with a window size of at least 8 MB or 1.25 times the size of the dictionary (whichever is greater), up to a maximum of 128 MB πŸ‹οΈβ€β™€οΈ.

The window size used gets encoded in the content (for now, that can only be expressed in powers of two) and it MUST be lower than this limit. An implementation MAY treat a window size that exceeds the limit as a decoding error 🚫.

With Zstandard compression, the full dictionary is available during compression and decompression until the input size goes past the compression window. After that point, the dictionary is gone πŸ‘‹. Using a compression window 1.25 times the size of the dictionary allows full delta compression for resources that have grown by 25% between releases, and the client still gets to control how much memory it allocates for a given response 🧠.

6. Negotiating the Content Encoding 🀝

When a compression dictionary is available to compress the response to a request, the encoding is negotiated through the regular HTTP content-encoding mechanism, using the Accept-Encoding request header and the Content-Encoding response header πŸŽ€.

The dictionary is negotiated separately and advertised in the Available-Dictionary request header πŸ’Œ.

6.1. Accept-Encoding πŸ₯‚

When a dictionary is available for a request and the client chooses to offer dictionary-based content encoding, the client adds the dictionary-aware content encodings it supports to the Accept-Encoding request header πŸ’…. For example:

Accept-Encoding: gzip, deflate, br, zstd, dcb, dcz

When a client doesn't have a stored dictionary that matches the request, or it chooses not to use one for the request, the client MUST NOT send its dictionary-aware content encodings in the Accept-Encoding request header πŸ™…β€β™€οΈβœ¨.

6.2. Content-Encoding πŸ’…

Okay so bestie, once the server has decided to compress the response with the dictionary the client advertised ✨, it sets the "Content-Encoding" response header to the matching value for whichever algorithm it picked. Like this:

Content-Encoding: dcb

πŸŽ€ Now here's the part that matters: if the response is cacheable, the server MUST include a "Vary" header. Why? So caches don't hand a dictionary-compressed copy to someone whose client can't read it πŸ™ˆ, and don't serve a response compressed with the wrong dictionary either. It's giving "protect the cache" energy πŸ’œ. Example:

Vary: accept-encoding, available-dictionary

7. IANA Considerations 🌸

7.1. Content Encoding Registration πŸ¦‹

IANA added two entries to the "HTTP Content Coding Registry" over at <https://www.iana.org/assignments/http-parameters/> 🧚:

Name:  dcb
Description:  "Dictionary-Compressed Brotli" data format.
Reference:  RFC 9842, Section 4
Name:  dcz
Description:  "Dictionary-Compressed Zstandard" data format.
Reference:  RFC 9842, Section 5

7.2. Header Field Registration πŸ“

IANA also added three entries to the "Hypertext Transfer Protocol (HTTP) Field Name Registry" at <https://www.iana.org/assignments/http-fields/> ✨. Every one is "permanent" status, slay πŸ‘‘:

+======================+===========+=======================+
| Field Name           | Status    | Reference             |
+======================+===========+=======================+
| Use-As-Dictionary    | permanent | RFC 9842, Section 2.1 |
+----------------------+-----------+-----------------------+
| Available-Dictionary | permanent | RFC 9842, Section 2.2 |
+----------------------+-----------+-----------------------+
| Dictionary-ID        | permanent | RFC 9842, Section 2.3 |
+----------------------+-----------+-----------------------+

                                 Table 1

IANA added one entry to the "Link Relation Types" registry at <https://www.iana.org/assignments/link-relations/> 🌈:

Relation Name:  compression-dictionary
Description:  Refers to a compression dictionary used for content
   encoding.
Reference:  RFC 9842, Section 3

8. Compatibility Considerations πŸ™ˆ

Honestly, it's super normal for devices on the network path to poke at HTTP requests, like web proxies, firewalls, and intrusion detection systems πŸ‘€. So to keep those devices from messing up dictionary-compressed responses, compression dictionary transport MUST only be used in secure contexts (HTTPS) πŸ”’βœ¨.

9. Security Considerations πŸ’€

The security considerations for Brotli [RFC7932], Shared Brotli [SHARED-BROTLI], and Zstandard [ZSTD] all apply to the dictionary-based versions of those algorithms. Serious business, bestie 😭.

9.1. Changing Content πŸ”₯

The dictionary needs the same security care as the content itself 🫢, because a change to the dictionary can change the decompressed content. Yikes.

The dictionary gets validated with a SHA-256 hash of the content so the client and server are both using the same dictionary πŸ”. The strength of SHA-256 isn't explicitly needed to fight off attacks here, since the dictionary is served from the same origin as the content. Still, if a weakness ever turns up in SHA-256 and the dictionary negotiation should switch to a different hash, the "Use-As-Dictionary" response header can be extended to name the new algorithm. The server would just ignore any "Available-Dictionary" requests that don't use the updated hash πŸ¦‹.

9.2. Reading Content πŸ‘‘

The compression attacks in Section 2.6 of [RFC7457] show that compressing data from mixed sources (like public and private) is a bad idea 🚫. The data sources include the dictionaries too, not just the compressed data. For example, if secret cookies get compressed with a public-data-only dictionary, info about the cookies still leaks πŸͺπŸ’€.

The dictionary can reveal info about the compressed data, and vice versa. Data compressed with the dictionary can reveal the dictionary's contents when an adversary can control parts of the data being compressed and watch the compressed size πŸ‘€. On the flip side, if the adversary can control the dictionary, they can learn about the compressed data 😱.

9.3. Security Mitigations πŸ›‘οΈ

If any of the mitigations don't pass, the client MUST drop the response and return an error ❌.

9.3.1. Cross-Origin Protection 🌍

To make sure a dictionary can only affect content from the same origin it was served from, the URL Pattern used for matching a dictionary to requests (Section 2.1.1) is guaranteed to be for that same origin ✨.

9.3.2. Response Readability πŸ“–

For clients like web browsers that add extra protection around how readable a response payload is and around user tracking, additional protections MUST be taken so that dictionary-based compression doesn't reveal anything that wouldn't otherwise be available πŸ™ˆπŸ”’.

In those cases, dictionary compression MUST only be used when both the dictionary and the compressed response are fully readable by the client πŸ“š.

In browser terms, that means either the dictionary and compressed response are same-origin to the context they're fetched from, or the response is cross-origin and passes the Cross-Origin Resource Sharing (CORS) check (see Section 4.9 of [FETCH]) πŸ¦‹.

9.3.3. Server Responsibility 🧚

Okay, this one is serious 😭. As with any compressed content in a secure context, there's a potential timing attack if an attacker can control any part of the dictionary, or can read the dictionary and control part of the content being compressed while making multiple requests that vary the dictionary or the injected content. Under that kind of attack, the changing size or processing time of the response reveals info about the content, which might be enough to read the supposedly secure response πŸ’€.

Generally, a server can mitigate these attacks by preventing per-request variations, like not actively using multiple dictionaries for the same content, disabling compression when any part of the content comes from uncontrolled sources, and securing access to and control over the dictionary content the same way it does for the response content πŸ”. On top of that, the following server requirements are meant to turn off dictionary-aware compression when the client sends CORS request header fields that indicate a cross-origin request context 🌐.

The following algorithm returns FALSE for cross-origin requests where precautions, like not using dictionary-based compression, should be considered πŸ’…:

  1. If there is no "Sec-Fetch-Site" request header, return TRUE.
  2. If the value of the "Sec-Fetch-Site" request header is "same-origin", return TRUE.
  3. If there is no "Sec-Fetch-Mode" request header, return TRUE.
  4. If the value of the "Sec-Fetch-Mode" request header is "navigate" or "same-origin", return TRUE.
  5. If the value of the "Sec-Fetch-Mode" request header is "cors":
    • If the response does not include an "Access-Control-Allow-Origin" response header, return FALSE.
    • If the request does not include an "Origin" request header, return FALSE.
    • If the value of the "Access-Control-Allow-Origin" response header is "*", return TRUE.
    • If the value of the "Access-Control-Allow-Origin" response header matches the value of the "Origin" request header, return TRUE.
  6. Return FALSE.

10. Privacy Considerations 🫣

Since dictionaries get advertised in future requests using the hash of the dictionary's content, it's possible to abuse the dictionary and turn it into a tracking cookie πŸͺπŸ‘€. Not it πŸ™…β€β™€οΈ.

To mitigate these extra tracking concerns, clients MUST treat dictionaries the same way they treat cookies [RFC6265] πŸͺ. That includes partitioning the storage using partitioning similar to or stricter than the partitioning used for cookies, and clearing the dictionaries whenever cookies are cleared 🧹✨.


11. References πŸ“š

11.1. Normative References πŸ’œ

[FETCH] WHATWG, "Fetch Standard", WHATWG Living Standard, <https://fetch.spec.whatwg.org/>. Commit snapshot: <https://fetch.spec.whatwg.org/commit-snapshots/5a9680638ebfc2b3b7f4efb2bef0b579a2663951/>

[FOLDING] Watsen, K., Auerswald, E., Farrel, A., and Q. Wu, "Handling Long Lines in Content of Internet-Drafts and RFCs", RFC 8792, DOI 10.17487/RFC8792, June 2020, <https://www.rfc-editor.org/info/rfc8792>.

[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/info/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/info/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/info/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/info/rfc8174>.

[SHA-256] Eastlake 3rd, D. and T. Hansen, "US Secure Hash Algorithms (SHA and SHA-based HMAC and HKDF)", RFC 6234, DOI 10.17487/RFC6234, May 2011, <https://www.rfc-editor.org/info/rfc6234>.

[SHARED-BROTLI] Alakuijala, J., Duong, T., Kliuchnikov, E., Szabadka, Z., and L. Vandevenne, Ed., "Shared Brotli Compressed Data Format", RFC 9841, DOI 10.17487/RFC9841, September 2025, <https://www.rfc-editor.org/info/rfc9841>.

[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/info/rfc9651>.

[URL] 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/info/rfc3986>.

[URLPATTERN] WHATWG, "URL Pattern Standard", WHATWG Living Standard, <https://urlpattern.spec.whatwg.org/>. Commit snapshot: <https://urlpattern.spec.whatwg.org/commit-snapshots/696b4029d52e5854044bac6b72cdb198cb962ed0/>

[WEB-LINKING] Nottingham, M., "Web Linking", RFC 8288, DOI 10.17487/RFC8288, October 2017, <https://www.rfc-editor.org/info/rfc8288>.

[ZSTD] Collet, Y. and M. Kucherawy, Ed., "Zstandard Compression and the 'application/zstd' Media Type", RFC 8878, DOI 10.17487/RFC8878, February 2021, <https://www.rfc-editor.org/info/rfc8878>.

11.2. Informative References πŸ“š

okay bestie, these are the informative refs, the ones the doc name-drops for extra context without being required reading to implement it. 🧚


Authors' Addresses 🫢

Patrick Meenan (editor) πŸ’… Google LLC Email: pmeenan@google.com

Yoav Weiss (editor) πŸ’… Shopify Inc. Email: yoav.weiss@shopify.com

and that's the whole doc, bestie!! πŸŽ€βœ¨ we made it through every section, and the authors are right there at the bottom if you ever need to slide into their inbox πŸ’–

πŸ“¦ where this page comes from