How to get JSON from external URL using JavaScript (jQuery) Ajax?

I want to get some JSON content from a URL using JavaScript (jQuery) Ajax, but it’s always failing to load the data.

My code is very simple:

<div id="content">
loading...
</div>
console.log("jQuery Version: " + jQuery.fn.jquery);

$.ajax({
    type: "GET",
    url: "https://www.teamspeak.com/versions/server.json",
    dataType: "json",
    success: function(data){
    $("#content").html(data);
        console.log("SUCCESS: " + JSON.stringify(data));
    },
    error: function(data){
        $("#content").html("Failed to load data. " + JSON.stringify(data));
        console.log("ERROR: " + JSON.stringify(data));
    },
    complete: function(data){
        console.log("COMPLETED: " + JSON.stringify(data));
    },
});

The page is always showing this content:

Failed to load data. {"readyState":0,"status":0,"statusText":"error"}

When I try dataType: "jsonp" (with the P) instead of dataType: "json", then it’s showing this content:

Failed to load data. {"readyState":4,"status":200,"statusText":"load"}

So… It was successful, but it’s still loading? I don’t get it. When I open the above mentioned URL in my browser, I can see application/json formatted data.

Check the result of the code here: https://jsfiddle.net/j2t91osz/1/

Answer

You are unable to complete the call because you are making a request to a URL that is at a host address (www.teamspeak.com) that is different from the one the HTML page is deployed at (jsfiddle.net).

Have a look at the message displayed in the console:

Access to XMLHttpRequest at ‘https://www.teamspeak.com/versions/client.json’ from origin ‘https://fiddle.jshell.net’ has been blocked by CORS policy: No ‘Access-Control-Allow-Origin’ header is present on the requested resource.

When this happens (different hosts), your request is subject to the same-origin policy. In this scenario, the browser will only allow the request to complete if the response contains some specific headers (e.g. Access-Control-Allow-Origin) authorizing the call. More details here.

How to make it work?

  • If you have access to the server, you can configure it to return the necessary headers. (Each server/language has a way to do that – check some solutions here.)
  • If you don’t control the server, you can mirror it (through tools such as reverse proxies, or via a very simple app that just forwards the call) and include all the necessary headers there.
  • For demo purposes, you could also use a free CORS proxy such as https://allorigins.win/. See demo: https://jsfiddle.net/acdcjunior/rc14skf8/ (just don’t use it in production, since they will be able to inspect all of your traffic, you can’t count on their availability and many other issues)