By Drew Noakes


2010-08-29 16:12:40 8 Comments

I'm developing a page that pulls images from Flickr and Panoramio via jQuery's AJAX support.

The Flickr side is working fine, but when I try to $.get(url, callback) from Panoramio, I see an error in Chrome's console:

XMLHttpRequest cannot load http://www.panoramio.com/wapi/data/get_photos?v=1&key=dummykey&tag=test&offset=0&length=20&callback=processImages&minx=-30&miny=0&maxx=0&maxy=150. Origin null is not allowed by Access-Control-Allow-Origin.

If I query that URL from a browser directly it works fine. What is going on, and can I get around this? Am I composing my query incorrectly, or is this something that Panoramio does to hinder what I'm trying to do?

Google didn't turn up any useful matches on the error message.

EDIT

Here's some sample code that shows the problem:

$().ready(function () {
  var url = 'http://www.panoramio.com/wapi/data/get_photos?v=1&key=dummykey&tag=test&offset=0&length=20&callback=processImages&minx=-30&miny=0&maxx=0&maxy=150';

  $.get(url, function (jsonp) {
    var processImages = function (data) {
      alert('ok');
    };

    eval(jsonp);
  });
});

You can run the example online.

EDIT 2

Thanks to Darin for his help with this. THE ABOVE CODE IS WRONG. Use this instead:

$().ready(function () {
  var url = 'http://www.panoramio.com/wapi/data/get_photos?v=1&key=dummykey&tag=test&offset=0&length=20&minx=-30&miny=0&maxx=0&maxy=150&callback=?';

  $.get(url, function (data) {
    // can use 'data' in here...
  });
});

16 comments

@MiJyn 2013-06-06 23:15:38

There is a small problem in the solution posted by CodeGroover above , where if you change a file, you'll have to restart the server to actually use the updated file (at least, in my case).

So searching a bit, I found this one To use:

sudo npm -g install simple-http-server # to install
nserver # to use

And then it will serve at http://localhost:8000.

@Vi100 2018-05-02 09:48:39

While this link may answer the question, it is better to include the essential parts of the answer here and provide the link for reference. Link-only answers can become invalid if the linked page changes. - From Review

@MiJyn 2018-05-05 23:25:00

Clarified the link.

@mAsT3RpEE 2013-10-19 13:32:02

Not all servers support jsonp. It requires the server to set the callback function in it's results. I use this to get json responses from sites that return pure json but don't support jsonp:

function AjaxFeed(){

    return $.ajax({
        url:            'http://somesite.com/somejsonfile.php',
        data:           {something: true},
        dataType:       'jsonp',

        /* Very important */
        contentType:    'application/json',
    });
}

function GetData() {
    AjaxFeed()

    /* Everything worked okay. Hooray */
    .done(function(data){
        return data;
    })

    /* Okay jQuery is stupid manually fix things */
    .fail(function(jqXHR) {

        /* Build HTML and update */
        var data = jQuery.parseJSON(jqXHR.responseText);

        return data;
    });
}

@Cheng Chen 2011-05-06 16:27:50

As long as the requested server supports the JSON data format, use the JSONP (JSON Padding) interface. It allows you to make external domain requests without proxy servers or fancy header stuff.

@andymenon 2014-08-21 05:18:05

Folks,

I ran into a similar issue. But using Fiddler, I was able to get at the issue. The problem is that the client URL that is configured in the CORS implementation on the Web API side must not have a trailing forward-slash. After submitting your request via Google Chrome and inspect the TextView tab of the Headers section of Fiddler, the error message states something like this:

*"The specified policy origin your_client_url:/' is invalid. It cannot end with a forward slash."

This is real quirky because it worked without any issues on Internet Explorer, but gave me a headache when testing using Google Chrome.

I removed the forward-slash in the CORS code and recompiled the Web API, and now the API is accessible via Chrome and Internet Explorer without any issues. Please give this a shot.

Thanks, Andy

@Ganesh Kamath - 'Code Frenzy' 2014-07-10 06:32:30

Make sure you are using the latest version of JQuery. We were facing this error for JQuery 1.10.2 and the error got resolved after using JQuery 1.11.1

@mslembro 2013-09-30 07:47:51

I also got the same error in Chrome (I didn't test other browers). It was due to the fact that I was navigating on domain.com instead of www.domain.com. A bit strange, but I could solve the problem by adding the following lines to .htaccess. It redirects domain.com to www.domain.com and the problem was solved. I am a lazy web visitor so I almost never type the www but apparently in some cases it is required.

RewriteEngine on
RewriteCond %{HTTP_HOST} ^domain\.com$ [NC]
RewriteRule ^(.*)$ http://www.domain.com/$1 [R=301,L]

@user2701060 2013-08-20 18:35:37

If you are doing local testing or calling the file from something like file:// then you need to disable browser security.

On MAC: open -a Google\ Chrome --args --disable-web-security

@user2688838 2013-08-16 09:11:13

As final note the Mozilla documentation explicitly says that

The above example would fail if the header was wildcarded as: Access-Control-Allow-Origin: *. Since the Access-Control-Allow-Origin explicitly mentions http://foo.example, the credential-cognizant content is returned to the invoking web content.

As consequence is a not simply a bad practice to use '*'. Simply does not work :)

@CodeGroover 2012-03-07 15:49:55

For a simple HTML project:

cd project
python -m SimpleHTTPServer 8000

Then browse your file.

@pjammer 2013-07-03 22:12:34

while awesome and works, when you go to 0.0.0.0:8000 and try POST requests you get: code 501, message Unsupported method ('POST') for the googles.

@ecounysis 2014-05-28 22:39:04

"When a Python web server (like cherrypy for instance) says it is serving on 0.0.0.0 it means it is listening for all TCP traffic that ends up at that machine no matter the hostname or IP that was requested." So maybe try posting to localhost:8000 stackoverflow.com/a/4341808/102022

@GreySage 2017-02-08 22:15:41

I tried this, but got the same error as before.

@Kalpesh Patel 2012-01-03 19:09:55

In my case, same code worked fine on Firefox, but not on Google Chrome. Google Chrome's JavaScript console said:

XMLHttpRequest cannot load http://www.xyz.com/getZipInfo.php?zip=11234. 
Origin http://xyz.com is not allowed by Access-Control-Allow-Origin.
Refused to get unsafe header "X-JSON"

I had to drop the www part of the Ajax URL for it to match correctly with the origin URL and it worked fine then.

@romu31 2011-07-29 18:58:00

We managed it via the http.conf file (edited and then restarted the HTTP service):

<Directory "/home/the directory_where_your_serverside_pages_is">
    Header set Access-Control-Allow-Origin "*"
    AllowOverride all
    Order allow,deny
    Allow from all
</Directory>

In the Header set Access-Control-Allow-Origin "*", you can put a precise URL.

@Raptor 2013-05-06 09:47:16

this does not work on XAMPP's Apache. the problem still exists.

@Rob Quist 2014-02-26 21:09:11

This is unsafe. See here why; stackoverflow.com/questions/7564832/…

@d337 2019-01-03 07:04:04

It's unsafe as @RobQuist said.

@ssokolow 2010-09-19 06:06:38

For the record, as far as I can tell, you had two problems:

  1. You weren't passing a "jsonp" type specifier to your $.get, so it was using an ordinary XMLHttpRequest. However, your browser supported CORS (Cross-Origin Resource Sharing) to allow cross-domain XMLHttpRequest if the server OKed it. That's where the Access-Control-Allow-Origin header came in.

  2. I believe you mentioned you were running it from a file:// URL. There are two ways for CORS headers to signal that a cross-domain XHR is OK. One is to send Access-Control-Allow-Origin: * (which, if you were reaching Flickr via $.get, they must have been doing) while the other was to echo back the contents of the Origin header. However, file:// URLs produce a null Origin which can't be authorized via echo-back.

The first was solved in a roundabout way by Darin's suggestion to use $.getJSON. It does a little magic to change the request type from its default of "json" to "jsonp" if it sees the substring callback=? in the URL.

That solved the second by no longer trying to perform a CORS request from a file:// URL.

To clarify for other people, here are the simple troubleshooting instructions:

  1. If you're trying to use JSONP, make sure one of the following is the case:
    • You're using $.get and set dataType to jsonp.
    • You're using $.getJSON and included callback=? in the URL.
  2. If you're trying to do a cross-domain XMLHttpRequest via CORS...
    1. Make sure you're testing via http://. Scripts running via file:// have limited support for CORS.
    2. Make sure the browser actually supports CORS. (Opera and Internet Explorer are late to the party)

@jQuerybeast 2011-12-09 21:04:09

So what is the solution to this?

@Tim 2012-03-29 09:10:37

callback=? FTW

@echox 2012-06-12 16:20:09

Some browsers like chrome allow CORS if started with the parameter --allow-file-access-from-files

@crunkchitis 2012-06-28 18:06:46

callback=? didn't work for me, But jsonp=? did. Any explanation for that?

@ssokolow 2012-07-03 01:53:01

@crunkchitis: I'm not sure why callback=? isn't working for you, given that the current jQuery docs still say it should but, if I'm reading them correctly, they also say that anything_else=? will also work.

@styfle 2013-06-09 22:30:38

Thanks. I was using the generic $.ajax() function and changing the dataType from json to jsonp worked.

@BeNdErR 2014-06-07 09:39:24

Chrome allows this kind of request from local files, just run it with --disable-web-security

@Will Sewell 2014-08-11 15:55:25

Do I have to install a webserver to test via http://? Or is there a way to simply open the file using that protocol?

@ssokolow 2014-08-17 08:46:04

@Fractal Try running python -m SimpleHTTPServer in the folder with your files and then opening up http://localhost:8000/. My CORS stuff tends to be using Django or Bottle, which have their own development servers, but it should probably work. (If it doesn't and you know any Python, it's trivial to adapt Bottle's Hello World example.)

@Kevin Christopher Henry 2017-01-19 06:28:36

For the record, null is a perfectly valid value for Origin, and can indeed be returned in the Access-Control-Allow-Origin header. (See the Origin spec and the CORS spec.)

@Pere 2017-04-03 09:30:31

From the getJSON docs: This is a shorthand Ajax function, which is equivalent to: $.ajax({ dataType: "json", url: url, data: data, success: success }); I don't see how this can be equivalent to $.getwith dataType to jsonp nor what the callback=? could help here...

@ssokolow 2017-04-04 08:48:36

@Pere On the page you linked, it says "If the URL includes the string "callback=?" (or similar, as defined by the server-side API), the request is treated as JSONP instead. See the discussion of the jsonp data type in $.ajax() for more details."

@ssokolow 2017-05-17 16:02:25

@kevin-christopher-henry I didn't think the validity of null was in question. The issue is that, per the spec, browsers exhibit null != null behaviour.

@Kevin Christopher Henry 2017-05-17 17:37:39

@ssokolow: Per which spec? Perhaps I'm missing something, but it seems to me that the CORS spec goes out of the way to say that the matching algorithm applies exactly the same way with null: "The above algorithm also functions when the ASCII serialization of an origin is the string 'null'."

@ssokolow 2017-05-18 04:44:19

@KevinChristopherHenry It's late, so I don't have time to track down all of the instances now, but the gist of it is that null is a placeholder that's used when the actual origin doesn't pass muster, so an origin which serializes to null does not compare equal to a null that got echoed back. This shows up in places like section 7.3 of RFC 6454, which is the RFC linked from "ASCII serialization" in the document you referenced. This behaviour is also applied to redirects via step 6 of the "redirect steps" in section 7.1.7 of the document you linked.

@Kevin Christopher Henry 2017-05-19 01:37:09

@ssokolow: The references you cited concern when the browser should set the origin to null; they don't address the question of whether an Origin request header value of null should match an Access-Control-Allow-Origin response value of null when doing a CORS check. That is addressed by the section I cited and section 4.9 of the Fetch standard, which make it clear that they should match. (And I can tell you from personal experience that they do, though of course I can't prove that for every browser.)

@ssokolow 2017-05-20 03:06:11

@KevinChristopherHenry The very section you linked to says 2. If origin is null or failure, return failure., which makes perfect sense because, if it were possible for two different pages where the origins both serialize to null to be authenticated by the same non-* CORS authorization, it would be a massive security hole. Hence, as I initially said, exhibiting null != null behaviour.

@Kevin Christopher Henry 2017-05-23 01:27:58

@ssokolow: Did you read the next sentence? "Note: Null is not 'null'." That is, in the absence of the header value, return failure; otherwise—including when the value is the string 'null'—continue. When you do, there will be a match and the CORS check will pass. There doesn't seem to be much point in trying to convince you so I will just leave this here as a warning to others.

@ssokolow 2017-05-23 18:21:29

@KevinChristopherHenry I'll accept that point, since I now realize that I'd assigned too much importance to the capitalization in the note and too little to the lack of backticks in step 2, but that still doesn't explain the observed behaviour and principle that two sites which produce a null Origin cannot compare equal because it would open a security hole. I can only assume that somewhere else in the maze of specs, it tells browsers to compare the echoed-back null against the UUID/FQDN/etc. used for local or sensitive origins before they get translated to Origin: null to be sent.

@zenio 2012-04-02 11:52:05

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.

@Thomas Decaux 2011-02-11 10:59:17

You need to maybe add a HEADER in your called script, here is what I had to do in PHP:

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

More details in Cross domain AJAX ou services WEB (in French).

@Uri 2011-04-02 11:45:23

How is this done on a normal html file (no php)?

@ssokolow 2011-04-08 00:37:52

@Uri: Depends on your HTTP server. With Apache, you'll want to look into mod_headers.

@Herberth Amaral 2012-01-14 21:14:39

@Uri <meta http-equiv="Access-Control-Allow-Origin" content="*">

@thandasoru 2012-04-02 06:08:58

@HerberthAmaral I tried adding this inside <head></head>, but it doesn't work for me. I am trying it in iOS Safari and Chrome, but in the console, I get the origin null is not allowed by Access-Control-Allow-Origin error.

@Justin Blank 2012-09-02 19:23:17

It doesn't work in the head of the html file for security reasons. It has to be a header. stackoverflow.com/questions/7015782/…

@Roman Plášil 2017-01-10 10:33:33

It can't be in the HTML. It has to be specified by the program that is sending the HTML page to your browser over the network (so called web server).

@Darin Dimitrov 2010-08-29 16:14:53

Works for me on Google Chrome v5.0.375.127 (I get the alert):

$.get('http://www.panoramio.com/wapi/data/get_photos?v=1&key=dummykey&tag=test&offset=0&length=20&callback=?&minx=-30&miny=0&maxx=0&maxy=150',
function(json) {
    alert(json.photos[1].photoUrl);
});

Also I would recommend you using the $.getJSON() method instead as the previous doesn't work on IE8 (at least on my machine):

$.getJSON('http://www.panoramio.com/wapi/data/get_photos?v=1&key=dummykey&tag=test&offset=0&length=20&callback=?&minx=-30&miny=0&maxx=0&maxy=150', 
function(json) {
    alert(json.photos[1].photoUrl);
});

You may try it online from here.


UPDATE:

Now that you have shown your code I can see the problem with it. You are having both an anonymous function and inline function but both will be called processImages. That's how jQuery's JSONP support works. Notice how I am defining the callback=? so that you can use an anonymous function. You may read more about it in the documentation.

Another remark is that you shouldn't call eval. The parameter passed to your anonymous function will already be parsed into JSON by jQuery.

@Drew Noakes 2010-08-29 16:23:28

Hmm ok let me try again. I'm on a different version of Chrome btw "6.0.472.51 beta".

@Drew Noakes 2010-08-29 16:26:46

Your code worked for me to. I updated my question with some code that draws the problem out though.

@Drew Noakes 2010-08-29 16:31:18

Thanks for the tip re getJSON... I forked your jsFiddle example to show the problem (jsfiddle.net/ZfvKm) and now see the error message XMLHttpRequest cannot load panoramio.com/wapi/data/…. Origin fiddle.jshell.net is not allowed by Access-Control-Allow-Origin.

@Drew Noakes 2010-08-29 16:49:30

@Darin, thanks for the update. I see your point, and I've played with a few combinations of this, but I'm yet to find a way to access the returned object. Could you update your jsFiddle example to show accessing the data? If you set the callback to ? then the returned JSON is surrounded with parenthesis. You don't define a parameter for your callback function, and the value of this doesn't seem to have a response object (at least, the .data value is null).

@Darin Dimitrov 2010-08-29 16:55:13

@Drew, example updated: jsfiddle.net/ZfvKm/2 as well as my post.

@Drew Noakes 2010-08-29 17:00:05

@Darin, fantastic. Many thanks. Working well now. For anyone else reading this, the inclusion of callback=? tells jQuery to generate a random function name internally, resulting in a call to the anonymous function you pass to .getJSON. Appreciated.

@Quentin 2010-08-29 16:15:25

It's the same origin policy, you have to use a JSON-P interface or a proxy running on the same host.

@Darin Dimitrov 2010-08-29 16:16:17

panoramio already sends JSONP.

Related Questions

Sponsored Content

28 Answered Questions

[SOLVED] Access-Control-Allow-Origin Multiple Origin Domains?

13 Answered Questions

[SOLVED] How does Access-Control-Allow-Origin header work?

7 Answered Questions

[SOLVED] how to bypass Access-Control-Allow-Origin?

18 Answered Questions

[SOLVED] Origin is not allowed by Access-Control-Allow-Origin

11 Answered Questions

8 Answered Questions

5 Answered Questions

[SOLVED] Origin null is not allowed by Access-Control-Allow-Origin

  • 2011-12-10 12:36:55
  • dudledok
  • 255733 View
  • 172 Score
  • 5 Answer
  • Tags:   jquery html cors

11 Answered Questions

[SOLVED] Access-Control-Allow-Origin wildcard subdomains, ports and protocols

  • 2012-12-22 13:44:26
  • Elie
  • 269033 View
  • 266 Score
  • 11 Answer
  • Tags:   cors

Sponsored Content