User-Agent evolution
String to Client Hints
merewood@ / @rowan_m
Confidential + Proprietary
Confidential + Proprietary
What are we going to talk about?
Confidential + Proprietary
User-Agent string
User-Agent: CERN-LineMode/2.15 libwww/2.17b3
Confidential + Proprietary
User-Agent string
User-Agent: CERN-LineMode/2.15 libwww/2.17b3
Mozilla/5.0 (Linux; Android 11; Pixel 5) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/90.0.4430.61 Mobile Safari/537.36
Confidential + Proprietary
User-Agent String
Confidential + Proprietary
60-70%
"…of HTTP user-agent strings can accurately identify hosts in our datasets"
Microsoft research: Host Fingerprinting and Tracking on the Web:Privacy and Security Implications
Confidential + Proprietary
Reducing Chrome's�user-agent string
Confidential + Proprietary
Confidential + Proprietary
Reducing Chrome's user-agent string
Mozilla/5.0 (Linux; Android 9; SM-A205U) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/93.0.1234.56 Mobile Safari/537.36
Mozilla/5.0 (Linux; Android 10; K) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/93.0.0.0 Mobile Safari/537.36
Full phases detailed at: chromium.org/updates/ua-reduction
Confidential + Proprietary
Early opt-in origin trial
Confidential + Proprietary
Confidential + Proprietary
Privacy Sandbox patterns
Confidential + Proprietary
Confidential + Proprietary
Client Hints
⬆️ Client (browser) sends initial request
⬇️ Server specifies desired hints in response
⬆️ Client may send hints in subsequent requests
Confidential + Proprietary
⬇️ Server response� Accept-CH: Viewport-Width, Width
↪️ Or a meta tag� <meta http-equiv="Accept-CH" content="Viewport-Width, Width" />
⬆️ Client request� Viewport-Width: 460� Width: 230
Confidential + Proprietary
Migrate User-Agent data to Client Hints for a�cleaner, active method of obtaining the same information.
Confidential + Proprietary
Confidential + Proprietary
User-Agent Client Hints
⬆️ Initial client request� Sec-CH-UA: " Not;A Brand";v="99", "Google Chrome";v="91", "Chromium";v="91"� Sec-CH-UA-Mobile: ?0� Sec-CH-UA-Platform: "Linux"
⬇️ Server response� Accept-CH: Sec-CH-UA-Full-Version
⬆️ Client request� Sec-CH-UA: " Not;A Brand";v="99", "Google Chrome";v="91", "Chromium";v="91"� Sec-CH-UA-Mobile: ?0� Sec-CH-UA-Platform: "Linux"� Sec-CH-UA-Full-Version: "91.0.4469.4"
Confidential + Proprietary
Available hints - Sec-CH-UA-*
Confidential + Proprietary
Confidential + Proprietary
Accept-CH cache
The browser will continue to send the hints requested by the last Accept-CH header until:
Confidential + Proprietary
Client Hints on cross-origin requests
⬇️ Response from example.com� Accept-CH: Sec-CH-UA-Model, DPR� Permissions-Policy: ch-ua-model=(self "https://downloads.example.com"),� ch-dpr (self "img.example.com")
⬆️ Request to downloads.example.com� Sec-CH-UA-Model: "Pixel 5"
⬆️ Requests to img.example.com� DPR: 2
Confidential + Proprietary
Confidential + Proprietary
What if I need all the user-agent data on first load?
Confidential + Proprietary
What if I need all the user-agent data on first load?
😽
Confidential + Proprietary
Things that are not the first request
Confidential + Proprietary
If you really need specific user-agent data on first load
⬆️ Initial client request� Sec-CH-UA: " Not;A Brand";v="99", "Google Chrome";v="91", "Chromium";v="91"� Sec-CH-UA-Mobile: ?1� Sec-CH-UA-Platform: "Android"
⬇️ Server response� Accept-CH: Sec-CH-UA-Platform-Version� Critical-CH: Sec-CH-UA-Platform-Version
⬆️ Client retries same request� Sec-CH-UA: " Not;A Brand";v="99", "Google Chrome";v="91", "Chromium";v="91"� Sec-CH-UA-Mobile: ?1� Sec-CH-UA-Platform: "Android"� Sec-CH-UA-Platform-Version: "11"
Confidential + Proprietary
Confidential + Proprietary
Avoiding the round trip with Application-Layer Protocol Settings
ClientHello� + alps
ServerHello�EncryptedExtensions�+ alps=(https://example.com, Sec-CH-UA-Platform-Version)�…�Finished
Finished� GET / HTTP/2.0� Host: example.com� Sec-CH-UA-Platform-Version: 11
HTTP/2.0 200 OK�Vary: Sec-CH-UA-Platform-Version�Accept-CH: Sec-CH-UA-Platform-Version�Critical-CH: Sec-CH-UA-Platform-Version
Confidential + Proprietary
Confidential + Proprietary
Confidential + Proprietary
DevTools Issues:�user-agent-client-hints.glitch.me/
Confidential + Proprietary
Literally do nothing option
Confidential + Proprietary
Front-end option
if (navigator.userAgentData) {
// use new hints
} else {
// fall back to user-agent string parsing
}
Confidential + Proprietary
Server-side static header option
Confidential + Proprietary
Hints needed on first request option
Confidential + Proprietary
Dynamic requirements option
Confidential + Proprietary
Using third-party libraries option
Confidential + Proprietary
Retrofill option - please don't
Confidential + Proprietary