Kyle Banks

Fetching Cross-Domain JSON (Tweets) with JavaScript and JSONP

Written by @kylewbanks on May 11, 2013.

The Problem

Browser security does not allow cross-domain AJAX requests. This means that a domain of http://example.com cannot request http://twitter.com using AJAX. A common solution to this is to use your server as a proxy, having it request the tweets and return it's response to your JavaScript. The problem with this is that you now have two network calls to wait for, and it requires a server-side language to implement. Is it possible to do this using only client-side JavaScript? Of course!

The Solution

Rather than loading the Twitter JSON using AJAX, we can load it as a <script>, and use JSONP to execute our JavaScript code when the JSON is returned. Because the JSON response is simply a JavaScript object (JavasScript Object Notation), it is entirely acceptable to pass it as a function parameter. Let's take a look at what the script from Twitter will need to look like:

executeCallback({"this": "is JSON"});

So how do we tell Twitter to format the JSON inside of a function call like that, rather than just responding with plain old JSON? Well, luckily for us they have built it into their API (as have many other REST APIs, actually). We just need to pass a parameter to the REST calls like so:

https://api.twitter.com/restMethod?callback=parseTweets

Now that Twitter knows to execute our JavaScript function parseTweets, let's parse some Tweets. In order to bypass the need to authenticate API requests I'm going to demonstrate this using Twitter API version 1, but the callback parameter works exactly the same in version 1.1. The following code is going to fetch my tweets and log each one to console.log (if you are using IE, you can use alert instead).

<script type="text/javascript">
function parseTweets(tweets) {
	$.each(tweets, function(i, tweet) {
		console.log(tweet);
	});
}
</script>

&ltscript src="https://api.twitter.com/1/statuses/user_timeline.json?screen_name=kylewbanks&callback=parseTweets" type="text/javascript"></script>

Now that you have the tweet objects, you are free to do with them what you will. This method will work for all Twitter API requests, and most REST APIs will offer a similar callback parameter.

This is all well and good when you know the Twitter handle (or REST URL) on page load, but what if you want to make more API calls, or format your API requests based on user input?

Dynamic API Calls

The solution is basically the same, with one minor change: the script must be inserted into the DOM using JavaScript once we have enough information to format the request URL. Using the example above, this may be allowing the user to enter a Twitter handle of their own:

var s = document.createElement("script");
s.src = "https://api.twitter.com/1/statuses/user_timeline.json?screen_name="+TWITTER_HANDLE+"&callback=parseTweets";
s.type = "text/javascript";
$('body').append(s);

What this does is generate a script tag and insert it at the end of the page's body. The variable TWITTER_HANDLE could be retrieved from a text input field, a drop down list, etc. Now that we can do this dynamically, we can continue to make calls at any time using JavaScript, not just on page load.

Let me know if this post was helpful on Twitter @kylewbanks or down below, and follow me to keep up with future posts!