Determining OS Platform Version

In general, you should not care what Operating System visitors are using to visit your website. If you attempt to be clever, you will often get it wrong and cause problems that are an annoyance for users and a hassle for me to debug.

So avoid trying to be nosy/clever if at all possible.

That being said, some websites want to be able to distinguish Windows versions for whatever reason; I’m an engineer, not a cop.

The typical path to get this information from Windows-based browsers is to look at the dreaded User-Agent string, a wretched hive of lies, scum, and villainy.

However, this approach falls down with Windows 11, which reports itself as Windows NT 10.0 (almost certainly for compatibility reasons); in general, browsers are moving toward freezing and reducing the User-Agent string to limit passive fingerprinting. The modern mechanism for learning more information about the client is called Client Hints.

If you want to be able to distinguish between Windows 10 and Windows 11, starting around October 2021 in Microsoft Edge 95 (and v95 of most Chromium browsers), the Sec-Ch-UA-Platform-Version Client Hint is the way to go.

Available for request in v95+, this value will indicate the UniversalApiContract “API Level” of the Windows platform. The mapping of values to Windows version is:

Windows VersionSec-CH-UA-Platform-Version
Windows 7 | 8 | 8.10.0.0
Windows 10 15071.0.0
Windows 10 15112.0.0
Windows 10 16073.0.0
Windows 10 17034.0.0
Windows 10 17095.0.0
Windows 10 18036.0.0
Windows 10 18097.0.0
Windows 10 1903 | 19098.0.0
Windows 10 2004 | 20H2 | 21H110.0.0
Windows 11 Previews13.0.0 | 14.0.0
Windows 11 Release | 2022 SV215.0.0

You can request this Client Hint from JavaScript thusly:

navigator.userAgentData.getHighEntropyValues(['platformVersion'])
.then(uapv => { console.log(uapv.platformVersion); });

Note that the userAgentData API requires that your page be a secure context (Served by ~https or on localhost).

Or you can request it be sent to your server as a HTTP request header on subsequent requests by sending a response header:

Response.AddHeader("Accept-CH", "Sec-CH-UA-Platform-Version");
Response.AddHeader("Accept-CH-Lifetime", "86400");

As you may have noticed, the 0.0.0 value is shared across all pre-Windows 10 versions of Windows, so you’ll need to continue to use the User-Agent to distinguish between Windows 7, 8.0, and 8.1 platforms (starting in v107, you will need Client Hints, because the UA string will lie and claim 10.0 even on earlier Windows).

As far as I know, Firefox does not plan to implement this Client Hint.

Bonus: Platform Architecture and Bitness

Distributors of native applications often would like to know the bitness and architecture of the client platform to ensure that they serve the correct installer for their native application (e.g. sending an ARM64-native app to a device like the Surface Pro X running Windows on ARM). The sec-ch-ua-bitness and sec-ch-ua-arch hints are useful for this purpose. Official Documentation

Unfortunately, there’s presently a bug in Chromium whereby ARM64 devices will return x86 as the architecture. UPDATE: Fixed in v98.

The legacy Edge-proprietary window.external.getHostEnvironmentValue("os-architecture") API returns the truth {"os-architecture":"ARM64"}, but this API is non-standard and you should not use it.

-Eric

PS: Native client apps should generally not check the registry key directly, instead it should query the appropriate “Is this API level supported?? API. HKLM\SOFTWARE\Microsoft\WindowsRuntime\WellKnownContracts\Windows.Foundation.UniversalApiContract

Published by ericlaw

Impatient optimist. Dad. Author/speaker. Created Fiddler & SlickRun. PM @ Microsoft 2001-2012, and 2018-, working on Office, IE, and Edge. Now a GPM for Microsoft Defender. My words are my own, I do not speak for any other entity.

One thought on “Determining OS Platform Version

  1. The data in table seems to be slightly misleading, as I’m getting 14.0.0 on a GA version of Windows 11 (10.0.22000.348).

Leave a comment