ActionScript and the Twitter API, Simplified
The API is one of the best things about Twitter. It gives developers the power to take this mass of accumulated ephemeral chattering and come up with many interesting ways of interacting with the data. But the API has its quirks, which makes accessing it from Flash or Flex a slightly rocky road at times.
The aim of this tutorial is to simplify matters, and get you making your first AS3 Twitter requests (using either Flash or Flex) within a few minutes. I have condensed the process down to three easy steps.

STEP 1: DECIDE WHAT YOU WANT TO ASK
Getting an answer becomes a lot easier once one has decided upon the question.
All requests to the Twitter API are HTTP based, which means they are no more complicated than calling a URL, with certain parameters passed via GET (occasionally POST). This means that before we even need open Flash/Flex we can test most of our API calls in the web browser.
Lets start by reading a user’s timeline. To return the last five tweets by user “zenbullets” you would request …
http://twitter.com/statuses/user_timeline/zenbullets.xml?count=5
… which will return an XML. The “count” variable specifies how many tweets you want returned (to a maximum of 200 currently).
If you want the public timeline, call:
Or, to get a single tweet, reference it by id:
You can also change the file extension from .xml to .json, .rss or .atom to return the data in a different format, eg. RSS:
http://twitter.com/statuses/user_timeline/zenbullets.rss?count=5
More interesting results can be gleaned by performing searches on the public timeline. This involves calling a separate API at http://search.twitter.com/, and passing it a few GET parameters.
Some examples:
http://search.twitter.com/search.atom?q=flashbrighton – all tweets mentioning “flashbrighton”
http://search.twitter.com/search.atom?q=from%3Azenbullets – all tweets from user “zenbullets”
http://search.twitter.com/search.atom?q=flashbrighton+from%3Azenbullets – all tweets from user “zenbullets” that refer to “flashbrighton”
Parameters include “from:”, “OR”, “+” etc., and can be combined to form advanced queries. The full list of operators is here. You’ll notice the parameters need to be URL encoded, eg. “from:” becomes “from%3A”. Two common encodings you might need are “%3A” for the “@” in @replies, or “%23″ for the hash tag “#”.
Note also that search requests can only be returned in either ATOM or JSON format.
Ok, so we’ve got a query, we’ve tested it in the browser. Next we need to request this data from ActionScript.

STEP 2: MAKE THE REQUEST
You know how to make a URL request in ActionScript don’t you? Of course you do.
For the example below I decided I wanted to get a list of all the tweets where one user referred to another:
var _twitterXML:XML; var _user1:String = "zenbullets"; var _user2:String = "yezzer";var urlReq:URLRequest = new URLRequest("http://search.twitter.com/search.atom?q=" + _user1 + "+from%3A" + _user2); var loader:Loader = new Loader(); loader.addEventListener(Event.COMPLETE, SuccessFunc); loader.addEventListener(IOErrorEvent.IO_ERROR, IOError); loader.addEventListener(SecurityErrorEvent.SECURITY_ERROR, SecurityError); loader.load(urlReq);private function SuccessFunc(e:Event):void { if (e.target.data) { _twitterXML = new XML(e.target.data); } }private function IOError(e:Event):void { // handle error }private function SecurityError(e:Event):void { // handle error }
All this does is call a URL on search.twitter.com and place the returned XML into a variable _twitterXML.
This method works fine with any request for unprotected public data. Things get a little more complicated if you want to access any of the functionality available to a logged in user, e.g. posting updates, reading Direct Messages, or accessing your friends timeline. All these feats can be performed by an authenticated user (i.e. one who has logged in). To do this from ActionScript you should use the OAuth protocol to get a login token before making requests.
But this is the “simplified” tutorial, so I’ll leave you to google this for yourselves rather than going off on a tangent here. Twitter also support Basic Access Authentication too, if you are after a quick, hacky (and less secure) solution. The list of methods available to authenticated users can be found within the Twitter API Documentation.
Lets now look at what we can do with the data we get back.
STEP 3: PARSE THE XML
This is probably the trickiest bit. Firstly, the XML is different depending upon which format we have chosen for the data (XML, RSS, ATOM) obviously, but it also differs depending on whether our call was to the Search or REST APIs (ie. search.twitter.com or www.twitter.com). So, in the name of keeping things simple lets just look at one of these cases – a response from the Search API (the most versatile of the two), in ATOM format.
If we analyse the XML returned from the example in Step 2, we can see that, after a bit of header information, the tweets are denoted by a stream of <entry> tags.
<entry> <id>tag:search.twitter.com,2005:1761695534</id> <published>2009-05-11T09:11:28Z</published> <link type="text/html" ... /> <title>Good to see evidence of Midlands New Media http://flashcamp.co.uk/ Tempted to go up to check out the talent. @yezzer @Little_Robot</title> <content type="html">Good to see evidence of Midlands New Media <a href="http://flashcamp.co.uk/"> http://flashcamp.co.uk/</a> Tempted to go up to check out the talent. <a href="http://twitter.com/yezzer">@< b>yezzer</b></a> <a href="http://twitter.com/Little_Robot"> @Little_Robot</a> </content> <updated>2009-05-11T09:11:28Z</updated> <link type="image/png" ... /> <twitter:source>TweetDeck</twitter:source> <twitter:lang>en</twitter:lang> <author> <name>zenbullets (Matt Pearson)</name> <uri>http://twitter.com/zenbullets</uri> </author> </entry>
We might assume that we can access a list of the text of all tweets with a statement like
var _tweetList:XMLList = _twitterXML.entry.title;
But no. I’m afraid it’s not that simple because all of the tags in this XML belong to namespaces. The tag <entry> is actually <http://www.w3.org/2005/Atom::entry>. Don’t worry if you don’t understand namespaces – they are a huge pain in the arse in ActionScript. I’m going to show you a little bit of code to get round them.
It is possible to just rip out the namespaces from an XML, but I find I’m more comfortable filtering out what I need using the rather obscure localName property of XML nodes. This code will loop through the TwitterXML and extract the <entry> tags:
var _tweetList:XMLList = _twitterXML.children(); for (var x:int = 0; x < _tweetList.length(); x++) { if (_tweetList[x].name().localName == "entry") { // it's a tweet, process it } }
The same goes for the elements within the Tweet. We’ll probably be most interested in the <title> and <content> tags, which contain the actual tweet itself in text and HTML formats. Lets add another parsing loop within the previous parsing loop to put these elements into an array.
var _titleArr:Array = new Array(); var _contentArr:Array = new Array(); var _tweetList:XMLList = _twitterXML.children(); for (var x:int = 0; x < _tweetList.length(); x++) { if (_tweetList[x].name().localName == "entry") { var thisTweet:XML = _tweetList[x]; var nodes:XMLList = thisTweet.children(); for (var y:int = 0; y < nodes.length(); y++) { if (nodes[y].name().localName == "content") { _contentArr.push(list[y].text()); } else if (nodes[y].name().localName == "title") { _titleArr.push(list[y].text()); } } } }
And there you have it. You have successfully harnessed your Tweets into arrays, ready to be herded into whatever application you have for them. It’s all worked so far, hasn’t it? HASN’T IT?
BONUS STEP: WHY DOESN’T IT WORK FOR ME …

All of the above should work, and publish to the web without issue. But I have cheated slightly by using search.twitter.com for my example, rather than www.twitter.com. If I were to go the correct API route, and use authenticated requests to the REST methods at www.twitter.com (notice how I glossed over those rather quickly) we would have come up against one final obstacle; Twitter’s cross-domain security restrictions. (search has a much friendlier cross-domain policy)
There are ways to climb every mountain though, and if you have managed to work out authentication, you should have no problem creating a PHP Proxy to bypass the security restrictions.
It’s not as scary as it sounds. It is only Flash Player that is limited by cross-domain policy files. If we make the API request from PHP we can bypass the security restriction.
The following two lines of PHP code will create your proxy service. Name this proxy.php and put it on your server:
<?php $url = $_GET['url']; readfile($url); ?>
Now, instead of calling
http://twitter.com/statuses/user_timeline/zenbullets.xml?count=5
We call
http://yourserver.com/proxy.php?url=http://twitter.com/statuses/ user_timeline/zenbullets.xml?count=5
This is all that is required to fool the cross-domain policy. This, ladies and gentlemen, is what we call a hack.
May 19th, 2009 at 11:25 am
You could simplify your life by just using the Tweetr Library which also already comes with a php proxy to circumvent the crossdomain policy.
http://tweetr.googlecode.com
Greets,
Sandro
June 19th, 2009 at 7:25 pm
Any idea why I would get these errors:
1152: A conflict exists with inherited definition flash.display:DisplayObject.x in namespace public.
June 29th, 2009 at 2:59 pm
Hi, I would like to precise that the actionScript part did not work for me at first until I replaced the Loader Class by an URLLoader class in step 2. Hope it will help others that have the same problem.
STEP 2: MAKE THE REQUEST
var loader:Loader = new Loader();
var loader:URLLoader = new URLLoader();
July 25th, 2009 at 1:26 pm
I had the same issue as Eric. I hit the books to find the answer – wish I’d read his post earlier now!
The Loader class should DEFINITELY be replaced with the URLLoader class.
Thankyou though, this was a great tutorial and very useful to someone who is still transitioning from AS2 to AS3! Thanks!
August 6th, 2009 at 6:36 pm
Hi lads. First off props to Matt for his gr8 post above. Now I don’t usually post these things but I felt compelled to help out. Im not really a dev more a designer so there are most likely correct/better ways to do what Im about to share with you all. I was having problems getting twitter working on my test site but finally came up with 2 ways Im more or less happy with.
Firstly I got the “REST” way working by using a custom php proxy (the one here didn’t work for me). But sadly I found out the hard way that there is a 150 requests per hour per client using rest. So basically I feel this approuch is best used if you’re creating an AIR app. Feel free to tweet me @yelpy if u want my proxy.php or if I can help in any other way I can with this method.
The second way, as Matt explains above is the “search” method. Unfortunately I couldn’t really get the way above to work correctly (Im a bit slow) but I did come up with my own way which I feel might be a bit easier to get the hang of. I’ll share the code below and if anyone has any questions just tweet me again @yelpy. One thing I would like to ask, has anyone else noticed that using the search method seems to leave out random tweets, if u search my tweets and the goto my twitter page you’ll find at least 2 tweets are missing from the search.
Anyway here’s my code below:-
(replace “yourusername” with, well your username)
[code start]
/**** vars ****/
var user:String;
var url:String;
var tweetCount:int;
var tweets:Array;
var times:Array;
/**** setup ****/
user = "yourusername";
tweetCount = 10;
loadTweets();
/**** start getting tweets ****/
function loadTweets()
{
url = "http://search.twitter.com/search.atom?q=+from:"+user+"&rpp="+tweetCount;
var urlReq:URLRequest = new URLRequest(url);
var loader:URLLoader = new URLLoader();
loader.addEventListener(Event.COMPLETE, getTweets);
loader.addEventListener(IOErrorEvent.IO_ERROR, IOError);
loader.addEventListener(SecurityErrorEvent.SECURITY_ERROR, SError);
loader.load(urlReq);
}
function getTweets(e:Event):void
{
if ( e.target.data )
{
tweets = new Array(); times = new Array();
var twitterXML:XML = new XML(e.target.data);
var tweetList:XMLList = twitterXML.children();
var tweetItem:String; var timeItem:String;
for (var i:int = 0; i < tweetList.length(); i++)
{
tweetItem = tweetList[i].*::title;
timeItem = tweetList[i].*::published;
if ( tweetItem != "" )
{
tweets.push(tweetItem);
trace(tweetItem);
}
if ( timeItem != "" )
{
timeItem = timeItem.split("T").join(" - ");
timeItem = timeItem.split("Z").join("");
times.push(timeItem);
trace(timeItem);
}
}
trace(tweets.length);
}
}
function IOError(e:Event):void
{
trace("io error!");
}
function SError(e:Event):void
{
trace("security error!");
}
[code end]
August 10th, 2009 at 6:17 am
This is awesome thanks mate.
I’m getting this error tho:
1120: Access of undefined property list.
August 10th, 2009 at 1:13 pm
Hummm.. well I know twitter has been up & down over the last few days so that may be the reason. The code should work fine if u just copy & paste the whole thing and also change the “username” to whatever, eg: Yelpy
Other than that I’m not really sure what your problem could be be, just make sure ur using AS3 i guess.. lol
August 14th, 2009 at 3:34 pm
Thanks for the script, was just what I have been spending 3 days looking for. Works a treat.
Jamie
August 28th, 2009 at 5:31 pm
Just a question…
How do I post a new comment to mu twitter account?
September 24th, 2009 at 5:06 am
I tried using the code from Step 1 and get the following error right off the bat:
1013: The private attribute may be used only on class property definitions.
October 22nd, 2009 at 11:06 am
Hey Yelpy!
Works cool with me. Thanks a lot man
Aditya
November 27th, 2009 at 3:07 pm
Very nice post!
November 30th, 2009 at 6:28 pm
Hi folks!
Does someone knows where I can find some as3 tutorial explain how to post to twitter accounts?
Regards,
Gustavo
December 30th, 2009 at 4:54 pm
This saved my life man! I can’t thank you enough for the proxy solution!
January 5th, 2010 at 10:36 pm
My example doesnt work, de Console Panel show the following message in loop:
[SWF] /search.atom – 0 bytes after decompression
Thanks for sharing.
January 5th, 2010 at 10:48 pm
Work for me now…a see the Eric Clement commentary, and change the Loader for URLoader.
February 17th, 2010 at 7:15 pm
One glaring problem in the proxy solution… Since the twitter api limits the number of calls you can make from a single IP, the proxy solution will quickly diminish if you have many users accessing your application. Without the proxy, each user will be limited by their own IP, whereas with a proxy, all users will be using your domain’s IP (quickly eating up the 150 allotment).
March 7th, 2010 at 6:54 am
Great tutorial. Thanks for the code.
April 18th, 2010 at 9:22 am
Helpful post. Here is something that works for me for posting to a twitter account. This helped : http://www.cfdan.com/posts/Adobe_AIR_Flex_3_HTTP_Basic_Authentication.cfm
package {
import flash.display.Sprite;
import flash.net.URLRequest;
import flash.net.URLRequestHeader;
import flash.net.URLRequestMethod;
import flash.net.URLVariables;
import flash.net.sendToURL;
import mx.utils.Base64Encoder;
public class Tweet extends Sprite {
public function Tweet() {
var request:URLRequest = new URLRequest(”http://api.twitter.com/1/statuses/update.json”);
var encoder64:Base64Encoder = new Base64Encoder();
encoder64.encode(”user name” + “:” + “password”);
var user_passwd:String = encoder64.toString();
var req_header:URLRequestHeader = new URLRequestHeader(”Authorization”, “Basic ” + user_passwd);
request.requestHeaders.push(req_header);
var variables:URLVariables = new URLVariables();
variables.status = “Tweeting from actionscript.”;
request.data = variables;
request.method = URLRequestMethod.POST;
sendToURL(request);
}
}
}
April 19th, 2010 at 1:05 pm
ArgumentError: Error #2096: The HTTP request header Authorization cannot be set via ActionScript.