Here are two pages, test.php and testserver.php.

test.php

<script src="scripts/jq.js" type="text/javascript"></script>
<script>
    $(function() {
        $.ajax({url:"testserver.php",
            success:function() {
                alert("Success");
            },
            error:function() {
                alert("Error");
            },
            dataType:"json",
            type:"get"
        }
    )})
</script>

testserver.php

<?php
$arr = array("element1",
             "element2",
             array("element31","element32"));
$arr['name'] = "response";
echo json_encode($arr);
?>

Now my problem: when both of these files are on the same server (either localhost or web server), it works and alert("Success") is called; If it is on different servers, meaning testserver.php on web server and test.php on localhost, its not working, and alert("Error") is executing. Even if the URL inside ajax is changed to http://domain.com/path/to/file/testserver.php

35 upvote
  flag
For people stopping by. Read this to have an idea how cross domain javascript calls work //allinonescript.com/a/11736771/228656 – Abdul Munim
1 upvote
  flag
I wrote an answer for this question here: Loading cross domain html page with jQuery AJAXthe last one, supports https – jherax

13 Answers 11

You need to have a look at Same Origin Policy:

In computing, the same origin policy is an important security concept for a number of browser-side programming languages, such as JavaScript. The policy permits scripts running on pages originating from the same site to access each other's methods and properties with no specific restrictions, but prevents access to most methods and properties across pages on different sites.

For you to be able to get data, it has to be:

Same protocol and host

You need to implement JSONP to workaround it.

upvote
  flag
Can I get a working example using jsonp? – Aviator

Browser security prevents making an ajax call from a page hosted on one domain to a page hosted on a different domain; this is called the "same-origin policy".

up vote 379 down vote accepted

Use JSONP.

jQuery:

$.ajax({
     url:"testserver.php",
     dataType: 'jsonp', // Notice! JSONP <-- P (lowercase)
     success:function(json){
         // do stuff with json (in this case an array)
         alert("Success");
     },
     error:function(){
         alert("Error");
     }      
});

PHP:

<?php
$arr = array("element1","element2",array("element31","element32"));
$arr['name'] = "response";
echo $_GET['callback']."(".json_encode($arr).");";
?>

The echo might be wrong, it's been a while since I've used php. In any case you need to output callbackName('jsonString') notice the quotes. jQuery will pass it's own callback name, so you need to get that from the GET params.

And as Stefan Kendall posted, $.getJSON() is a shorthand method, but then you need to append 'callback=?' to the url as GET parameter (yes, value is ?, jQuery replaces this with its own generated callback method).

1 upvote
  flag
Why do you need to return callbackName('/* json */') instead of callbackName(/* json */)? – Eric
2 upvote
  flag
@eric the callback expects a JSON string. Theoretically, an object might work as well, but not sure how jQuery responds to this, it might throw an error or fail silently. – BGerrissen
upvote
  flag
And don't forget to add http:// or https:// in the beginning of the request. – Sanket Sahu
upvote
  flag
I'm getting the following error. SyntaxError: missing ; before statement {"ResultCode":2}. Where {"ResultCode":2} is response. Please advice. – user2003356
upvote
  flag
@user2003356 looks like you are returning plain JSON instead of JSONP. You need to return something like: callbackFunction({"ResultCode":2}). jQuery adds the GET parameter 'callback' to the request, that's the name of the callback function jquery uses and should be added to the response. – BGerrissen
upvote
  flag
The comma at the end of error: function(){...}, appears to cause an error. I'd take it out but edits must be 6 characters. so. that's good. – user1566694
upvote
  flag
The explanation given by @BGerrissen worked well for me after adding crossDomain: true, from the docs, " crossDomain (default: false for same-domain requests, true for cross-domain requests) Type: Boolean If you wish to force a crossDomain request (such as JSONP) on the same domain, set the value of crossDomain to true. This allows, for example, server-side redirection to another domain. (version added: 1.5) " – srj
upvote
  flag
There is jsonp.jit.su it's a free JSON Proxy "Enables cross-domain requests to any JSON API." And it's on Github github.com/afeld/jsonp – Joël
upvote
  flag
It's 2016. CORS is now a widely supported standard, as opposed to JSONP which can only be described as a hack. @joshuarh's answer below should be the preferred one now. – Vicky Chijwani
upvote
  flag
why is it necessary to get the callback method in server? – Sudip Bhandari

From the Jquery docs (link):

  • Due to browser security restrictions, most "Ajax" requests are subject to the same origin policy; the request can not successfully retrieve data from a different domain, subdomain, or protocol.

  • Script and JSONP requests are not subject to the same origin policy restrictions.

So I would take it that you need to use jsonp for the request. But haven't tried this myself.

This is possible, but you need to use JSONP, not JSON. Stefan's link pointed you in the right direction. The jQuery AJAX page has more information on JSONP.

Remy Sharp has a detailed example using PHP.

upvote
  flag
Yes, Stefan sir's link, I am studying that.... Thanks a lot for you all... – Firose Hussain

JSONP is a good option, but there is an easier way. You can simply set the Access-Control-Allow-Origin header on your server. Setting it to * will accept cross-domain AJAX requests from any domain. (https://developer.mozilla.org/en/http_access_control)

The method to do this will vary from language to language, of course. Here it is in Rails:

class HelloController < ApplicationController
  def say_hello
    headers['Access-Control-Allow-Origin'] = "*"
    render text: "hello!"
  end
end

In this example, the say_hello action will accept AJAX requests from any domain and return a response of "hello!".

Here is an example of the headers it might return:

HTTP/1.1 200 OK 
Access-Control-Allow-Origin: *
Cache-Control: no-cache, no-store, max-age=0, must-revalidate
Content-Type: text/html; charset=utf-8
X-Ua-Compatible: IE=Edge
Etag: "c4ca4238a0b923820dcc509a6f75849b"
X-Runtime: 0.913606
Content-Length: 6
Server: WEBrick/1.3.1 (Ruby/1.9.2/2011-07-09)
Date: Thu, 01 Mar 2012 20:44:28 GMT
Connection: Keep-Alive

Easy as it is, it does have some browser limitations. See http://caniuse.com/#feat=cors.

12 upvote
  flag
Jsonp did not support post, put and delete. Your solution works great. – TonyTakeshi
32 upvote
  flag
in PHP header("Access-Control-Allow-Origin: *"); – SparK
upvote
  flag
@SparK This code is fine when am using xmlhttpRequest.But not working when am using jquery.Post... – Warrior
8 upvote
  flag
@Warrior If you're using jQuery's .post() method you have to enable cross-domain support in jQuery. It is done with this: $.support.cors = true. – Friederike
3 upvote
  flag
FYI - the official name for this is 'CORS' (Cross Origin Resource Sharing). More info: en.wikipedia.org/wiki/Cross-origin_resource_sharing – Dan Esparza
upvote
  flag
easy peasy! thanks fellas – Kristian
5 upvote
  flag
It's just lazy to not whitelist particular domains and instead allow access from all domains... – Jasper
19 upvote
  flag
What are the security implications of configuring a server in this manner? – Jon Schneider
4 upvote
  flag
@JonSchneider the problem with this approach (just allowing any origin with *) is that any malicious page can capture the user's information on that server. Gmail had this problem once. It was inadvertently disclosing the user's contacts list. – Sebastián Grignoli
13 upvote
  flag
It would be better to allow only those domains that you want to share the data with instead of using the wilcard "*". – Sebastián Grignoli

I use Apache server, so I've used mod_proxy module. Enable modules:

LoadModule proxy_module modules/mod_proxy.so
LoadModule proxy_http_module modules/mod_proxy_http.so

Then add:

ProxyPass /your-proxy-url/ http://service-url:serviceport/

Finally, pass proxy-url to your script.

I had to load webpage from local disk "file:///C:/test/htmlpage.html", call "http://localhost/getxml.php" url, and do this in IE8+ and Firefox12+ browsers, use jQuery v1.7.2 lib to minimize boilerplate code. After reading dozens of articles finally figured it out. Here is my summary.

  • server script (.php, .jsp, ...) must return http response header Access-Control-Allow-Origin: *
  • before using jQuery ajax set this flag in javascript: jQuery.support.cors = true;
  • you may set flag once or everytime before using jQuery ajax function
  • now I can read .xml document in IE and Firefox. Other browsers I did not test.
  • response document can be plain/text, xml, json or anything else

Here is an example jQuery ajax call with some debug sysouts.

jQuery.support.cors = true;
$.ajax({
    url: "http://localhost/getxml.php",
    data: { "id":"doc1", "rows":"100" },
    type: "GET",
    timeout: 30000,
    dataType: "text", // "xml", "json"
    success: function(data) {
        // show text reply as-is (debug)
        alert(data);

        // show xml field values (debug)
        //alert( $(data).find("title").text() );

        // loop JSON array (debug)
        //var str="";
        //$.each(data.items, function(i,item) {
        //  str += item.title + "\n";
        //});
        //alert(str);
    },
    error: function(jqXHR, textStatus, ex) {
        alert(textStatus + "," + ex + "," + jqXHR.responseText);
    }
});
1 upvote
  flag
I wrote an answer for this question here: Loading cross domain html page with jQuery AJAXthe last one, supports https – jherax
upvote
  flag
For the firest point: in PHP add this line to the script: header("Access-Control-Allow-Origin: *"); – T30

There are few examples for using JSONP which include error handling.

However, please note that the error-event is not triggered when using JSONP! See: http://api.jquery.com/jQuery.ajax/ or jQuery ajax request using jsonp error

It is true that the same-origin policy prevents JavaScript from making requests across domains, but the CORS specification allows just the sort of API access you are looking for, and is supported by the current batch of major browsers.

See how to enable cross-origin resource sharing for client and server:

http://enable-cors.org/

"Cross-Origin Resource Sharing (CORS) is a specification that enables truly open access across domain-boundaries. If you serve public content, please consider using CORS to open it up for universal JavaScript/browser access."

You can control this via HTTP header by adding Access-Control-Allow-Origin. Setting it to * will accept cross-domain AJAX requests from any domain.

Using PHP it's really simple, just add the following line into the script that you want to have access outside from your domain:

header("Access-Control-Allow-Origin: *");

Don't forget to enable mod_headers module in httpd.conf.

For cross origin AJAX requests, use the following jQuery plugin. https://github.com/jinujd/jQuery-Async-Form It works asynchronously, without reloading. It is not AJAX, but it does the task in most cases

upvote
  flag
Tried to request translate.google.ru . Got following error(firefox): Load denied by X-Frame-Options: translate.google.ru does not permit framing. Error: Permission denied to access property "document" – Eugene
upvote
  flag
Yes..Its a hack..Contributions invited..onLoadFinished wont work in most cases – Jinu Joseph Daniel

For Microsoft Azure, it's slightly different.

Azure has a special CORS setting that needs to be set. It's essentially the same thing behind the scenes, but simply setting the header joshuarh mentions will not work. The Azure documentation for enabling cross domain can be found here:

https://docs.microsoft.com/en-us/azure/app-service-api/app-service-api-cors-consume-javascript

I fiddled around with this for a few hours before realizing my hosting platform had this special setting.

Not the answer you're looking for? Browse other questions tagged or ask your own question.