Google Reader API series
- Part 1 – Programming to the API
- Part 2 – Listing API
- Part 3 – Editing API
Google have never officially released API documentation for Google Reader, so this information is unofficial and subject to change.
When I first started looking around for API docs to interface with Google Reader, this site seemed to be pretty much the only resource available. Unfortunately a lot of the information in that document is outdated, so I set about trying to figure out the API myself, with some success.
To interface with Google reader, you’ll need to collect the following things from their authentication system:
- SID – A session ID, which remains valid until you log out
- Token – Similar to a session ID, but expires quickly. Used to access direct API calls
- Cookie – An ordinary cookie that uses your SID to authenticate your session on API calls
The code samples I’m using will be in C#, but should be easily translatable to any language.
To get an SID, we send a GET request to https://www.google.com/accounts/ClientLogin with arguments service=reader&Email=[your Google username]&Passwd=[your Google password]
This will return some text with key=value pairs for LSID, SID and User. SID is the only part of this we need, so use your string library to grab this information.
Now that we have an SID we need a token. We send a GET request to http://www.google.com/reader/api/0/token with a cookie we generate from the SID. The cookie information is
- Name: SID
- Value: [your SID]
- Path: /
- Domain: .google.com
This request returns just the token text.
So here is the code I wrote for getting SID and token:
using System.IO;
namespace GoogleReader.NET
{
public class GoogleReader
{
private string _sid = null;
private string _token = null;
private Cookie _cookie = null;
private string _username;
private string _password;
public GoogleReader(string username, string password)
{
_username = username;
_password = password;
connect();
}
private bool connect()
{
getToken();
return _token != null;
}
private void getToken()
{
getSid();
_cookie = new Cookie("SID", _sid, "/", ".google.com");
string url = "http://www.google.com/reader/api/0/token";
HttpWebRequest req = (HttpWebRequest)WebRequest.Create(url);
req.Method = "GET";
req.CookieContainer = new CookieContainer();
req.CookieContainer.Add(_cookie);
HttpWebResponse response = (HttpWebResponse)req.GetResponse();
using (var stream = response.GetResponseStream())
{
StreamReader r = new StreamReader(stream);
_token = r.ReadToEnd();
}
}
private void getSid()
{
string requestUrl = string.Format
("https://www.google.com/accounts/ClientLogin?service=reader&Email={0}&Passwd={1}",
_username, _password);
HttpWebRequest req = (HttpWebRequest)WebRequest.Create(requestUrl);
req.Method = "GET";
HttpWebResponse response = (HttpWebResponse)req.GetResponse();
using (var stream = response.GetResponseStream())
{
StreamReader r = new StreamReader(stream);
string resp = r.ReadToEnd();
int indexSid = resp.IndexOf("SID=") + 4;
int indexLsid = resp.IndexOf("LSID=");
_sid = resp.Substring(indexSid, indexLsid - 5);
}
}
}
}
From here were can make interface calls (I plan to document the complete set of API calls in the very near future, but for now I’ll give a couple of examples). To add a subscription, make an HTTP POST to http://www.google.com/reader/api/0/subscription/quickadd?client=scroll with POST arguments quickadd=[url of feed]&T=[your token] and don’t forget to include your cookie. I wrote a couple of quick helper methods for making POST and GET calls first:
{
string url = string.Format("{0}?{1}", requestUrl, getArgs);
HttpWebRequest request = (HttpWebRequest)WebRequest.Create(url);
request.Method = "GET";
request.CookieContainer = new CookieContainer();
request.CookieContainer.Add(_cookie);
try
{
return (HttpWebResponse)request.GetResponse();
}
catch
{
// handle error
return null;
}
}
private HttpWebResponse httpPost(string requestUrl, string postArgs)
{
byte[] buffer = Encoding.GetEncoding(1252).GetBytes(postArgs);
HttpWebRequest request = (HttpWebRequest)WebRequest.Create(requestUrl);
request.Method = "POST";
request.CookieContainer = new CookieContainer();
request.CookieContainer.Add(_cookie);
request.ContentType = "application/x-www-form-urlencoded";
request.ContentLength = buffer.Length;
Stream PostData = request.GetRequestStream();
PostData.Write(buffer, 0, buffer.Length);
PostData.Close();
try
{
return (HttpWebResponse)request.GetResponse();
}
catch
{
//handle error
return null;
}
}
Now for the add subscription code:
{
string data = String.Format("quickadd={0}&T={1}", feedUrl, _token);
string url = "http://www.google.com/reader/api/0/subscription/quickadd?client=scroll";
HttpWebResponse response = httpPost(url, data);
if (response == null) return false;
return true;
}
We can add a label to a feed by POSTING to http://www.google.com/reader/api/0/subscription/edit?client=scroll with arguments a=user/-/label/[new label]&s=feed/[feed url]&ac=edit&T=[token] like so:
{
string data = String.Format
("a=user/-/label/{0}&s=feed/{1}&ac=edit&T={2}", label, feedUrl, _token);
string url = "http://www.google.com/reader/api/0/subscription/edit?client=scroll";
HttpWebResponse response = httpPost(url, data);
if (response == null) return false;
return true;
}
There are of course listing methods for getting feeds. So far I’ve only been able to figure out how to get feed information in JSON format, but if anyone knows how to grab XML data please leave a comment. To list items we send a GET request to http://www.google.com/reader/api/0/stream/contents/user/-/state/com.google/reading-list?ck=[current UNIX time] . Of course there are many more otpional arguments for all of these methods, which I will be documenting. Here’s the list code:
{
string url = string.Format
("http://www.google.com/reader/api/0/stream/contents/user/-/" +
"state/com.google/reading-list");
string args = string.Format
("ck={0}", getUnixTimeNow());
HttpWebResponse response = httpGet(url, args);
Stream str = response.GetResponseStream();
StreamReader sr = new StreamReader(str);
string s = sr.ReadToEnd();
// Handle JSON data in s
sr.Close();
}
getUnixTimeNow() is a small helper method I wrote for getting the current Unix time:
{
TimeSpan ts = (DateTime.UtcNow - new DateTime(1970, 1, 1, 0, 0, 0));
long unixTime = (long)ts.TotalSeconds;
return unixTime;
}
This has been a small taste of what’s to come as I work my way through this API. Stay tuned for more. If you want to get hacking on it yourself, the easiest way is to download Fiddler, a great web debugging tool, and watch the HTTP requests as you use Google Reader.
Part 2 now available.
By Martin Doms : Using the Google Reader API – Part 1 August 15, 2009 - 12:25 pm
[...] Martin Doms : Using the Google Reader API – Part 1 [...]
By Daniel September 17, 2009 - 6:43 am
Hey, thanks for all of this great information. Are you still able to get your tag editing functions to work? I’ve been working on a reader client and have had a pretty smooth time other than with marking items with tags such as “read” and “starred.” Even though I seem to be replicating the necessary POST data exactly, I always get an “invalid stream name” message. Since there’s so little information out there on the unofficial API, I thought I’d ask for your thoughts. Thanks again!
By Vitaly September 30, 2009 - 6:26 am
Great article! Thanks much.
I’ve been trying to rewrite your code in JavaScript, so JSON format is perfect for me.
But I can’t get the getToken to work. BTW, I don’t have to worry about same domain policy.
So I parse the strings from the first request, get the SID, save it to a cookie and then request the token. But this one doesn’t go through. Any thoughts why this may be?
By Vitaly September 30, 2009 - 6:59 pm
Never mind, I was sending the wrong cookie, should have been
document.cookie = “Name=SID;SID=#{SID};Domain=.google.com;Path=/;Expires=160000000000″;
By Vitaly October 1, 2009 - 12:44 am
Nope. I was mistaken. That didn’t help. I sent headers in my previous request, and all subsequent worked for a while, so I assumed cookie worked, while it actually didn’t.
So the question stays.
By Martin Doms : Using the Google Reader API – Part 2 October 16, 2009 - 4:06 pm
[...] this is your first foray into using the Google Reader API then you’ll want to read my previous post which describes how to acquire a valid token and cookie, and make calls to the API. Unlike part 1 [...]
By Martin Doms October 16, 2009 - 4:12 pm
Hi Vitaly, sorry for my late reply but I’ve been insanely busy at university
If the request is working intermittently, have you tried renewing the token and creating a new cookie? Those tokens will expire in time. If you find a solution I’d be interested to hear it.
By Matt Behrens October 28, 2009 - 7:50 am
Hey, thanks for the more recent write up compared with that Google Code wiki. It definitely helped! I managed to get my own version working in Python.
http://github.com/askedrelic/Google-Reader-API
By Martin Doms : Using the Google Reader API – Part 3 January 20, 2010 - 11:07 am
[...] Part I I went over how to program for the HTTP POST requests so for now I’ll just go over the API. [...]
By Google Reader Upgrade Causing Issues For Some Users | iTech Report January 20, 2010 - 1:44 pm
[...] no official API for Google Reader yet, but many developers have begun using an unofficial API – which has been documented by developers using reverse-engineering. It was thought that we [...]
By Parsing Json using F# April 28, 2010 - 10:28 am
[...] the API for that service yet. Yuck. But there are a couple of people out there (like here and here) who have picked it apart using fiddler or some such [...]
By Google Reader API – A Brief Tutorial | Mindshare Strategy May 22, 2010 - 3:10 am
[...] the best tutorial I could find online (and the one recommended by Stack Overflow users) was written for C# … WordPress runs in PHP. [...]
By 1834 June 3, 2010 - 2:00 pm
[...] Google Reader, or any RSS reader. Google Reader has an API, which developers could utilize to create to-print functionality [...]
By Pulling Starred Posts From Google Reader « Doom Stick June 18, 2010 - 9:12 am
[...] Google Reader does not, to my knowledge, have a public API. I got all the required information from Martin Doms. The examples have been translated to PHP. I don’t claim that this code is necessarily all [...]
By My daily readings 06/18/2010 « Strange Kite June 18, 2010 - 11:31 pm
[...] Martin Doms : Using the Google Reader API – Part 1 [...]
By JimBob June 27, 2010 - 11:22 pm
Just tried the first code segment (getting the sid and token)… i am getting a 403 error from the server… any ideas?
The sid is retrieved, but the token get doesn’t work.
This code was working the other day.
By Itsik June 29, 2010 - 9:24 am
Just like JimBob, my code was working fine until something happened during the last week or so, it’s getting the SID but when requesting the token I get a 403 forbidden error. Anyone knows what changed and how to fix it?
By Rekkeb June 30, 2010 - 9:23 pm
Hi boys, if you are getting the 403 forbidden error is because this authentication method (SID) has been deprecated by Google. SID parameter is no longer used to let the user to authenticate himself. You have to use Auth parameter. This parameter is included into the response when you send your first request with the username and password. Look for GoogleLogin header parameter.
Hope this can help you.
By Justin Long July 1, 2010 - 3:26 am
HI, I’m wondering if you’ve updated this for the new OAuth process? I’m having difficulty getting functionality to work to retrieve the token from reader/api/0/token (although everything else works just fine).
By Martin Doms July 6, 2010 - 10:09 am
Hi guys, sorry I simply haven’t had time to update the article to reflect the API changes. In the comments for part 3 ( http://blog.martindoms.com/2010/01/20/using-the-google-reader-api-part-3/ ) Andy kindly offered a solution which I intend to incorporate into this article very soon. Thanks for keeping me updated.
By Antoine B July 29, 2010 - 3:17 am
Hello Martin,
You’ve said:
“Hi guys, sorry I simply haven’t had time to update the article to reflect the API changes. In the comments for part 3 ( http://blog.martindoms.com/2010/01/20/using-the-google-reader-api-part-3/ ) Andy kindly offered a solution which I intend to incorporate into this article very soon. Thanks for keeping me updated.”
Any news?:)
Bye,
By Martin Doms July 29, 2010 - 9:58 am
I actually spent a couple of hours on Tuesday trying to get my head around Google’s new OAuth system, but found it is limited in some very frustrating ways that preclude building a proper Google Reader API library. I’ll keep exploring to see what I can come up with. In the mean time Andy’s solution in part 3 will work, but I suspect not for very long. Google looks to be going OAuth for everything.
By Antoine B July 29, 2010 - 9:16 pm
What do you think about http://code.google.com/p/devdefined-tools/wiki/OAuth?
If i understand, the authenfication processes will be changed ?
What about the part 2 (Part 2 – Listing API ) of your post?
Thanks,
By SR August 1, 2010 - 6:03 pm
hello,
from the code above, i am able to get the sid. but as i go to fetch the token with the sid it gives following error
“The remote server returned an error: (403) Forbidden”
can anyone suggest what am i suppose to do??
By SR August 1, 2010 - 7:41 pm
The article has helped alot to me, thankyou v much.
but me still stuck !!
cannot get feeds from the account which has only googlereader but no gmail account!!
I can get the feeds from the account having both gmail and googlreader but not from googlreader
Plz help!!
By Emmanuel September 25, 2010 - 3:41 am
hi all,
i get a 403 error
function : gettoken
line : HttpWebResponse response = (HttpWebResponse)req.GetResponse();
if you have any idea
thx a lot
By supra skytop November 4, 2010 - 3:03 pm
Do not, for one repulse, give up the purpose that you resolved to effect.
By supra skytop November 4, 2010 - 3:13 pm
The man with a new idea is a crank until the idea succeeds.
By mazatlan escorts December 4, 2010 - 8:32 am
Life goes on…
In three words I can sum up all I have learned about life: It goes on….
By Rob December 13, 2010 - 8:43 am
I am also getting a 403 error. First you need to escaped any symbols in your username and password fields, otherwise you wont be able to get an SID, but I when the code tries to get a token with the SID that was geenrated, I get a 403 error on the response. Has anyone resolved this issue?
By code masteer December 14, 2010 - 10:53 am
Dont think this works.
See http://groups.google.com/group/fougrapi/browse_thread/thread/e331f37f7f126c00 with the authentication changes
By I have over 10,000 shared items in Google Reader. What are my options for export? - Quora January 4, 2011 - 6:47 pm
[...] it to exactly the first url you use like this &c=CLDFmdS-mpYCcheck this out for more info. http://blog.martindoms.com/2009/…Insert a dynamic date hereCannot add comment at this [...]
By How does Feedly get data from Google Reader? - Quora February 3, 2011 - 4:49 am
[...] believe it uses the undocumented API of Google Reader. Information about the API can be found here: http://blog.martindoms.com/2009/… or here: http://stackoverflow.com/questio…Insert a dynamic date hereView All 0 CommentsCannot add [...]
By Prashant February 25, 2011 - 8:21 pm
i want this same fuctionality in java. m not able to convert this code in java as i m totally new in field.
By Prashant February 25, 2011 - 8:24 pm
i want java code in core java only because i want to use this code in android.
By Nicolas March 22, 2011 - 3:20 pm
That’s a great doc that you wrote ! Thanks to your work, Andy’s comment to support oAuth, and the “unofficial Google Reader API for Java” project, I’ve written a small Google Reader C# API using Json.Net to serialize/deserialize to proper classes.
For those who may be interested, code is available here: https://sourceforge.net/projects/greadi/
By Ninayan W.I.P.(25) | 程序的野望 April 5, 2011 - 3:18 am
[...] 这两天在给Ninayan添加Google Reader支持。Google Reader是Google众多服务中少数几个不开放官方API的服务之一,但仍然有众多第三方的客户端或官网增强辅助工具出现。好在有几个很好的人,把他们研究Google Reader的成果公布出来了,我主要参考这篇和这篇文档,再加上自己通过抓包工具观察官网的行为,现在基本已经得到实现一个Google Reader客户端所需要的所有资料。 不过现在有点头疼的是,要把Google Reader强塞到已经比较完整紧凑的架构中去,有不少需要调整的地方。比如新增一种账号类型,这种类型的账号就不同于以往的SNS账号,总之整个继承体系都被我修改过了。然后是界面交互的部分,也需要做不少的设计。 还有一点感受是,这个API不知道是不是Google本身的风格如此(我没用过Google其他服务公开的API,所以没有经验),还是说根本就没为第三方开发好好设计过,总感觉不太好用,虽然功能上都能实现,但不太方便。 [...]
By [C++] Using Google Reader API through Poco library | ~No Magic,Just Basic ~ May 15, 2011 - 5:04 pm
[...] [2] Martin Doms : Using the Google Reader API – Part 1 [...]
By Google Reader API resources | Drinking from the Firehose June 21, 2011 - 5:43 pm
[...] Martin Doms [...]
By Hacking Google Reader API | LAMPlights August 4, 2011 - 6:22 pm
[...] Using the Google Reader API [...]
By Littlesnail August 12, 2011 - 1:37 am
Below is new get token code:
private void getToken()
{
getSid();
web_cookie=new Cookie(“SID”, _sid, “/”, “.google.com”);
web_cookie.Expires = new DateTime(2013, 12, 31);
string url = “http://www.google.com/reader/api/0/token”;
//Result.InnerText +=”header is”+strheader;
HttpWebRequest req = (HttpWebRequest)WebRequest.Create(url);
req.Method = “GET”;
req.ContentType=”application/x-www-form-urlencoded”;
req.Headers.Add(string.Format(“Authorization: GoogleLogin auth={0}”, _auth));
try{
HttpWebResponse response = (HttpWebResponse)req.GetResponse();
using (var stream = response.GetResponseStream())
{
StreamReader r = new StreamReader(stream);
_token = r.ReadToEnd();
Result.InnerText+=”Token”+_token.ToString();
}
}
catch
{
Result.InnerText=”Fail to get token!”;
}
}
By Java에서 Google Reader 연동하기 | MindColored October 13, 2011 - 2:55 pm
[...] 그러다가 찾은 사이트. http://blog.martindoms.com/2009/08/15/using-the-google-reader-api-part-1/ [...]
By John Black November 14, 2011 - 3:34 am
Hi there thanks for the great work, although im having trouble adding a feed. once ive connected, i seem to be getting a 401 exception unauthorized when trying to add a feed. any ideas?
thanks
By c December 29, 2011 - 11:44 pm
I’m trying to implement a method that will allow a user to input the url of the feed he would like to subscribe to using the methods above (AddFeed and httpPost). however, false is always being returned. has there been any changes in the api that maybe effect the url that must be inputted for the subscription please?
thanks
By adi January 11, 2012 - 1:28 am
Hi,
It is great to have such a detailed article, i am using it to retrieve all articles i have subscribed. but what i want to do is, read all articles which are not read yet, once i read them or parse them i want to mark it as read so that in next iteration of reading articles it wont show the once i have read.
Please let me know how i can achieve this goal using c# thanks!
By Integrating Google Reader with Outlook » Kodiak’s Korner - My Little Corner of the Net July 5, 2012 - 12:16 pm
[...] create my own. Google has not published an API for reader, but based on the research of Martin Doms, it appears that such an interface may have once been an intent. With the Help [...]
By Google Reader 相關新聞 與 替代方案彙整 | Tsung's Blog March 26, 2013 - 6:43 am
[...] Using the Google Reader API – Part 1 [...]
By pgtycherfdk April 10, 2013 - 3:40 pm
LouisVuittonBagsIsTheFirstChoice,[url=http://www.vuittontenpo.com/]ルイヴィトン バッグ[/url],AnOpportuneGuideToAttainingDiscountLouisVuittonBagsOnline,http://vuittontenpo.com/,LouisVuittonStoreGeorgia:LvBags
By quvrorhd April 10, 2013 - 4:06 pm
hecq [url=http://www.montecosrl.it/swarovskigioielli.html]swarovski crystal sale[/url] [url=http://www.itosweb.com/swarovski-crystal.html]swarovski jewelry[/url] lipk
[url=http://www.montecosrl.it/swarovskigioielli.html]swarovski jewelry outlet[/url] [url=http://www.itosweb.com/swarovski-crystal.html]swarovski crystal[/url] wfsp
[url=http://www.montecosrl.it/swarovskigioielli.html]swarovski crystal sale[/url] [url=http://www.itosweb.com/swarovski-crystal.html]swarovski jewelry[/url] fqah
[url=http://www.montecosrl.it/swarovskigioielli.html]swarovski crystal[/url] [url=http://www.itosweb.com/swarovski-crystal.html]swarovski outlet[/url] uhpd
uiek
nfic
skql [url=http://www.montecosrl.it/swarovskigioielli.html][/url] [url=http://www.itosweb.com/swarovski-crystal.html][/url]