Last week I finally got around to doing something I've long intended: I moved all my RSS feeds into Google Reader and finally said goodbye to Bloglines. More interesting things have been coming from Google's direction lately, and though there's a public beta of a new version of Bloglines it's been feeling stagnant. The final tipping points for me were the ASP errors the mobile version's byte-trimming service has been issuing up for the past few weeks. So I switched, and after a very brief learning curve, I'm glad I did.

Aside from a nice iPhone-optimized version, one of the new toys I picked up in the switch is an unofficial Google Reader API. It's been in an unofficial state for a whole three years now, with no sign of an actual release, so documentation is sparse at best. This wiki seems to be the definitive source, and for non-programmers like myself, it's mind-bendingly vague.

One of the speculative reasons for the lack of an official release is the authentication currently necessary to log in and start using the API, and that proved to be exactly what I've spent the past few days banging my head against. Unless my Google-fu has weakened, there doesn't appear to be much publicly-available code for using the API, and virtually nothing in PHP. So I figured I'd share what I came up with.

This is a script for logging in with your own account and pulling out your latest unread items in the form of an Atom feed. Drop the script on your server, change the login id and password, and it should work as intended. I haven't explored much yet, and probably will never do anything beyond read-only, so you're on your own past this point. But hopefully it'll save someone a few hours anyway.

// ---------------------------------------- // Google Reader Authentication in PHP // a basic script to get you in the door of // Google's unofficial Reader API // by Dave Shea, // ---------------------------------------- // cobbled together from notes on: // // these are the urls we'll need to access various services $urlAuth = ""; $urlAtom = ""; // our array of login data $login = array( "service" => "reader", "continue" => "", // Google id-only of the account holder // ie. for, just use example "Email" => "google-id", // the account's password in plaintext "Passwd" => "password", // an identifying name for your script, can be anything "source" => "my reader script", ); // first step is to authenticae // let's build a POST request using the login data array $postRequest = ""; foreach($login as $field => $value) { $postRequest .= $field . "=" . $value . "&"; } // start buffering what we get back ob_start(); $ch = curl_init($urlAuth); curl_setopt ($ch, CURLOPT_POST, true); curl_setopt ($ch, CURLOPT_POSTFIELDS, $postRequest); curl_setopt ($ch, CURLOPT_FOLLOWLOCATION, true); curl_exec ($ch); curl_close ($ch); // throw the buffer into a variable $loginResult = ob_get_contents(); ob_end_clean(); // we just received three lines of ugliness to contend with. // each line is a huge string preceded with an ID // the IDs are: SID, LSID, and Auth; we only want SID // let's use some string parsing to weed it out if ($i = strstr($loginResult, "LSID")) { $SID = substr($loginResult, 0, (strlen($loginResult) - strlen($i))); $SID = rtrim(substr($SID, 4, (strlen($SID) - 4))); } // so we've found the SID // now we can build the cookie that gets us in the door $cookie = "SID=" . $SID . ";; path=/; expires=1600000000"; // this builds the action we'd like the API to perform // in this case, it's getting our list of unread items $action = $urlAtom . "/user/-/state/"; // note that the hyphen above is a shortcut // for "the currently logged-in user" // start buffering what we get back ob_start(); $ch = curl_init(); curl_setopt ($ch, CURLOPT_URL, $action); curl_setopt ($ch, CURLOPT_HTTPGET, true); curl_setopt ($ch, CURLOPT_COOKIE, $cookie); curl_exec ($ch); curl_close ($ch); // throw the buffer into a variable $xml = ob_get_contents(); ob_end_clean(); // and finally, let's take a look. echo $xml;