Browser Detect component for Blazor

Browser detect component for Blazor

An year ago I released the Browser detect component for Blazor on NuGet. This is a browser detect component for Blazor WebAssembly and Blazor Server with .NET6. Also, it was downloaded almost 20.000 times and used in quite interesting project. Today, I’m releasing a new update that detect correctly Windows 11 plus few improvements.

Detect Windows 11 and CPU architecture using User-Agent Client Hints

Websites can differentiate between users on Windows 11 and Windows 10, and detect the CPU architecture of the device, by using User-Agent Client Hints (UA-CH). The User-Agent Client Hints format is used by browsers to provide user agent information to websites.

Websites can also use the user agent information that’s sent from the browser to detect information such as:

  • The browser brand.
  • The browser version number.
  • The device platform on which the browser is running.

There are two approaches for sites to access user agent information:

  • User-Agent strings (legacy).
  • User-Agent Client Hints (recommended).

For details about these two approaches, see Detecting Microsoft Edge from your website.

In Microsoft Edge (and also in Google Chrome), sites can differentiate between users on Windows 11 and Windows 10, and can detect the CPU architecture of the device, via User-Agent Client Hints (UA-CH). This information can be found in the following UA-CH request headers:

Header fieldValues that indicate Windows 10Values that indicate Windows 11
Sec-CH-UA-PlatformWindowsWindows
Sec-CH-UA-Platform-Versionvalues between 1.0.0 and 10.0.013.0.0 and above

User-Agent strings won’t be updated to differentiate between Windows 11 and Windows 10, or to differentiate between CPU architectures. We don’t recommend using User-Agent strings to retrieve user agent data. Browsers that don’t support User-Agent Client Hints won’t be able to differentiate between Windows 11 and Windows 10, or between CPU architectures.

Browsers that support User-Agent Client Hints

The following table shows which browsers support differentiating between Windows 11 and Windows 10, and between different CPU architectures.

BrowserSupports differentiation via User-Agent Client Hints?
Microsoft Edge 94+Yes
Chrome 95+Yes
OperaYes
FirefoxNo
Internet Explorer 11No

Sample code for detecting Windows 11

The following code detects Windows 11:

navigator.userAgentData.getHighEntropyValues(["platformVersion"])
 .then(ua => {
   if (navigator.userAgentData.platform === "Windows") {
     const majorPlatformVersion = parseInt(ua.platformVersion.split('.')[0]);
     if (majorPlatformVersion >= 13) {
       console.log("Windows 11 or later");
      }
      else if (majorPlatformVersion > 0) {
        console.log("Windows 10");
      }
      else {
        console.log("Before Windows 10");
      }
   }
   else {
     console.log("Not running on Windows");
   }
 });

Sample code for detecting ARM or x86

Use detection of CPU architecture to have your website automatically download the version of your app that’s built specifically for the user’s CPU.

CPU detection is particularly helpful for ARM-based devices, so that a customer using an ARM device automatically downloads the native ARM version of an application. This prevents the user from inadvertently installing an app that’s built for x86, and then experiencing reduced performance due to emulation.

The following code detects CPU architecture:

navigator.userAgentData.getHighEntropyValues(["architecture","bitness"])
 .then(ua => {
   if (navigator.userAgentData.platform === "Windows") {
     if (ua.architecture === 'x86') {
       if (ua.bitness === '64') {
         console.log("x86_64");
       }
       else if (ua.bitness === '32') {
         console.log("x86");
       }
     }
     else if (ua.architecture === 'arm') {
       if (ua.bitness === '64') {
         console.log("ARM64");
       }
       else if (ua.bitness === '32') {
         console.log("ARM32");
       }
     }
   }
   else {
     console.log("Not running on Windows");
   }
 });

Optimizing detection performance with Critical-CH

Currently, website servers must send the Accept-CH response header to the browser client to request higher entropy fields not sent in the Sec-CH-UA header by default. The following diagram shows the browser sending request headers to the server including user agent: <UA string> and receiving response headers including Accept-CH: sec-ch-ua-platform.

Requests using only Accept-CH header - Browser Detect component for Blazor

During this initial request, the client will record the Accept-CH preferences and on subsequent requests include sec-ch-ua-platform by default.

To further optimize this flow, the new Critical-CH header can be used in addition to the Accept-CH header to reissue the request header immediately, without the need for a page reload. The following diagram shows the browser sending request headers to the server including user agent: <UA string> and receiving response headers including Accept-CH: sec-ch-ua-platform and Critical-CH: sec-ch-ua-platform. The browser then sends request headers to the server immediately.

Requests using Critical-CH and Accept-CH headers - Browser Detect component for Blazor

Starting with Microsoft Edge version 96, you can use the new Critical-CH header to receive desired high entropy headers with optimized performance.

Remember that Critical-CH and Accept-CH preferences persist until session cookies are cleared, or until a user clears site data or cookies for a given origin. For more information about Critical-CH, refer to Client Hint Reliability.

Detecting specific Windows versions

To detect specific versions of Windows, use the following values for platformVersion in User-Agent Client Hints:

VersionplatformVersion
Win7/8/8.10
Win10 15071
Win10 15112
Win10 16073
Win10 17034
Win10 17095
Win10 18036
Win10 18097
Win10 19038
Win10 19098
Win10 200410
Win10 20H210
Win10 21H110
Win10 21H210
Win1113+

Using the component

Now, we can start to use the browser detect component for Blazor.

To detect in a correct way the correct version of the operating system and the architecture of the CPU, the component has to run few tests that take time.

For this reason I added 2 events in the component:

  • WindowsArchitectureUpdate
  • WindowsVersionUpdate

So, if you want to receive the notification when of the correct version of Windows and the CPU architecture, the component is like this code:

<BrowserDetect @bind-BrowserInfo="@Info" 
               WindowsArchitectureUpdate="WindowsArchitectureString"
               WindowsVersionUpdate="WindowsUpdateString" />

then the functions look like

public BrowserInfo? Info { get; set; }
public string? WindowsInfo { get; set; } = "";
public string? WindowsCPUInfoString { get; set; }

private void WindowsArchitectureString(string cpu)
{
    WindowsCPUInfoString = cpu;
}

private void WindowsUpdateString(string version)
{
    WindowsInfo = version;
}

Both events return a simple string with the values. For example:

  • if the operating system is Windows 11, the WindowsUpdateString receives the string 11;
  • if the operating system is Windows 10 1809, the WindowsUpdateString receives the string 10 (1809)
  • if the CPU is 32 bit, the WindowsArchitectureString, receives the string x86
Windows Architecture Values
  • x86_64
  • x86
  • ARM64
  • ARM32
Windows Version
VersionplatformVersion
Win7/8/8.17/8/8.1
Win10 150710 (1507)
Win10 151110 (1511)
Win10 160710 (1607)
Win10 170310 (1703)
Win10 170910 (1709)
Win10 180310 (1803)
Win10 180910 (1809)
Win10 190310 (1903 or 10 1909)
Win10 190910 (1903 or 10 1909)
Win10 200410 (2004 or 20H2 or 21H1 or 21H2)
Win10 20H210 (2004 or 20H2 or 21H1 or 21H2)
Win10 21H110 (2004 or 20H2 or 21H1 or 21H2)
Win10 21H210 (2004 or 20H2 or 21H1 or 21H2)
Win1111

Wrap up

In conclusion, I hope the Browser Detect component for Blazor can help in your projects. If you need help, here some links:

Leave a Reply

This site uses Akismet to reduce spam. Learn how your comment data is processed.