Categories
javascript json jsonp terminology

What is JSONP, and why was it created?

2366

I understand JSON, but not JSONP. Wikipedia’s document on JSON is (was) the top search result for JSONP. It says this:

JSONP or “JSON with padding” is a JSON extension wherein a prefix is specified as an input argument of the call itself.

Huh? What call? That doesn’t make any sense to me. JSON is a data format. There’s no call.

The 2nd search result is from some guy named Remy, who writes this about JSONP:

JSONP is script tag injection, passing the response from the server in to a user specified function.

I can sort of understand that, but it’s still not making any sense.


So what is JSONP? Why was it created (what problem does it solve)? And why would I use it?


Addendum: I’ve just created a new page for JSONP on Wikipedia; it now has a clear and thorough description of JSONP, based on jvenema‘s answer.

4

  • 43

    For the record, do NOT use JSONP if you don’t trust the server you’re talking to 100%. If it is compromised, your webpage will be trivially compromised.

    Jan 27, 2012 at 20:56

  • 10

    Also note that JSONP can be hijacked if not implemented correctly.

    – Pacerier

    Mar 29, 2015 at 7:20

  • 4

    I would like to give credit to the author of JSONP who gave the philosophy behind it: Bob Ippolito’s archive on JSONP. He introduces JSONP as “a new technology agnostic standard methodology for the script tag method for cross-domain data fetching”.

    – gawkface

    Feb 10, 2017 at 6:05

  • 5

    For those who might arrive here more than a decade after the question through a search for something else and are confused: JSON-P is now also the name of a Java API for processing JSON, mainly parsing and writing it. It mirrors the XML StAX and DOM APIs, for streaming input/output and document modeling respectively. It supports JSON Pointer for querying, like XPath for XML. I think it also intends to provide the means to transform JSON through JSON Patch, like XML with XSLT and the Java XML Transformer API, but it’s still a bit less advanced than XSLT. This question is about script injection.

    – G_H

    Sep 29, 2021 at 21:18

2233

It’s actually not too complicated…

Say you’re on domain example.com, and you want to make a request to domain example.net. To do so, you need to cross domain boundaries, a no-no in most of browserland.

The one item that bypasses this limitation is <script> tags. When you use a script tag, the domain limitation is ignored, but under normal circumstances, you can’t really do anything with the results, the script just gets evaluated.

Enter JSONP. When you make your request to a server that is JSONP enabled, you pass a special parameter that tells the server a little bit about your page. That way, the server is able to nicely wrap up its response in a way that your page can handle.

For example, say the server expects a parameter called callback to enable its JSONP capabilities. Then your request would look like:

http://www.example.net/sample.aspx?callback=mycallback

Without JSONP, this might return some basic JavaScript object, like so:

{ foo: 'bar' }

However, with JSONP, when the server receives the “callback” parameter, it wraps up the result a little differently, returning something like this:

mycallback({ foo: 'bar' });

As you can see, it will now invoke the method you specified. So, in your page, you define the callback function:

mycallback = function(data){
  alert(data.foo);
};

And now, when the script is loaded, it’ll be evaluated, and your function will be executed. Voila, cross-domain requests!

It’s also worth noting the one major issue with JSONP: you lose a lot of control of the request. For example, there is no “nice” way to get proper failure codes back. As a result, you end up using timers to monitor the request, etc, which is always a bit suspect. The proposition for JSONRequest is a great solution to allowing cross domain scripting, maintaining security, and allowing proper control of the request.

These days (2015), CORS is the recommended approach vs. JSONRequest. JSONP is still useful for older browser support, but given the security implications, unless you have no choice CORS is the better choice.

19

  • 215

    Please note that using JSONP has some security implications. As JSONP is really javascript, it can do everything else javascript can do, so you need to trust the provider of the JSONP data. I’ve written som blog post about it here: erlend.oftedal.no/blog/?blogid=97

    – Erlend

    Jan 14, 2010 at 21:24

  • 76

    Is there really any new security implication in JSONP that is not present in a <script> tag? With a script tag the browser is implicitly trusting the server to deliver non-harmful Javascript, which the browser blindly evaluates. does JSONP change that fact? It seems it does not.

    – Cheeso

    Jan 14, 2010 at 21:45

  • 26

    Nope, it doesn’t. It you trust it to deliver the javascript, same thing applies for JSONP.

    Jan 14, 2010 at 21:52

  • 17

    It’s worth noting that you can ramp up security a little by changing how the data is returned. If you return the script in true JSON format such as mycallback(‘{“foo”:”bar”}’) (note that the parameter is now a string), then you can parse the data manually yourself to “clean” it before evaluating.

    Jan 15, 2010 at 0:04


  • 9

    CURL is a server-side solution, not client-side. They serve two different purposes.

    Sep 8, 2010 at 13:10

774

JSONP is really a simple trick to overcome the XMLHttpRequest same domain policy. (As you know one cannot send AJAX (XMLHttpRequest) request to a different domain.)

So – instead of using XMLHttpRequest we have to use script HTML tags, the ones you usually use to load js files, in order for js to get data from another domain. Sounds weird?

Thing is – turns out script tags can be used in a fashion similar to XMLHttpRequest! Check this out:

script = document.createElement('script');
script.type="text/javascript";
script.src="http://www.someWebApiServer.com/some-data";

You will end up with a script segment that looks like this after it loads the data:

<script>
{['some string 1', 'some data', 'whatever data']}
</script>

However this is a bit inconvenient, because we have to fetch this array from script tag. So JSONP creators decided that this will work better(and it is):

script = document.createElement('script');
script.type="text/javascript";
script.src="http://www.someWebApiServer.com/some-data?callback=my_callback";

Notice the my_callback function over there? So – when JSONP server receives your request and finds callback parameter – instead of returning plain js array it’ll return this:

my_callback({['some string 1', 'some data', 'whatever data']});

See where the profit is: now we get automatic callback (my_callback) that’ll be triggered once we get the data.
That’s all there is to know about JSONP: it’s a callback and script tags.

NOTE: these are simple examples of JSONP usage, these are not production ready scripts.

Basic JavaScript example (simple Twitter feed using JSONP)

<html>
    <head>
    </head>
    <body>
        <div id = 'twitterFeed'></div>
        <script>
        function myCallback(dataWeGotViaJsonp){
            var text="";
            var len = dataWeGotViaJsonp.length;
            for(var i=0;i<len;i++){
                twitterEntry = dataWeGotViaJsonp[i];
                text += '<p><img src = "' + twitterEntry.user.profile_image_url_https +'"/>' + twitterEntry['text'] + '</p>'
            }
            document.getElementById('twitterFeed').innerHTML = text;
        }
        </script>
        <script type="text/javascript" src="http://twitter.com/status/user_timeline/padraicb.json?count=10&callback=myCallback"></script>
    </body>
</html>

Basic jQuery example (simple Twitter feed using JSONP)

<html>
    <head>
        <script type="text/javascript" src="https://ajax.googleapis.com/ajax/libs/jquery/1.6.2/jquery.min.js"></script>
        <script>
            $(document).ready(function(){
                $.ajax({
                    url: 'http://twitter.com/status/user_timeline/padraicb.json?count=10',
                    dataType: 'jsonp',
                    success: function(dataWeGotViaJsonp){
                        var text="";
                        var len = dataWeGotViaJsonp.length;
                        for(var i=0;i<len;i++){
                            twitterEntry = dataWeGotViaJsonp[i];
                            text += '<p><img src = "' + twitterEntry.user.profile_image_url_https +'"/>' + twitterEntry['text'] + '</p>'
                        }
                        $('#twitterFeed').html(text);
                    }
                });
            })
        </script>
    </head>
    <body>
        <div id = 'twitterFeed'></div>
    </body>
</html>

JSONP stands for JSON with Padding. (very poorly named technique as it really has nothing to do with what most people would think of as “padding”.)

6

  • 37

    Thanks for the script tag explanation. I wasn’t able to figure out how the cross domain security policy was bypassed by JSONP. After the explanation I feel a litte stupid to miss the point…

    – Eduard

    Aug 2, 2012 at 7:35

  • 14

    This is a very good complementary answer to jvenema’s answer – I didn’t understand why the callback was necessary until you pointed out that the json data would otherwise have to be accessed via the script element.

    – Matt

    Mar 9, 2014 at 1:26

  • 7

    Thanks for such lucid explanation. I wish my college textbooks were written by people like you 🙂

    – hashbrown

    Nov 21, 2014 at 2:50

  • 1

    Good explication rather than the previous one. Ofcourse- your excerpt ” the ones you usually use to load js files, in order for js to get data from another domain. Sounds weird?” is also eye opener for me. Example code in very much illustrious.

    – SIslam

    Jul 24, 2015 at 12:56

  • I like this explanation with concrete examples better than the accepted answer! Thanks!

    – ihor.eth

    Oct 23, 2020 at 15:21

50

JSONP works by constructing a “script” element (either in HTML markup or inserted into the DOM via JavaScript), which requests to a remote data service location. The response is a javascript loaded on to your browser with name of the pre-defined function along with parameter being passed that is tht JSON data being requested. When the script executes, the function is called along with JSON data, allowing the requesting page to receive and process the data.

For Further Reading Visit: https://blogs.sap.com/2013/07/15/secret-behind-jsonp/

client side snippet of code

    <!DOCTYPE html>
    <html lang="en">
    <head>
     <title>AvLabz - CORS : The Secrets Behind JSONP </title>
     <meta charset="UTF-8" />
    </head>
    <body>
      <input type="text" id="username" placeholder="Enter Your Name"/>
      <button type="submit" onclick="sendRequest()"> Send Request to Server </button>
    <script>
    "use strict";
    //Construct the script tag at Runtime
    function requestServerCall(url) {
      var head = document.head;
      var script = document.createElement("script");

      script.setAttribute("src", url);
      head.appendChild(script);
      head.removeChild(script);
    }

    //Predefined callback function    
    function jsonpCallback(data) {
      alert(data.message); // Response data from the server
    }

    //Reference to the input field
    var username = document.getElementById("username");

    //Send Request to Server
    function sendRequest() {
      // Edit with your Web Service URL
      requestServerCall("http://localhost/PHP_Series/CORS/myService.php?callback=jsonpCallback&message="+username.value+"");
    }    

  </script>
   </body>
   </html>

Server side piece of PHP code

<?php
    header("Content-Type: application/javascript");
    $callback = $_GET["callback"];
    $message = $_GET["message"]." you got a response from server yipeee!!!";
    $jsonResponse = "{\"message\":\"" . $message . "\"}";
    echo $callback . "(" . $jsonResponse . ")";
?>

2