Many moving parts related to Client Hints were enabled by default in Chrome version 84. Starting in this version, access to Client Hints can be delegated to 3rd parties. 🎉
Client Hints has been here for a while – since Chrome 35 in 2015, actually. However, support in most Chrome browsers got pulled due to privacy concerns in version 67. In short, there was concerns about that Client Hints could be used to fingerprint end users. As a result, access to Client Hints were limited to certain Chrome versions on Android and 1st party origins in other Chrome versions.
Still, specification work continued, and much of the Client Hints are moved into the Network Information API. Here is the list of client hints (not related to the user-agent hints, which I’ll cover in a later post):
Until recently, requests to sub resources at the origin will receive the above hints, provided that the site opts in:
Accept-CH: viewport-width, width, device-memory, dpr, rtt, downlink, ect
So far so good. If the server response for the web page contains this response header, the subsequent request ot the same origin, for images for example, the client hints will be added to the requests for resources.
Here is a glitch demoing the basic infrastructure:
For the glitch examples; make sure to test them using Chrome version 84 or higher.
Hint: look at the request headers of the image on the page above.
Client Hints to 3rd parties and sub-domains
When the full support for Client Hints was pulled in Chrome 67, the intention was to reintroduce it when Feature Policies could add a layer of security to it. With Chrome version 84, we’re finally there.
From Chrome version 84 onwards, resources located on 3rd party domains and sub domains is also able to receive Client Hints. This is good news of CDNS, in particular image optimization CDNs
Here’s now to delegate Client Hints to 3rd parties:
At the time of writing, the mechanism for delegating Client Hints to 3rd parties is named Feature Policies. However, it’s about to be renamed to Permission Policies.
A Feature / Permission policy is a HTTP header specifying which origins (domains) have access to which browser features.
In the following example, I’ve specified this policy:
Feature-Policy: ch-viewport-width https://example.com;ch-width https://example.com;ch-dpr https://example.com;ch-device-memory https://example.com;ch-rtt https://example.com;ch-ect https://example.com;ch-downlink https://example.com
This policy grants resources located on
https://example.com access to the specified hints.
Pitfall 1) Note the
ch- prefix. The notation is
Pitfall 2) Use lowercase! Even if docs and examples say for example
Accept-CH: DPR, make sure to use
ch-dpr in the your policy header!
In the glicth above, client hints are now delegated to
https://example.com/ and the image request for
https://example.com/test.jpg receives the specified hints.
Note that the 3rd party being delegated to, doesn’t have to opt in or announce which hints it will respond to. All resources on
example.com will receive the delegated hints. But only image requests will get the
width hint. Moreover, it seems like
viewport-width will have a default value for non-image requests.
Here are some captures from dev tools to demostrate:
Browser is requesting
https://holly-imaginary-emoji.glitch.me/ and gets this response:
The browser is rendering the response, acknowledging the feature headers, and finally seing the request for
https://example.com/test.jpg. Then the browser knows that for this origin (
https://example.com) the client hints specified in the
accept-ch header should be a part of the request for
It wasn’t obvious to me how this would end up being implemented in Chrome. Docs, specs and examples explains it differently. Then there is case sensitivity, prefixing and policy renaming. All moving targets right now. However, in Chrome v84 it’s being implemented like described here, so chances are good that this is how it will end up in the wild.