There are various versions of HTTP; a really old browser will only support HTTP/1.0, while newer once, depending on their age, will support HTTP/1.1, HTTP/2, or HTTP/3.
See also https://superuser.com/questions/1659248/how-does-browser-know-which-version-of-http-it-should-use-when-sending-a-request for some more information.
So depending on how fullstack you want to go, you can use that information to detect really old browsers. If the initial request from the browser is GET / HTTP/1.0
, it's probably ancient; if it sends at least GET / HTTP/1.1
, it's at least somewhat newer. Unfortunately, this won't work with stuff that's newer, as HTTP/2 always wants TLS.
Also, you could have your response set a cookie and include a css
link. Really old browsers won't read the css, so the fact that the css
gets read means at least some support for it. At that point, the HTML is already sent, so it might be too late for your landing page, but you could use the information in following pages. (This also means that people using text-based browsers like lynx, or people automating things with curl, will get the non-css-version, which is probably beneficial in this context).
But be aware that none of this is foolproof. The user might use a proxy, use HTTP/1.0 between the browser and the proxy, but something newer between proxy and your site. The user might be behind some "web accelerator" that evaluates and downloads links itself even before the browser starts reading the page, so the accelerator reads the css even if the browser doesn't. If you really want to make sure a netscape 1.0 user can access the downgraded HTML, it's probably best to provide a link to it that can be used even if the rest of the site looks like gibberish.