Prepare for Client Hints, freezing User Agent

Daybrush (Younkue Choi)
NAVER FE Platform
Published in
5 min readSep 4, 2020

Chrome was planned to freeze userAgent to improve user privacy, and it is being applied as an experimental feature in 84+.

Not only Chrome, but other browsers will come someday.

It is still an experimental feature until Chrome(chromium) 84.
If you want to test, enable the flag below.
chrome://flags/#enable-experimental-web-platform-features
chrome://flags/#freeze-user-agent

Freezing the userAgent means that both the client and the server using the userAgent can be affected. Therefore, you need to prepare for server and client.

For server-related information, please refer to the following article.
https://web.dev/user-agent-client-hints

What I want to talk about in this article is how to deal with the client side.

There are various reasons for using userAgent. Some examples are:

  • Differences in browser behavior.
  • Differences in OS behavior.
  • Difference by mobile.
  • Bugs in specific versions of the OS or browser.

When userAgent the freezing changes as follows

  • the following attribute values will not appear correctly.
    * navigator.userAgent
    * navigator.appVersion
    * navigator.platform
    * navigator.productSub
    * navigator.vendor
  • You should use navigator.userAgentData instead of navigator.userAgent.
    * Browser version only shows major.
    * OS name and version become inaccurate.
    * But OS name, OS version, Browser full version should be fetched asynchronously.

navigator.userAgent can be changed as follows:

  • Galaxy Z Flip, Android 10, Chrome 85.0.4183.81
    Before: Mozila/5.0 (Linux; Android 10; SM-F700N) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/85.0.4183.81 Mobile Safari/537.36
    After: Mozila/5.0 (Linux; Android 9; Unspecified Device) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/85.0.0.0 Mobile Safari/537.36
  • Mac OS X 10.15.4, Chrome Canary 87.0.4243.0
    Before: Mozilla/5.0 (Macintosh; Intel Mac OS X 10_15_4) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/87.0.4243.0 Safari/537.36
    After: Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/87.0.0.0 Safari/537.36

Here, the OS name and version are unknown, but Android can.

https://github.com/chromium/chromium/blob/ce52a06958beedd09141a567aa90c562ac50ffd2/third_party/blink/renderer/core/frame/navigator_id.cc#L67

In fact, you can check Android in chromium and the other OS is changed to Windows.

Use userAgentData instead of userAgent

https://wicg.github.io/ua-client-hints/#interface

When navigator.userAgentData is accessed, there are brands(uaList for chromium < 84), mobile attributes and getHighEntropyValues method.

  • brands is a list of user agents’ commercial names. Also, you can know the engine name through this information.
Chrome Canary 87.0.4243.0
Edge 85.0.564.44
  • mobile: A boolean indicating if the user agent’s device is a mobile device.

From the moment the userAgent is frozen, the OS name and version cannot be known synchronously. Instead, you can get the OS name, version, and ua full version asynchronously through the getHighEntropyValues method.

Mac OS X 10.15.4, Chrome Canary 87.0.4243.0

This is the usage of userAgentData. Why are we researching and preparing?

Because more than 30 million people use our service every day. All of our services use @egjs/agent to get OS or browser information. Also, many components use the agent module. However, if the userAgent suddenly freezes, our service may become paralyzed. If there are many users, it will be a big blow.

So we need to support client hints in @egjs/agent. However, in many services, userAgent is used synchronously or constant as shown in the code below.

How should we deal with the freezing of the userAgent?

Even if the userAgent is frozen, some can be used as it is now.

Possible when brought synchronously

  • Check browser name, major version
  • Check mobile
  • Check iOS, Android
  • Check webkit, chromium
  • Check old OS, OS Version (Chrome 84 support range or less)
    < Android 5.0
    < Mac OS X 10.10
    < Windows 7
    < iOS Unknown

The OS other than Android becomes unclear. But iOS can check. This is because the browser engine of iOS is all webkit. Isn’t it chromium? Is it mobile and webkit? Then it becomes iOS.

chromium has the keywords chrome or chromium. Also, the webkit version does not exceed 537.36.

It is possible to check the old OS version. Browsers have a range of OS support. Android supports versions from 5.0 to 84. iOS safari follows the OS version. Even if there is no support plan for iOS safari yet, there is a wider range of checks than Android.

Impossible when brought synchronously

  • Check OS (Mac with browsers except Safari, Windows), OS version
  • Check Browser full version.

If you fetch asynchronously, it is the same as before.

  • You can get accurate agent information.
  • Check OS(Mac, Windows, Linux), OS version
  • Check Browser full version.

In getAccurateAgent, you can get the OS name, version, and full version of the browser by using the getHighEntropyValues method. If userAgentData is not supported, userAgent is used.

If you dare to use synchronously, you have to choose.

  • You cannot get the OS name and version other than iOS, Android.
  • You can only get the major version of the browser. However, unless there is a serious bug, you will mainly check the major version.
  • Instead, infer to browser, webkit, or chromium
  • It is not possible to know the specific version of OS (ex: Android 7)

Let me give you some examples.

  • Check Mac Safari, iOS all browsers.
    Mac Safari, iOS all browsers are webkit.
  • Check Android version >= 5
    From Android 5, Client Hints are supported, and if the version is -1, the version is high.
  • Check iOS version >= 10
    Like Android, iOS will change to -1 from the version that supports Client Hints.

Prepare now!

Browser vendors have made a notice and will change someday. Be prepared not only on the client but also on the server. There must be a change in the things you don’t know synchronously.

@egjs/agent can get browser information and os information that supports userAgent and userAgentData.

The code and project can be found on GitHub. Please refer to the API document for how to use it.

To use with npm or script, run the following command:

  • npm
npm install @egjs/agent
  • script
<script src="//naver.github.io/egjs-agent/release/latest/dist/agent.min.js"></script>

If you have any questions or requests, feel free to write them down on Github Issues.

Thank you.

--

--