Here’s my idea:
Have a tiny, stand-alone JavaScript file that will start up after a page is completely loaded. The script will start a timer, download a file of a known size (let’s say exactly 10KB of gibberish text), then stop the timer.
If the timer determines that it takes exactly 1 second to download the file, does that mean that the user only has 80 kilobits per second downstream at their disposal? Or rather does it mean that it will consistently take them 1 second to download 80 kilobits from my server whether it be an image, a text file, a music file, etc.?
There is a lot going on here. First off, when downloading a file, you have to content with both latency (the amount of time it takes the first downloaded bit to travel across the line) AND the bandwidth (the volume of data that fits in the wire). You also have to contend with the fact that contention and/or routing is fundamentally variable, and as such measurements will vary – perhaps significantly – from time to time.
If you want a decent measure, you will need to try files of several different sizes (10kb, 100kb, 1000kb,, 10000kb, etc.) several times each. With that data (esp. if it is measured at different times) you should be able to estimate the “download speed” by trying to estimate the latency (independent of download size), factoring that out, and looking at the remaining time (for the best, worst, or average cases).
If you keep the request packet small, I’d neglect the delay due to upload. Just make sure you try downloading really big files and you should be OK.