Posted by theharmonyguy in Facebook | 3 comments
Exporting Your Facebook Feed
The blogosphere has often bemoaned the fact that Facebook provides no RSS feed or similar mechanism for accessing a user’s news feed or mini-feed (now combined with wall posts) outside of Facebook. Other feeds, such as the status updates of friends, are available in RSS via tokenized URLs. Many lifestreaming applications would certainly benefit from access to a user’s actual activity feed instead.
However, such access is not impossible. In browsing the code for the new Facebook layout, I noticed how much AJAX was used in handling the display of feed items on a user’s profile. A bit of analysis revealed that all of the feed items visible on the profile are available via AJAX. By posting the proper variables to a particular URL, you can get the feed items as HTML embedded within some JSON. I’m quite certain that a regex ninja could parse the results into a usable format.
So what’s the catch? Facebook protects against CSRF attacks by adding to forms a variable called “post_form_id” that contains a special hex string. That variable is required to pull off the aforementioned AJAX requests. A simple check of the source code on nearly any Facebook page will allow a user to find his or her current post_form_id (I say “current” without being certain how often it changes – I do know my current one has persisted across the last two sessions).
Now, post_form_id serves an extremely important purpose, and if a non-Facebook page could automatically access it, CSRF attacks would likely be quite simple. Still, I can imagine knowledgable geeks making use of this AJAX hack, if for nothing else than proof-of-concept tools.
To get a quick feel for how this works, check out a simple test page I whipped up. You’ll need your Facebook ID and your current post_form_id, and the page will forward you to either your entire recent feed or recent items posted by you.
By the way, an extra variable called max_time allows one to access past feed items as well. Another AJAX page (http://www.new.facebook.com/ajax/feed.php) gives access to the main news feed, though the format is quite different and I haven’t yet taken the time to explore it much. I do know it includes a time control as well.
Hopefully these tricks will let other developers build some interesting projects. All of the necessary URLs and applicable variables can be found buried in Facebook’s code, but I find the simplest way to discover them is to boot up Wireshark and take note of HTTP POSTs as you click various feed-related links.
Addendum (August 15): Take note that Facebook does check your cookies on these AJAX requests, so you do have to be logged in for the tricks to work. And my post_form_id has changed since I originally posted.
Trackbacks/Pingbacks
- social code - Exporting Your Facebook Feed... Bookmarked your post over at Blog Bookmarker.com!...
- Recent Links Tagged With "csrf" - JabberTags - [...] public links >> csrf Exporting Your Facebook Feed Saved by ZehSebastiaan on Wed 01-10-2008 Grails ...
I may not be doing something right. I get an super long string of nonsensical code when I follow your instructions on the test page. Is this normal?
Also, if I’m reading you correctly, due to the need to have a cookie set, this isn’t something you could set up thru a yahoo pipe, right?
@Mark: You probably are doing it right – you do end up with a long string of code that may appear nonsensical. The code is actually the HTML for your feed, so it includes all sorts of div tags and other info. But it’s also escaped and put inside of a JSON array, so it doesn’t look like straight HTML either.
Not only does this require cookies, but the need for post_form_id means a Yahoo Pipe would be impractical if not impossible. This definitely more proof-of-concept than commercially viable.
I must be doing something wrong too. I enter my email address (above) and my ID and get this:
for (;;);{“error”:1357001,”errorSummary”:”Not Logged In”,”errorDescription”:”You must be logged in to do that.”,”errorIsWarning”:false,”payload”:null,”bootload”:[{"name":"js\/e75qsq5bjbk800cw.pkg.js","type":"js","src":"http:\/\/static.ak.fbcdn.net\/rsrc.php\/zEDR9\/lpkg\/9tkta4k9\/en_US\/141\/157460\/js\/e75qsq5bjbk800cw.pkg.js","permanent":false}],”onload”:["if (window.Env) { Env[\"nectar_last_impression_id\"]=\”379327fe5db7b8deb0c56d5c5651138f\”; }”,”if (window.Env) { Env[\"nectar_last_nav_impression_id\"]=\”\”; }”]}
What am I doing wrong?
Scott