Home >
What in the heck is JSONP and why would you use it?
Have you ever looked at some technology, or framework, and simply didn't understand why someone would use it? For some time now I've never quite gotten what JSONP is, nor why someone would use it over XML. Everything finally cleared up for me last week and since I assume (I hope!) I'm not alone in being confused, I thought I'd share what I learned.
JSONP (JSON with Padding) was created as a workaround to the cross domain problem. The cross domain problem refers to the fact that Ajax code run from website A can't access data from website B. So as a simple example, imagine trying to load Yahoo Search results from your site:
This simple example will fail immediately with this error: Access to restricted URI denied. None of this should be new to us (although I do get asked about this every few weeks). The normal way around this is to build a proxy on your own server. So the Ajax code would hit some URL on your own domain. Server side code (like ColdFusion) handles making the remote call and then returns the results to the front end Ajax code. This works well, although it does end taking a bit longer due to the extra stops along the way. I intentionally chose Yahoo's search api for my example above since Yahoo was the first provider I noticed supporting JSON/P. At the time I had assumed it simply helped support their JSON format results. I didn't quite get what else it would provide. I figured Yahoo was simply providing JSON as an alternative to XML for data size reasons (JSON can be a lot slimmer) and that people were using it along with the "proxy" setup I just described.
Last week I came across this excellent article at IBM: Cross-domain communications with JSONP, Part 1: Combine JSONP and jQuery to quickly build powerful mashups. Finally, everything clicked. Turns out, there is a back door to the whole cross domain issue. If you dynamically create a new script block, you are allowed to point this new script block at any domain you want. So for example, I could dynamically create a script block that acts as if I had done:
So with that being possible (and with the way browsers are updated this little backdoor probably won't ever be shut) you can now dynamically request dat from another server. But how do you actually work with the data? Normally script tags like the one above load a library of code into your browser. They aren't just used to load data by itself. Another problem is handling the data. If my intent was to request Yahoo search data and present it within my own UI, I'd need to be able to make the request as well as handle the result manually. This is where the whole 'with Padding' thing comes to play. An API that supports JSONP will return not only the pure JSON data you want, but will also wrap it in a function call. So in English, I can tell Yahoo: "Please return search results for 'finances'. I want the data in JSON format and I want you to wrap it in a call to a function called handleIt that I've defined below."
To see an example of this, open the following URL in your browser:
http://search.yahooapis.com/WebSearchService/V1/webSearch?appid=YahooDemo&query=finances&format=pdf&output=json
Notice the result is simple JSON. Now modify the URL a bit to request a callback:
http://search.yahooapis.com/WebSearchService/V1/webSearch?appid=YahooDemo&query=finances&format=pdf&output=json&callback=loadit
Now the JSON code is wrapped in a function call to something called loadit. If I had a function named loadit on my page, it would have been run and the search result data passed to it. To bring this together into a real working example, I'll demonstrate using jQuery. jQuery provides builtin support for JSONP. You don't have to worry about writing any of the code to inject a new SCRIPT tag into the DOM. All you end up doing is modifying the URL to tip off jQuery that a JSONP call is being made. From the docs for getJSON, we see that by ending your URL with a ?, jQuery will treat the request like a JSONP call. You don't have to specify a function name yourself. jQuery will take care of that. Here is a full example:
I built a simple form and tied it my search function. I had created a base URL for Yahoo so that all I need to do is append the current search term from the from. After that I added callback=?. Again - this tips off jQuery that it needs to treat the request like JSONP. I can then supply an inline function to handle the results. I won't go into detail about the code there as it is mostly HTML handling, but I think you get the idea.
Interesting technique - but would I use it? First, you can only use it with APIs that support JSONP (anyone have a good list of them?). Secondly, even if an API does support JSONP, you may still prefer the proxy support for a few reasons. First, it may be easier to massage the results on the server side. You may want to filter, for example, the search results to items that match with certain products in your database. That could be done with further Ajax calls, but it may be simpler to just do one call to your server and let it do all the handiwork. Using a proxy also makes it a bit easier to handle errors. Again, you could do that client side, but you may want to revert to server side cached results in the case where Yahoo fails to respond.
I'd love to hear from people using this in production!
<html>
<head>
<script src="/jquery/jquery.js"></script>
<script>
$(function() {
var req = 'http://search.yahooapis.com/WebSearchService/V1/webSearch?appid=YahooDemo&query=finances&format=pdf&output=json'
$.getJSON(req,{}, function(data) {
console.dir(data)
});
});
</script>
</head>
<body>
</body>
</html>
<script src="http://search.yahooapis.com/someJSLibrary.js"></script>
http://search.yahooapis.com/WebSearchService/V1/webSearch?appid=YahooDemo&query=finances&format=pdf&output=json
Notice the result is simple JSON. Now modify the URL a bit to request a callback:
http://search.yahooapis.com/WebSearchService/V1/webSearch?appid=YahooDemo&query=finances&format=pdf&output=json&callback=loadit
Now the JSON code is wrapped in a function call to something called loadit. If I had a function named loadit on my page, it would have been run and the search result data passed to it. To bring this together into a real working example, I'll demonstrate using jQuery. jQuery provides builtin support for JSONP. You don't have to worry about writing any of the code to inject a new SCRIPT tag into the DOM. All you end up doing is modifying the URL to tip off jQuery that a JSONP call is being made. From the docs for getJSON, we see that by ending your URL with a ?, jQuery will treat the request like a JSONP call. You don't have to specify a function name yourself. jQuery will take care of that. Here is a full example:
<html>
<head>
<script src="/jquery/jquery.js"></script>
<script>
var baseurl = 'http://search.yahooapis.com/ImageSearchService/V1/imageSearch?appid=YahooDemo&output=json&query='
function search() {
var search = $("#search").val()
console.log(search)
var surl = baseurl + escape(search) + '&callback=?'
$.getJSON(surl, function(data) {
var res = '<h1>Search for '+search+'</h1>'
res += '<p>There were '+data.ResultSet.totalResultsAvailable+' results.</p>'
for(var i=0; i<data.ResultSet.Result.length; i++) {
var result = data.ResultSet.Result[i]
var resultStr = '<img src="'+result['Thumbnail']['Url']+'" align="left">';
resultStr += '<a href="'+result['ClickUrl']+'">'+result['Title']+'</a><br clear="left"/>'
res+=resultStr
}
$("#result").html(res)
})
}
$(document).ready(function() {
$("#searchBtn").click(search)
});
</script>
</head>
<body>
<input type="text" name="search" id="search"> <input type="button" value="Search" id="searchBtn">
<div id="result"></div>
</body>
</html>




Facebook Application Development
I read this far:
and stopped, sorry.This sounds like a nice little trick, but surely it is a security hole that will eventually be plugged by at least on of the major browsers if not all. Even one browser plugging this hole causes problems for Ajax developers.
I found an articl eon this technique back in 05, so it would probably be safe to use. So really, you stopped reading? Come on - finish the article at least! :)
Ahh hah, it makes sense now. I always wondered what 'with Padding' meant, and never bothered to look it up..
After reading this article I understand that JSON/P is really a seemingly simple concept. Thanks for the great explanation.
That's also really cool how jQuery handles it so easily, jQuery ftw!
I just submitted this link to dzone:
http://www.dzone.com/links/what_in_the_heck_is_jsonp_and_why_would_you_use_it.html
Very good one! I always asked myself what is JSONP good for and now everything is clearer for me1
"but surely it is a security hole that will eventually be plugged"
It won't. It's a technique commonly known as the script tag hack and it was one way of doing AJAX before XMLHttpRequest existed. It worked in 1999, it works in 2009 and I bet you a beer coaster it'll still work in 2019.
Hello,
please add your blog at www.sweebs.com where other people can find your site among the best sites on the internet!
Regards
Kris
Apparently this cross-domain ability will be handled inherently in the upcoming releases of browsers without having to use JSON/P. Watch John Resig talk about cross-domain XMLHttpRequest, right at about 33 minutes...
http://www.youtube.com/watch?v=13-3VMzfU3Y
So, I have a question, Is it possible to make POST requests using JSONP? In particular, I'd like to post status updates to Twitter, but it requires POST and I don't see a way of getting that done.
Is it only GET requests?
John, get only. It ends p being the exact same as you typing in a script block tag on your page.
Yeah, JSONP is good. But it's very limited: a) you can only integrate with webservices who support the standard (and some don't for security concerns), and b) you can only use GET and you must send/receive via JSON format.
flXHR is a project which gives you full GET and POST capabilities with cross-domain Ajax calls, and you can send and receive any kind of data (text, html, json, jsonp, xml, even binary). It presents an identical API to the native XHR Ajax calling object mechanism. In this way, it can be dropped into any existing page, even those with frameworks like jQuery, Dojo, etc, and you don't have to change *any* other code to work with it -- you just get cross domain capability that simple.
It's a javascript+invisible flash alternative to XHR so that it can make those cross-domain calls directly in the browser. It's benchmark tested to be as quick as (or sometimes faster than) other cross-domain hacks, like iframe-proxies or window.name. And it takes care of any messiness with flash for you, by auto-detecting plugin version, prompting for inline automatic update if necessary, etc. Since 99% of people have some version of flash installed, this means flXHR basically will provide almost completely universal cross-domain Ajax capability.
Because it uses flash, it uses Adobe's more secure server opt-in policy model for servers to authorize the cross-domain calls to places they trust, while blocking those they don't. flXHR is the only complete solution which gives better security, more efficiency, and totally cross-browser, cross-platform support for cross-domain Ajax.
Well thats pretty darn interesting Kyle. I had never heard of flXHR before.
Are flXHR calls truly asynchronous? This is another disadvantage of JSONP/dynamic script tags; browsers stop what they are doing until script responses return and execute.
Yes, flXHR calls are asynchronous, to the extent that browsers will allow it. If you look at some of the multi-request demos, and try them yourself, you can see that multiple requests can get fired off simultaneously, with results coming back nearly at the same time.
is it possible to send data using JSONP? no, right?
is it possible to send data to a server using JSONP?
Yes. Notice how in the last example I pass in a search value?
hmm i wonder, i dont use js libraries but as i know the jquery getJSON function will append content from server, it seems strange to me that is possible because of the functionning of JSONP(appends script tag), btw looks like your example does not work(nothings appends in the output div)
Not sure what to tell you. I just tried it again locally - with a cut and paste from above - and it worked ok. Make sure you edit the script tag to point to a valid jquery source.
yes, sorted. cheers
what i dont get is how when you search for a word , how the word gets written on the server in the JSON file.
It isn't written on the server. Basically, jQuery creates a new SCRIPT tag in your DOM (the page). The script tag points to the URL specified in the code, and my search term is added. So it _acts_ as if I had written the script tag myself and pointed it to
http://search.yahooapis.com/ImageSearchService/V1/imageSearch?appid=YahooDemo&output=json&query=X
where X is my search term. Yahoo has code o their side to respond to this request with the proper results.
ok thanks for those clarification, two weeks ago i built a json prog a bit like yours that retrieve data from flickr but i did it using plain javascript.
Thanks for this article... I didn't quite get JSONP until I read this... I've got an API for one of our apps that returns json data, and I wanted to get it from another domain.... I tried using jQuery's JSONP support, but it didn't work.... I didn't get that I needed to check my request to see if it has a "callback" parameter in it, and add that parameter as a function call to the response! Thanks so much!
This is a great article. However, it doesn't work with adobe air because air has some restrictions on callbacks (since callbacks kind of like actually insert scripts into the dom to pull data and run it and this is not allowed in air for security purposes). Anyone know a way around it or a way of having json callbacks in adobe air?
You don't need jsonp. AIR can already do XHR requests to other domains. I took the code above, REMOVE the &callback, built it with adl and it ran just fine.
For those thinking this is a "bug" that will be "patched", it's not. It's a workaround using valid functionality.
How would you "patch" this? Apply same-origin policy to the tag? That breaks half the web.
It also won't get "fixed" considering google, twitter, yahoo and a dozen more major sites are using the same technique where appropriate.
It's interesting to learn about both JSONP and flXHR. Like you, I had heard about JSONP a thousand times, and read about it briefly on several occasions, and tried to understand why it was popular. Now I finally know.
I wonder if anyone's created a jQuery plugin that uses flXHR by default and falls back to JSONP when flash isn't available. If flXHR works better than JSONP, it seems to me that such a thing would take off, if properly executed.
@BenAtkin
It's an interesting idea, the jQuery plugin that falls back to JSONP if flash isn't available.
There is a flXHRproxy jquery plugin for flXHR which causes jQuery to use flXHR for its normal ajax calls. It matches up via target url to do this selection.
This plugin is located here: http://flxhr.flensed.com/jquery.php
It would seem like it wouldn't be too difficult to extend the plugin to do a flash version check in addition to its target-url matching.
The flash version checking is already done by the flensedCore code that comes with flXHR. So you can just inspect the detected version numbers and go from there.
Now, flXHR will attempt to upgrade a user's plugin if their flash is present but not of a high enough version for flXHR's security model (9.0.124). So, I would think the best logic would be to only fall back to JSONP if flash is either missing, or too low to even be upgraded. So that logic would be done like this:
if (flensed.ua.pv[0] // flash is either missing or just plain too old, fall back to JSONP
}
else {
// good news, flash is present and is either already up to date, or can be updated if the user agrees, so continue with flXHR, and it should work!
}
Again, you could weave that into the matching function in the jQuery flXHRproxy plugin, and force it not to match if the flash availability fails.
Lastly, if you are wanting to fall back to JSONP, you just need to signal to the jquery XHR registry to abandon XHR calls and fall back to JSONP. That part I'm not exactly sure how to do, but it's possible. I think you just simply set the 'transport' property to JSONP, if I'm not mistaken.
In any case, the point is, it's a good idea and I think very doable. If you attempt it and need help getting it working, let me know. And if you get it working, please let me know too, I'd love to highlight it.
reposting code logic fragment:
if (flensed.ua.pv[0] < 6 || (flensed.ua.pv[0] == 6 && flensed.ua.pv[2] < 65) {
// flash is either missing or just plain too old, fall back to JSONP
}
else {
// good news, flash is present and is either already up to date, or can be updated if the user agrees, so continue with flXHR, and it should work!
}
I've been curious what JSONP was and now you've made it very clear. Thanks!
FYI:
There's another cross-domain Ajax project I recently released, called jXHR. It still defines the same XHR API interface, but it uses JSON-P to make the calls. It also adds basic error handling.
http://test.getify.com/jXHR
I'm looking for a cross-domain solution to post twitter status updates. flXHR doesn't do this because twitter's crossdomain.xml does not allow requests outside of its domain. It appears that a serverside proxy is the ONLY thing that works. Anyone know otherwise?
@Joe -- If twitter will support GETs for the updates, then you can use JSON-P (which you could do easily with jXHR!).
If not, you could do hidden form posts. Basically, you could create a dynamic form and then fill in values, and post it. You may need to target a hidden iframe to prevent the page/browser from changing locations.
Hello Kyle!
I am really interested in flXHR. That would really solve my problem on cross domain requests using POST method as there is a large data needed to post like a 'memo' field (textarea) with my application.
I see to it that you wrote or authors this awesome technology. Can you help me understand on how to use it? I have been reading your documentation but can't get quite it to work. What I need is simple, just to make a cross domain request using post. What do I need to have to make it work? Required files?
Currently in my application, I have jquery version 1.3.1
Hoping for your kindest response.
Thanks
@cocoy -- contact me through the site/forums and I'll be happy to help!
Way to go Raymond... this is first class information.
Thanks.
sundownr
I'm doing some cross-domain ajax stuff (I connect multiple .org and .com subdomains to a common server), using apache with the ProxyPass directive and conventional XMLHttpRequest stuff. I'm considering whether I can use jsonp in the browser to avoid the extra request in each proxied reference.
I'm confused about whether the jquery getjson method is truly asynchronous or not. I understand jsonp, the script tag approach, how jquery installs the callback, and how the callback is invoked when the server reply arrives.
The reason I think about any of this is the "A" in AJAX -- if I have a page with multiple form buttons, I want to fire off one and continue handling the others while I wait for the reply with results from the first.
I thought the browsers had to do special magic to accomplish the asynchronous part of the XMLHttpRequest handling. Has jquery somehow hooked or wrapped that magic, and injected script tags into the existing mechanism? I read claims that getjson is limited to "GET" requests, which leads towards "no", I think. Does anybody really know (has somebody actually looked inside jquery? I tried, and find it impenetrable).
If so, then does anybody know *how*? I'd like to replicate that trick, without having to use jquery throughout my browser-side code.
If not, then aren't the cross-domain jsonp calls actually synchronous -- don't they have to wait for the server to respond before invoking the callback, blocking the getjson caller?
Hi
This is good JSONP idea. I have this json feed but can't write getJSON script to parse my json. Can you help me.
http://www.office1.bg/eshop/cocacola/PHP_sessions3/data.json