[javascript] How to detect internet speed in JavaScript?

It's possible to some extent but won't be really accurate, the idea is load image with a known file size then in its onload event measure how much time passed until that event was triggered, and divide this time in the image file size.

Example can be found here: Calculate speed using javascript

Test case applying the fix suggested there:

_x000D_
_x000D_
//JUST AN EXAMPLE, PLEASE USE YOUR OWN PICTURE!_x000D_
var imageAddr = "http://www.kenrockwell.com/contax/images/g2/examples/31120037-5mb.jpg"; _x000D_
var downloadSize = 4995374; //bytes_x000D_
_x000D_
function ShowProgressMessage(msg) {_x000D_
    if (console) {_x000D_
        if (typeof msg == "string") {_x000D_
            console.log(msg);_x000D_
        } else {_x000D_
            for (var i = 0; i < msg.length; i++) {_x000D_
                console.log(msg[i]);_x000D_
            }_x000D_
        }_x000D_
    }_x000D_
    _x000D_
    var oProgress = document.getElementById("progress");_x000D_
    if (oProgress) {_x000D_
        var actualHTML = (typeof msg == "string") ? msg : msg.join("<br />");_x000D_
        oProgress.innerHTML = actualHTML;_x000D_
    }_x000D_
}_x000D_
_x000D_
function InitiateSpeedDetection() {_x000D_
    ShowProgressMessage("Loading the image, please wait...");_x000D_
    window.setTimeout(MeasureConnectionSpeed, 1);_x000D_
};    _x000D_
_x000D_
if (window.addEventListener) {_x000D_
    window.addEventListener('load', InitiateSpeedDetection, false);_x000D_
} else if (window.attachEvent) {_x000D_
    window.attachEvent('onload', InitiateSpeedDetection);_x000D_
}_x000D_
_x000D_
function MeasureConnectionSpeed() {_x000D_
    var startTime, endTime;_x000D_
    var download = new Image();_x000D_
    download.onload = function () {_x000D_
        endTime = (new Date()).getTime();_x000D_
        showResults();_x000D_
    }_x000D_
    _x000D_
    download.onerror = function (err, msg) {_x000D_
        ShowProgressMessage("Invalid image, or error downloading");_x000D_
    }_x000D_
    _x000D_
    startTime = (new Date()).getTime();_x000D_
    var cacheBuster = "?nnn=" + startTime;_x000D_
    download.src = imageAddr + cacheBuster;_x000D_
    _x000D_
    function showResults() {_x000D_
        var duration = (endTime - startTime) / 1000;_x000D_
        var bitsLoaded = downloadSize * 8;_x000D_
        var speedBps = (bitsLoaded / duration).toFixed(2);_x000D_
        var speedKbps = (speedBps / 1024).toFixed(2);_x000D_
        var speedMbps = (speedKbps / 1024).toFixed(2);_x000D_
        ShowProgressMessage([_x000D_
            "Your connection speed is:", _x000D_
            speedBps + " bps", _x000D_
            speedKbps + " kbps", _x000D_
            speedMbps + " Mbps"_x000D_
        ]);_x000D_
    }_x000D_
}
_x000D_
<h1 id="progress">JavaScript is turned off, or your browser is realllllly slow</h1>
_x000D_
_x000D_
_x000D_

Quick comparison with "real" speed test service showed small difference of 0.12 Mbps when using big picture.

To ensure the integrity of the test, you can run the code with Chrome dev tool throttling enabled and then see if the result matches the limitation. (credit goes to user284130 :))

Important things to keep in mind:

  1. The image being used should be properly optimized and compressed. If it isn't, then default compression on connections by the web server might show speed bigger than it actually is. Another option is using uncompressible file format, e.g. jpg. (thanks Rauli Rajande for pointing this out and Fluxine for reminding me)

  2. The cache buster mechanism described above might not work with some CDN servers, which can be configured to ignore query string parameters, hence better setting cache control headers on the image itself. (thanks orcaman for pointing this out))