Back to Blog

How to easily display a twitter feed using javascript

March 15, 2012

By Matt Mombrea
27 Comments

Update: March 2013

This method of retrieving timeline data from Twitter is going to be shut down very soon. Please see my follow up article on the death of the Twitter API v1 for more details on why it will no longer be possible to use JavaScript for the Twitter API.


Twitter. For better or worse it’s everywhere. You’d be hard pressed to find a new website or blog that is not incorporating a twitter feed into the site somewhere. There are tons of plugins, libraries, and extensions that help you get up and running with a twitter feed quickly, but many times they can be overkill for what you need.

One of the great things about twitter is how accessible it is. The team at twitter has done a really good job of creating an API that is simple, powerful, and flexible all at the same time. If you just need to read a single timeline (your own or someone else) you can skip all the 3rd party plugins and libraries and just roll your own JavaScript solution.

The example I’m going to discuss could be used to read a list of status updates for a user, or just the latest tweet, and display it anywhere you like in a website or blog. For convenience sake I’m using jQuery since we are generally using it in every project these days anyway.

Getting the data URL

Twitter’s API is pretty straight forward, you can get to whatever data you need with ease by reading their REST documentation. In our case, we are using the Get Statuses method call. The syntax is:

https://api.twitter.com/1/statuses/user_timeline/CypressNorth.json?callback=?&count=1

In our case we are limiting the response to 1 because we are only concerned with the latest tweet. If you remove the count parameter you get back the most recent 15 status updates. You can use the same URL to get the timeline of the account you are interested in, just replace cypressnorth.json with youraccountname.json.

Similarly, if you’d prefer to work with XML, you can change the extension of the request to youraccountname.xml and XML will be returned.

Making the AJAX Request

Now that we know the URL to retrieve our data, it’s time to make the request. In my case I’m only interested in working with JSON data, so to save time I can use the jQuery $.getJSON() function to both make the request and parse the results. An added benefit of using this shortcut is that it is compatible with Internet Explorer so you don’t need to make a separate XDR request.

$(document).ready(function() {
	loadLatestTweet();
});

function loadLatestTweet(){
	var _url = 'https://api.twitter.com/1/statuses/user_timeline/CypressNorth.json?callback=?&count=1';
	$.getJSON(_url,function(data){
		//data is holding a JSON object
	});
}

We now have the timeline back as JSON in the data object.

Building the HTML

Now that we have the status update, we need to display it somewhere. An easy way to do it is to create a <DIV> element with a unique ID for your twitter feed like so:

<div id="twitter-feed"></div>

Using jQuery, you can fill this div with the twitter response:

function loadLatestTweet(){
	var _url = 'https://api.twitter.com/1/statuses/user_timeline/CypressNorth.json?callback=?&count=1';
	$.getJSON(_url,function(data){
		var tweet = data[0].text;
		$("#twitter-feed").html('<p>'+tweet+'</p>');
	});
}

You have successfully retrieved your twitter status update and placed it on the page. The trouble is, it looks terrible and is pretty useless at the moment. Usually when you see a twitter post, it has links to the @Users and #hashtags mentioned in the posts and shows the date stamp of the update.

Parsing the Response

To make the status update more friendly and meaningful, we want to parse out any URL’s, @Usernames, and #Hashtags so that they are links. In addition we want to parse the date stamp of the update into a nice format which links to the original status update. To do that, we have a date parsing function and 3 JavaScript extensions to make our lives easier (thank you to Simon Whatley for the prototype extensions).

//Twitter Parsers
String.prototype.parseURL = function() {
	return this.replace(/[A-Za-z]+://[A-Za-z0-9-_]+.[A-Za-z0-9-_:%&~?/.=]+/g, function(url) {
		return url.link(url);
	});
};
String.prototype.parseUsername = function() {
	return this.replace(/[@]+[A-Za-z0-9-_]+/g, function(u) {
		var username = u.replace("@","")
		return u.link("http://twitter.com/"+username);
	});
};
String.prototype.parseHashtag = function() {
	return this.replace(/[#]+[A-Za-z0-9-_]+/g, function(t) {
		var tag = t.replace("#","%23")
		return t.link("http://search.twitter.com/search?q="+tag);
	});
};
function parseDate(str) {
    var v=str.split(' ');
    return new Date(Date.parse(v[1]+" "+v[2]+", "+v[5]+" "+v[3]+" UTC"));
}

Using these methods we can create a nice looking and helpful status update with ease:

function loadLatestTweet(){
	var _url = 'https://api.twitter.com/1/statuses/user_timeline/CypressNorth.json?callback=?&count=1';
	$.getJSON(_url,function(data){
		var tweet = data[0].text;
		var created = parseDate(data[0].created_at);
                var createdDate = created.getDate()+'-'+(created.getMonth()+1)+'-'+created.getFullYear()+' at '+created.getHours()+':'+created.getMinutes();
                tweet = tweet.parseURL().parseUsername().parseHashtag();
		tweet += '<div class="tweeter-info"><div class="uppercase bold"><a href="https://twitter.com/#!/CypressNorth" target="_blank" class="black">@CypressNorth</a></div><div class="right"><a href="https://twitter.com/#!/CypressNorth/status/'+data[0].id_str+'">'+createdDate+'</a></div></div>'
		$("#twitter-feed").html('<p>'+tweet+'</p>');
	});
}

*Note: The reason for the parseDate() function is to normalize the date format as it is not the same across browsers. If you skip that step it may fail in Internet Explorer (surprise).

Full Solution

Bringing it all together you have the full script ready for use, all you need to do is edit the HTML and CSS to suite your needs.

You can download the script and sample HTML file here: Twitter-Feed-Reader.zip

$(document).ready(function() {
	loadLatestTweet();
}); 

//Twitter Parsers
String.prototype.parseURL = function() {
	return this.replace(/[A-Za-z]+://[A-Za-z0-9-_]+.[A-Za-z0-9-_:%&~?/.=]+/g, function(url) {
		return url.link(url);
	});
};
String.prototype.parseUsername = function() {
	return this.replace(/[@]+[A-Za-z0-9-_]+/g, function(u) {
		var username = u.replace("@","")
		return u.link("http://twitter.com/"+username);
	});
};
String.prototype.parseHashtag = function() {
	return this.replace(/[#]+[A-Za-z0-9-_]+/g, function(t) {
		var tag = t.replace("#","%23")
		return t.link("http://search.twitter.com/search?q="+tag);
	});
};
function parseDate(str) {
    var v=str.split(' ');
    return new Date(Date.parse(v[1]+" "+v[2]+", "+v[5]+" "+v[3]+" UTC"));
} 

function loadLatestTweet(){
	var _url = 'https://api.twitter.com/1/statuses/user_timeline/CypressNorth.json?callback=?&count=1';
	$.getJSON(_url,function(data){
		var tweet = data[0].text;
                var created = parseDate(data[0].created_at);
                var createdDate = created.getDate()+'-'+(created.getMonth()+1)+'-'+created.getFullYear()+' at '+created.getHours()+':'+created.getMinutes();
                tweet = tweet.parseURL().parseUsername().parseHashtag();
		tweet += '<div class="tweeter-info"><div class="uppercase bold"><a href="https://twitter.com/#!/CypressNorth" target="_blank" class="black">@CypressNorth</a></div><div class="right"><a href="https://twitter.com/#!/CypressNorth/status/'+data[0].id_str+'">'+createdDate+'</a></div></div>'
		$("#twitter-feed").html('<p>'+tweet+'</p>');
	});
}

UPDATE API 1.1

To load more than just the latest tweet, modify the loadLatestTweet() function to look like the following (and change the count parameter to the number of tweets you want):

function loadLatestTweet(){
	var numTweets = 1;
    var _url = 'https://api.twitter.com/1/statuses/user_timeline/CypressNorth.json?callback=?&count='+numTweets+'&include_rts=1';
    $.getJSON(_url,function(data){
    for(var i = 0; i< data.length; i++){
            var tweet = data[i].text;
            var created = parseDate(data[i].created_at);
            var createdDate = created.getDate()+'-'+(created.getMonth()+1)+'-'+created.getFullYear()+' at '+created.getHours()+':'+created.getMinutes();
            tweet = tweet.parseURL().parseUsername().parseHashtag();
            tweet += '<div class="tweeter-info"><div class="uppercase bold"><a href="https://twitter.com/#!/CypressNorth" target="_blank" class="black">@CypressNorth</a></div><div class="right"><a href="https://twitter.com/#!/CypressNorth/status/'+data[i].id_str+'">'+createdDate+'</a></div></div>'
            $("#twitter-feed").append('<p>'+tweet+'</p>');
        }
    });
}
Matt Mombrea

Matt Mombrea

Matt is a longtime entrepreneur and software engineer. He also sits on the board of Computer Science at SUNY Fredonia. Born and raised in Buffalo, Matt is passionate about building and maintaining great businesses in Buffalo. Apart from leading Cypress North, Matt architects our company’s datacenter, engineers dozens of custom applications, and directs the rest of the development team.

See Matt's Most Recent Posts

Share this post

27 comments

Thomas van Zuijlen March 19, 2012Reply

Thanks for the easy-to-follow guide, Matt!

Something to take note of with regard to date parsing: The code you’ve posted here, will produce a zero-based month number (e.g. created.getMonth() returns a ‘2’ for March) and a day number based on the day of the week rather than that of the month (e.g. created.getDay() returns a ‘0’ for Sundays).

To hammer out a more human-comprehensible date display, I’ve substituted line 32 of your Full Solution code example with the following:

var createdDate = created.getDate()+’-‘+(created.getMonth()+1)+’-‘+created.getFullYear()+’ at ‘+created.getHours()+’:’+created.getMinutes();

So adding 1 to the month obtained from created.getMonth, and replacing the week-based created.getDay with the month-based created.getDate. Also, I’ve added created.getFullYear() to get the tweet’s year.

The above line results in something like ’19-03-2012 at 15:21′ for March 19th, 3:21 PM.

Hope this is a decent addition to your solution!

Matt Mombrea March 19, 2012Reply

Thanks Tom, I’ve updated the solution with your contribution. I admit the date formatting was done hastily, In the actual project I was using the jQuery DateFormat extension but refactored it out of the example. I should have done more testing!

Thomas van Zuijlen March 19, 2012Reply

Ah, I see. Thanks for the quick reply – and thanks again for the clever solution.

Mike May 7, 2012Reply

I think there might be a typo in the code. When I run the example, I get the following error:

Uncaught SyntaxError: Unexpected token . it seems there is a missing + before
‘created.getHours()+’

It should be ‘+created.getHours()+’

I’m a noob. So forgive me if I’ve just embarrassed myself. 😉

Matt Mombrea May 7, 2012Reply

You are quite right, thanks for the catch. I’ve updated the post as well as the example project.

Eric September 5, 2012Reply

Hey Matt!

First of all, nice work!

I have noticed one thing that’s not working tho(assuming I’ve done it all correctly). If I set the count to, let say, five and on the timeline I’m displaying there are 3 tweets, 1 retweet and then 1 more tweet. The script only displays a total of 4 tweets instead of just showing the next tweet(making it five). Or why not show retweets aswell?

The reason why this is important to me is that I have a client who want to display the 5 latest tweets and I can’t really tell them not to retweet anything or else they’ll mess it up.

Is there a solution for this? Let me know if you need any code etc.

Cheers!
/Eric

Matthew Mombrea September 5, 2012Reply

Eric,

Thanks! This example is not currently set up for multiple tweets, just the latest 1. To modify it to handle more tweets you’ll need to change the function loadLatestTweet(). I’ve added an example to the end of this post.

Eric September 6, 2012Reply

Hey Matt,

Thanks you for the quick response! Your solution worked great but there is still the problem with the feed skipping retweets and thus showing the incorrect tweetcount.

Is this something that can be fixed? Either show all posts on the chosen timeline or continue to pick just the tweets, ignore all the retweets and still show the correct count.

Cheers,
Eric

Matthew Mombrea September 6, 2012Reply

Eric,

My mistake. It doesn’t look like version 1 of the API includes retweets in the feed but does count them toward your max results. I’ve updated the example to use the API v1.1 with the include_rts=1 flag set which seems to work better. I’ve also updated the project file download to reflect this change. I think that should solve the issue for you.

Eric September 7, 2012Reply

Matt,

That’s just great! Thank you so much for your expertice and quick response.

All the best,
Eric

Dave October 1, 2012Reply

Hi, thanks for explaining and sharing! I looked at the .js file and it doesn’t look like you’re using the API 1.1. I’ve been trying to understand how that works because we need to Authenticate to get the data back from Twitter.

Have you been able to make this approach work with the 1.1 API?

Kind regards,
Dave

Adam J October 11, 2012Reply

Thanks so much for this. I’ve been looking for examples of 1.1 recent tweet widgets. This was perfect. They should really have more straightforward documentation on the twitter dev site.

kevin October 11, 2012Reply

Thanks for that, i’ve been looking for a while for a reliable solution. This works just fine.

Johan Danforth October 24, 2012Reply

Hi, good post but you’re not Calling the version 1.1 api, which requires oauth to work. Version 1.0 of the api is said to stop working in april 2013 :/

Sean C January 26, 2013Reply

Thanks for this clear well-written post, but would also love to see an update that addresses the recent 1.1 changes to the Twitter api which requires OAuth.

chris February 18, 2013Reply

How would I go about changing the text colour? I have tried CSS and that changes everything but the hashtag, date and username?

Cheers
Chris

Matthew Mombrea February 18, 2013Reply

Chris,

You can add a css style for the following selector:
#twitter-feed p{color:green;}

Apostolis March 4, 2013Reply

Maybe it’s a bit late for this party guys but a have a noobie question. The first line of code with the https where should I put it? I can imagine after the in terms of getting the data etc. but I can’t put it in a tag because it treats the “//” as a comment in JavaScript language. Sorry I am so new in JavaScript / jQuery.
Cheers!

Matthew Mombrea March 4, 2013Reply

That first code snippet is just an example of the API call that will be made later, it’s not meant to go into your code.

Toward the bottom of this post is a link to the source code for this example that you can download and it should work out of the box.

As a heads up, this method of retrieving twitter timelines via javascript is going to be shut down by twitter very soon and will no longer work.

See here for a follow up: http://www.itworld.com/unified-communications/343649/death-twitter-api-or-new-beginning

Ellis May 3, 2013Reply

Around 150 games in total, but that’s relatively small compared to our users. Don’t leave the landscape designing
and terrain optimization to the last moment. Well, you
can have that same chess engine on your Android
mobile phone, courtesy of Droid – Fish.

Chris H June 11, 2013Reply

Twitter no longer allows unauthorised requests for public tweets.. Any chance we can get an update using oAuth, which is now required?

Cheers.

Tom July 4, 2013Reply

Checkout this post if anyone needs a JavaScript twitter feed and guide that authenticates (via PHP) for public timelines
http://www.webdevdoor.com/javascript-ajax/custom-twitter-feed-integration-jquery/

Alamin August 20, 2013Reply

I have downloaded the zip file but it is not working. Why?

Matthew Mombrea August 20, 2013Reply

Alamin,

This method will no longer work now that Twitter forces API v1.1 with OAuth. Have a look at this proxy you can use to re-enable this functionality: https://github.com/mombrea/twitter-api-php-cached

Th@guy January 30, 2014Reply

You should maybe update this to reference the new API 1.1 OAuth requirements – Or at least make a statement about the update at the top of the post…

Matthew Mombrea January 31, 2014Reply

You mean like the very first statement in a huge title tag at the top of the post? Along with the one at the bottom?

Balu March 26, 2017Reply

Hi Matthew,

I tried to use this functionality but getting below error,
/**/({“errors”:[{“message”:”The Twitter REST API v1 is no longer active. Please migrate to API v1.1. https://dev.twitter.com/docs/api/1.1/overview.”,”code”:64}]});

Can you please suggest the solution for this issue.

Leave a Reply

Search our blog

Start A Project

Categories

What's next?

Well...you might like one of these

Article

Is Google Analytics 4 a Tactical Move...

There’s something fishy going on with the way that Google...

Read article

Article

How We Build It: Website Process with...

This month, I sat down with Matt Mombrea, Chief Technical...

Read article

Article

[SOLVED] Using an in-memory repository....

.NET Core Data Protection One of the main benefits of...

Read article