Published: October 21, 2021
It's not possible to use the User Agent HTTP Header to detect browsers on Windows 11 accessing your website. The Chromium and Firefox developers have announced that they are "freezing" the Windows version fragment at Windows NT 10.0 and that their browsers will not be sending "Windows NT 11.0" or similar fragments to indicate that the browser is running on Windows 11.
As such, in order to detect browsers running on Windows 11 accessing your website, its necessary to instead look at the Client Hints headers. At the moment only Chromium based browsers send Client Hints headers, so for now, it's not possible for websites to detect Windows 11 on Firefox.
Even if your visitor's web browser has the ability to send Client Hints headers, it still won't send all of them by default. So it's necessary for your server to specifically request the Client Hints that reveal the version number of Windows from your visitors. To do this, you need to make sure that any page you want to detect Windows 11 on includes the accept-ch HTTP Response header.
How your website does this will depend on the platform/software that your website is built with, but the end result is that the HTTP Request to your site will be returned along with a HTTP Response Header called accept-ch that contains a comma-seperated list of Client Hints headers you want your visitor to send in their subsequent requests.
Since this guide is about detecting Windows 11, you'll need to ask your visitors for:
If you use very straight forward PHP, requesting client hints from your visitors is as easy as adding:
at any point in the request processing before PHP has started "outputting" the response. In other words, do it early in the request processing. Read more: PHP: header function.
If you use a PHP framework (such as Symfony or Laravel, you should follow their documentation to see the best way to do it.
If you use the fantastic Django Python framework (like we do!), requesting Client Hints from your visitors is easy with a simple bit of Middleware.
You can create and activate a simple middleware class like this:
This will cause every response from your website to include the response header accept-ch, which tells your visitor's browsers to send those Client Hints headers when they make a request to your site. Read more: Django Middleware.
Other web frameworks and languages will have similar approaches.
Adding the accept-ch header to your site responses causes those Client Hints headers to be sent in subsequent requests by browsers which are capable of sending Client Hints. So next you need to look at the headers in those requests.
The requests to your site will now contain the extra HTTP headers you requested: the Sec-Ch-Ua-Platform and Sec-Ch-Ua-Platform-Version request headers that you specified. These two headers will give you an idea of what Operating System the visitor to your website is using.
Start by inspecting the Sec-Ch-Ua-Platform request header to check for "Windows". If the request header contains that string, then the browser appears to be Microsoft Windows.
Note that the header value itself will have the leading and closing quotation marks. This is expected behaviour, defined by the Structured Field Values for HTTP RFC.
Once you have determined their Client Hint indicates they're using Microsoft Windows, to check for Windows 11 look at the Sec-Ch-Ua-Platform-Version request header for the value "14.0.0".
Now since we're looking for Windows 11, you may be asking why you need to look for 14! This is because the Platform Version value for Windows based browsers comes from the underlying "Windows.Foundation.UniversalApiContract" string, which for Windows 11 is 14.0.0.
The ua-client-hints issue ticket (Ticket: 220) actually states that to detect Windows 11, you should look for a Platform Version value of 13 or higher. In our experience we've only observed Chromium Based browsers on Windows 11 sending Platform Version numbers of "14.0.0" but it's a good idea to follow the spec and check for 13 or greater. There was a short period of time that we observed Edge 95 on Windows 11 sending its Platform Version as 15.0.0, but it doesn't seem to do it any more. Edge "95.0.1020.9" did this, Edge "95.0.1020.20" does not.
Your website is sending the right HTTP Response headers, your visitors are including Client Hints in their requests, and your code is able to identify browsers on Windows 11. Success!
If there's anything that's not clear in this guide, just let me know and I'll clarify it.