How to ping IP addresses using JavaScript

78,445

Solution 1

You can't do this from JS. What you could do is this:

 client --AJAX-- yourserver --ICMP ping-- targetservers

Make an AJAX request to your server, which will then ping the target servers for you, and return the result in the AJAX result.

Possible caveats:

  • this tells you whether the target servers are pingable from your server, not from the user's client
    • so the client won't be able to test hosts its LAN
    • but you shouldn't let the host check hosts on the server's internal network, if any exist
    • some hosts may block traffic from certain hosts and not others
  • you need to limit the ping count per machine:
    • to avoid the AJAX request from timing out
    • some site operators can get very upset when you keep pinging their sites all the time
  • resources
    • long-running HTTP requests could run into maximum connection limit of your server, check how high it is
    • many users trying to ping at once might generate suspicious-looking traffic (all ICMP and nothing else)
  • concurrency - you may wish to pool/cache the up/down status for a few seconds at least, so that multiple clients wishing to ping the same target won't launch a flood of pings

Solution 2

The only method I can think of is loading e.g. an image file from the external server. When that load fails, you "know" the server isn't responding (you actually don't know, because the server could just be blocking you).

Take a look at this example code to see what I mean:

 /*note that this is not an ICMP ping - but a simple HTTP request
    giving you an idea what you could do . In this simple implementation it has flaws
    as Piskvor correctly points out below */
    function ping(extServer){
     var ImageObject = new Image();
     ImageObject.src = "http://"+extServer+"/URL/to-a-known-image.jpg"; //e.g. logo -- mind the caching, maybe use a dynamic querystring
     if(ImageObject.height>0){
       alert("Ping worked!");
     } else {
       alert("Ping failed :(");
     }

}

Solution 3

I was inspired by the latest comment, so I wrote this quick piece of code.

This is a kind of "HTTP ping" which I think can be quite useful to use along with XMLHttpRequest calls(), for instance to figure out which is the fastest server to use in some case or to collect some rough statistics from the user's internet connexion speed.

This small function is just connecting to an HTTP server on an non-existing URL (that is expected to return a 404), then is measuring the time until the server is answering to the HTTP request, and is doing an average on the cumulated time and the number of iterations.

The requested URL is modified randomely at each call since I've noticed that (probably) some transparent proxies or caching mechanisms where faking results in some cases, giving extra fast answers (faster than ICMP actually which somewhat weird).

Beware to use FQDNs that fit a real HTTP server! Results will display to a body element with id "result", for instance:

<div id="result"></div>

Function code:

function http_ping(fqdn) {

var NB_ITERATIONS = 4; // number of loop iterations
var MAX_ITERATIONS = 5; // beware: the number of simultaneous XMLHttpRequest is limited by the browser!
var TIME_PERIOD = 1000; // 1000 ms between each ping
var i = 0;
var over_flag = 0;
var time_cumul = 0;
var REQUEST_TIMEOUT = 9000;
var TIMEOUT_ERROR = 0;

document.getElementById('result').innerHTML = "HTTP ping for " + fqdn + "</br>";

var ping_loop = setInterval(function() {


        // let's change non-existent URL each time to avoid possible side effect with web proxy-cache software on the line
        url = "http://" + fqdn + "/a30Fkezt_77" + Math.random().toString(36).substring(7);

        if (i < MAX_ITERATIONS) {

            var ping = new XMLHttpRequest();

            i++;
            ping.seq = i;
            over_flag++;

            ping.date1 = Date.now();

            ping.timeout = REQUEST_TIMEOUT; // it could happen that the request takes a very long time

            ping.onreadystatechange = function() { // the request has returned something, let's log it (starting after the first one)

                if (ping.readyState == 4 && TIMEOUT_ERROR == 0) {

                    over_flag--;

                    if (ping.seq > 1) {
                        delta_time = Date.now() - ping.date1;
                        time_cumul += delta_time;
                        document.getElementById('result').innerHTML += "</br>http_seq=" + (ping.seq-1) + " time=" + delta_time + " ms</br>";
                    }
                }
            }


            ping.ontimeout = function() {
                TIMEOUT_ERROR = 1;
            }

            ping.open("GET", url, true);
            ping.send();

        }

        if ((i > NB_ITERATIONS) && (over_flag < 1)) { // all requests are passed and have returned

            clearInterval(ping_loop);
            var avg_time = Math.round(time_cumul / (i - 1));
            document.getElementById('result').innerHTML += "</br> Average ping latency on " + (i-1) + " iterations: " + avg_time + "ms </br>";

        }

        if (TIMEOUT_ERROR == 1) { // timeout: data cannot be accurate

            clearInterval(ping_loop);
            document.getElementById('result').innerHTML += "<br/> THERE WAS A TIMEOUT ERROR <br/>";
            return;

        }

    }, TIME_PERIOD);
}

For instance, launch with:

fp = new http_ping("www.linux.com.au"); 

Note that I couldn't find a simple corelation between result figures from this script and the ICMP ping on the corresponding same servers, though HTTP response time seems to be roughly-exponential from ICMP response time. This may be explained by the amount of data that is transfered through the HTTP request which can vary depending on the web server flavour and configuration, obviously the speed of the server itself and probably other reasons.

This is not very good code but I thought it could help and possibly inspire others.

Solution 4

The closest you're going to get to a ping in JS is using AJAX, and retrieving the readystates, status, and headers. Something like this:

url = "<whatever you want to ping>"
ping = new XMLHttpRequest();    
ping.onreadystatechange = function(){

    document.body.innerHTML += "</br>" + ping.readyState;

    if(ping.readyState == 4){
        if(ping.status == 200){
            result = ping.getAllResponseHeaders();
            document.body.innerHTML += "</br>" + result + "</br>";
        }
    }

}
ping.open("GET", url, true);    
ping.send();

Of course you can also put conditions in for different http statuses, and make the output display however you want with descriptions etc, to make it look nicer. More of an http url status checker than a ping, but same idea really. You can always loop it a few times to make it feel more like a ping for you too :)

Solution 5

I've come up with something cause I was bored of searching hours after hours for something that everyone is saying "impossible", only thing I've found was using jQuery. I've came up with a new simple way using Vanilla JS (nothing else than base JavaScript).

Here's my JSFiddle: https://jsfiddle.net/TheNolle/5qjpmrxg/74/

Basically, I create a variable called "start" which I give the timestamp, then I try to set an invisible image's source to my website (which isn't an image) [can be changed to any website], because it's not an image it creates an error, which I use to execute the second part of the code, at this time i create a new variable called "end" which i give the timestamp from here (which is different from "start"). Afterward, I simply make a substraction (i substract "start" from "end") which gives me the latency that it took to ping this website. After you have the choice you can store that in a value, paste it on your webpage, paste it in the console, etc.

let pingSpan = document.getElementById('pingSpan');
// Remove all the way to ...
let run;

function start() {
  run = true;
  pingTest();
}

function stop() {
  run = false;
  setTimeout(() => {
    pingSpan.innerHTML = "Stopped !";
  }, 500);
}

// ... here

function pingTest() {
  if (run == true) { //Remove line
    let pinger = document.getElementById('pingTester');
    let start = new Date().getTime();
    pinger.setAttribute('src', 'https://www.google.com/');
    pinger.onerror = () => {
      let end = new Date().getTime();
      // Change to whatever you want it to be, I've made it so it displays on the page directly, do whatever you want but keep the "end - start + 'ms'"
      pingSpan.innerHTML = end - start + "ms";
    }
    setTimeout(() => {
      pingTest();
    }, 1000);
  } // Remove this line too
}
body {
  background: #1A1A1A;
  color: white
}

img {
  display: none
}
Ping:
<el id="pingSpan">Waiting</el>
<img id="pingTester">

<br> <br>

<button onclick="start()">
  Start Ping Test
</button>
<button onclick="stop()">
  Stop
</button>
Share:
78,445

Related videos on Youtube

user434885
Author by

user434885

Updated on August 04, 2021

Comments

  • user434885
    user434885 almost 3 years

    I want to run a JavaScript code to ping 4 different IP addresses and then retrieve the packet loss and latency of these ping requests and display them on the page.

    How do I do this?

  • Piskvor left the building
    Piskvor left the building over 13 years
    That's not ping, that's an HTTP request (therefore TCP/IP). Also, if the target doesn't run an HTTP server, the request will take a loooong time to time out; plus, the loading is asynchronous - unless the image is already in cache, ImageObject.height will return 0 if you check it right after setting the src; and if it is in cache, it will return "Ping worked", whether the target is up or not. en.wikipedia.org/wiki/Ping
  • Dennis G
    Dennis G over 13 years
    Relax Piskvor - you are perfectly correct that this is not a REAL ping (neither is your solution) - you would need to be able to open sockets and send arbitrary TCP/IP packets to simulate a ping - I just called the method ping for simplicity. You are also correct that if the target doesn't run an HTTP server it will take a long time - hence I wrote "URL to a known image"... Also caching is an issue. This was a simple demonstration of an approach you could take, same principle as CSS history hacks. Thanks for the downvote.
  • Piskvor left the building
    Piskvor left the building over 13 years
    Don't take the downvote personally, I didn't downvote you; I just felt that it doesn't really answer the question - although it is a simple way of checking if a known HTTP server might be up, it doesn't really answer the ping loss or latency. I agree that my approach is not pinging from the client's computer, that would require a lot of lowered permissions and many security holes (and ActiveX).
  • Dennis G
    Dennis G over 13 years
    Not taking it personally :-) Thanks for the follow-up
  • fny
    fny over 11 years
    Warning: The above will cache. Be sure to append something unique to the end of the URL. Also, a lone IP/Domain will work just as well for the image src: "http://" + ipOrHost + "?pingedat=" + new Date().getTime();.
  • mulllhausen
    mulllhausen almost 9 years
    this will not send the icmp packet
  • Mike Causer
    Mike Causer over 7 years
    This will check if a server responds to a request, such as a http request. A ping is a completely different thing.
  • Ibrahim İnce
    Ibrahim İnce over 7 years
    Ide of using AJAX and retrieving the ready states is works for me. May I please ask how can I add a else statemen in this content. Like if the url is not available I would like to print a massage to user. Like document.getElementById("div").innerHTML = "Ping is not success!";
  • Jeffrey Tackett
    Jeffrey Tackett almost 7 years
    Down voting this answer doesn't make sense. The question was how to ping using Javascript, and the link shows you how to effectively ping using Javascript. Not sure what else someone could expect. Thanks for the rep subtraction though, much appreciated. Wow.