Just got an email pointing towards the "Ultimate client-side JavaScript client sniff. Version 3.03". This is certainly the be-all, end-all of detecting which client is taking a look at your web page, but has much too much overhead for me to ever think about using. It's been around for a while, but I thought I'd blog it.

Here's an example of what I mean. There's a check for Javascript version and also for what kind of OS the client's using. Here's part of the OS check:
var is_aix = (agt.indexOf("aix") !=-1); // IBM
var is_aix1 = (agt.indexOf("aix 1") !=-1);
var is_aix2 = (agt.indexOf("aix 2") !=-1);
var is_aix3 = (agt.indexOf("aix 3") !=-1);
var is_aix4 = (agt.indexOf("aix 4") !=-1);

That is to say, if we're interested in seeing "uplevel content", we're probably using Mozilla. I don't need five checks for OS when it has no bearing on what I'm going to do with my html -- I'm not going to write a different page for AIX. I just don't care what OS we've got (on a practical level). What am I going to do with these vars?

You might say "hack them out", which is exactly what I do, but with these bytes, not a subset of their 14k of bytes (incl whitespace):

if (document.layers) {	// NS 4

// do NS 4x jive
} else if (document.all || document.getElementById) { // IE 5 or DOM1
// do DOM jive
} else { // else we don't support this DOM
// window.close();

A little from my ye ole email reply:
Regardless of this falling into "CLASSIC MISTAKE #2 IN CLIENT DETECTION: CONFUSING OBJECT DETECTION WITH CLIENT DETECTION", it's quite a bit smaller than the 14k crap this bit has. I'm also, for better or worse, not worried about WebTV users or HotJava or Opera. They get whatever's in the "else", which is what lynx users get too, or they get whatever they pretend to be (eg Opera has partial DOM1 -- if their impl stinks, that's their job, I think.)