How can I create a JavaScript page that will detect the user’s internet speed and show it on the page? Something like “your internet speed is ??/?? Kb/s”.
It's better to use images for testing the speed. But if you have to deal with zip files, the below code works.
var fileURL = "your/url/here/testfile.zip";
var request = new XMLHttpRequest();
var avoidCache = "?avoidcache=" + (new Date()).getTime();;
request.open('GET', fileURL + avoidCache, true);
request.responseType = "application/zip";
var startTime = (new Date()).getTime();
var endTime = startTime;
request.onreadystatechange = function () {
if (request.readyState == 2)
{
//ready state 2 is when the request is sent
startTime = (new Date().getTime());
}
if (request.readyState == 4)
{
endTime = (new Date()).getTime();
var downloadSize = request.responseText.length;
var time = (endTime - startTime) / 1000;
var sizeInBits = downloadSize * 8;
var speed = ((sizeInBits / time) / (1024 * 1024)).toFixed(2);
console.log(downloadSize, time, speed);
}
}
request.send();
This will not work very well with files < 10MB. You will have to run aggregated results on multiple download attempts.
As I outline in this other answer here on StackOverflow, you can do this by timing the download of files of various sizes (start small, ramp up if the connection seems to allow it), ensuring through cache headers and such that the file is really being read from the remote server and not being retrieved from cache. This doesn't necessarily require that you have a server of your own (the files could be coming from S3 or similar), but you will need somewhere to get the files from in order to test connection speed.
That said, point-in-time bandwidth tests are notoriously unreliable, being as they are impacted by other items being downloaded in other windows, the speed of your server, links en route, etc., etc. But you can get a rough idea using this sort of technique.
Even though this is old and answered, i´d like to share the solution i made out of it 2020
it comes with the flexibility to run at anytime and run a callback if greater and or smaller the specified mbps
testConnectionSpeed:{
imageAddr : "/app/images/test_connection.jpg" , // you have to adjust this
downloadSize : 31291,// and this must match with file above ;)
run:function(mbps_max,cb_gt,cb_lt){
testConnectionSpeed.mbps_max = parseFloat(mbps_max) ? parseFloat(mbps_max) : 0;
testConnectionSpeed.cb_gt = cb_gt;
testConnectionSpeed.cb_lt = cb_lt;
testConnectionSpeed.InitiateSpeedDetection();
},
InitiateSpeedDetection: function() {
window.setTimeout(testConnectionSpeed.MeasureConnectionSpeed, 1);
},
result:function(){
var duration = (endTime - startTime) / 1000;
var bitsLoaded = testConnectionSpeed.downloadSize * 8;
var speedBps = (bitsLoaded / duration).toFixed(2);
var speedKbps = (speedBps / 1024).toFixed(2);
var speedMbps = (speedKbps / 1024).toFixed(2);
if(speedMbps >= (testConnectionSpeed.max_mbps ? testConnectionSpeed.max_mbps : 1) ){
testConnectionSpeed.cb_gt ? testConnectionSpeed.cb_gt() : false;
}else {
testConnectionSpeed.cb_lt ? testConnectionSpeed.cb_lt() : false;
}
},
MeasureConnectionSpeed:function() {
var download = new Image();
download.onload = function () {
endTime = (new Date()).getTime();
testConnectionSpeed.result();
}
startTime = (new Date()).getTime();
var cacheBuster = "?nnn=" + startTime;
download.src = testConnectionSpeed.imageAddr + cacheBuster;
}
}
you can then start the test anywhere after you included the snippet above by running the testConnectionSpeed.run(mbps, morefunction, lessfunction)
for example:
testConnectionSpeed.run(1.5, function(){console.log(">= 1.5Mbps")}, function(){console.log("< 1.5Mbps")} )
(the larger the image, the more reasonable the test)