Welcome to the first part of my reddit API tutorial for Python 2.7! In this short tutorial we will just focus on signing in to reddit’s API so we can interact with it later.
Hopefully you’ve read the introduction on the modules we’ll be using found here, so if you’re a beginner, you won’t be that lost.
Before we start, I am just going to give you a brief overview of what we are going to do: create a python DICT that has your reddit account name and password in it, so that we can send it to the API with our request. Then, armed with our modhash that we received from the API, we can move on to interacting with reddit, which we’ll check out in the next part of this tutorial!
Tinypaste of the entire code as seen at the bottom of the page
Hit the jump for how to login to the reddit’s API. As usual, the full code will be shown at the end of this page.
First things first: the imports. We are going to import the usual networking tools, requests, json, as well as the ever useful pprint module.
import requests import json from pprint import pprint
Now that we’ve imported the right modules, we can set what our username and password to, for easy access later on in the code. With having them both at the top of the file here, we can just make quick and painless edits in one spot instead of having them all hardcoded all over the script.
#set username and password values username = 'YOURUSERNAME' password = 'YOURPASSWORD'
Next, we create a python dict to pass as a data argument to the POST request we are going to be making. That way, the API knows what our username and password is, and can hand us the right person’s modhash. You’ll notice a strange 3rd item in the dict, it’s used to tell what kind of data we are expecting the API to send to us. Usually, it defaults to xml, but I prefer to use JSON since it’s very easy to work with.
#create dict with username and password user_pass_dict = {'user': username, 'passwd': password, 'api_type': 'json'}
Now we set the user-agent of the API. The reddit guys kindly ask us to describe our API, so that they can have a decent idea of what it is trying to do. Typically, a user-agent lets any given site know what browser you’re using, or if you’re on a mobile phone, that sort of thing. Make sure you don’t try to spoof a browser, since that’d get you banned pretty quick, as far as I can tell.
#set the header for all the following requests headers = {'user-agent': '/u/TankorSmash\'s API python tutorial bot', }
Next up is the creation of a Session instance, which is useful to us here because it automatically takes care of any cookies in the responses, and we can assign attributes to it, like we will later with the user’s modhash. You can use a session instance to call session.get , session.put , and session.post functions just like the module functions.
#create a requests.session that'll handle our cookies for us client = requests.session() client.headers=headers
Now we actually make the session.post call here to the URL specified in the API docs, along with the dictionary we made that contains your username, password, and the type of response you are looking for (json, for this tutorial). The session.post function returns the response, which we store as r , so we can manipulate it later, to extract the JSON later.
#make a login request, passing in the user and pass as data r = client.post(r'http://www.reddit.com/api/login', data=user_pass_dict)
Using the text attribute from the response we saved as r, we can read the string of text the API returned to us. If everything worked correctly, it should be a JSON in string format. Assuming it is a valid response(you can create the proper error handling, if you would like), we convert the returned JSON into a native Python dict using the json module’s loads function and save it as j.
#turns the response's JSON to a native python dict j = json.loads(r.content)
Finally, we find the modhash key inside the data dict inside the json in the j . That might sound complicated, but once you look around in j for yourself, using the pprint function, you’ll see that it’s actually pretty compact.
#grabs the modhash from the response client.modhash = j['json']['data']['modhash']
And there you have it, you’ve signed into the reddit API, using Python 2.7 with the great requests module. Wasn’t so bad eh? Next up, we’ll take a crack and grabbing all of a user’s relevant data, like their date of registration and all that juicy karma they’ve acquired. Below is the commented tt in full, with extra debugging strings tossed in.
#importing all the modules from pprint import pprint import requests import json #set username and password values username = 'YOURUSERNAME' password = 'YOURPASSWORD' #create dict with username and password user_pass_dict = {'user': username, 'passwd': password, 'api_type': 'json',} #set the header for all the following requests headers = {'user-agent': '/u/TankorSmash\'s API python tutorial bot', } #create a requests.session that'll handle our cookies for us client = requests.session() client.headers=headers #make a login request, passing in the user and pass as data r = client.post(r'http://www.reddit.com/api/login', data=user_pass_dict) #optional print to confirm error-free response #pprint(r.content) #turns the response's JSON to a native python dict j = json.loads(r.content) #grabs the modhash from the response client.modhash = j['json']['data']['modhash'] #prints the users modhash print '{USER}\'s modhash is: {mh}'.format(USER=username, mh=client.modhash)
I have just started using it to build something of my own. I am unable to find how I can get the dat/time when a link or a comment has been posted. The json response has “created_utc” (ex.1342565632.0) and “created” (ex.1342590832.0) fields but I am not sure they are correct. The reason I say this is because the values returned, when converted to date (in java) show a date in Jan 1970. I need help with understanding this date. Am I even looking at the right field?
That’s strange, are you sure that you’re passing the number in as seconds instead of milliseconds? When I do the following in Python 2.7:
import time
created_utc = time.ctime(1342590832)
print create_utc
I get: ‘Wed Jul 18 01:53:52 2012’. Otherwise yeah, it may be that you’re passing it wrong to Java somehow
I thought I’d point this out even though most people who are doing this will already know, but …
#create dict with username and password
user_pass_dict = {‘user’: username,
‘passwd’: password
‘api_type’: ‘json’,}
You have a comma after ‘json’ and not after password.
E
Oh good catch, thanks for that. Was probably just a matter of editing it for the blog or something. If you’ve got any features of the API that you’d like to see covered, let me know.
Thanks again for the correction.
Thanks for this tutorial!
One little thing: you never actually use the
headers
variable. Did you mean to doclient = requests.session(headers=headers)
?Glad you liked it! You’re right, I’ll fix that right now. Is there any other part of the API you’d like a tutorial for?
Sorry about the long delay for the reply!
I’m having a bit of trouble with that part of the code–I’m using
requests.session(headers=headers)
, but I’m getting the following error:TypeError: __init__() got an unexpected keyword argument 'headers'
I’m using v1.03 of the requests module, installed via pip on Windows 7.
I’ll have to make the change, the tutorial was written for requests 0.4.0.
You’ll have to do something like session.config(headers=headers) but I’m not quite sure yet, haven’t tried the new requests update. edit: Looks like it has to be session.headers = headers, but you’ll have to try it for yourself, and let me know! This is where I looked https://github.com/kennethreitz/requests/blob/master/requests/sessions.py#L141
Hey,
Just wanted to say for those having trouble the
client=requests.session(headers=headers)
line, doesn’t actually take any arguments. Looking at the code for Sessions on GitHub, it looks like the new constructor doesn’t take any arguments. I used this
client=requests.session()
client.headers=headers
It worked but it also worked without the second line strangely enough. I guess Reddit doesn’t automatically block requests that don’t have a user agent
Thanks, I have to update the tutorial, I wrote this back for requests 0.4.0 I think, and back then, session objects could take arguments. Thanks for letting me know!
Hi, r.text did not work. I had to replace it with r.content. And for the url I have found some people suggesting https://ssl.reddit.com/api/login.
Thanks for the tutorial.
Thanks! They’ve been changing around the reddit API a bunch recently, so this might be a bit out of date.
This is an amazing tutorial! I’m new to python and I found this to be really helpful. I like the step by step explanations and the style is very clean! 🙂 I would love to see more of these!
Happy to help!
Hi 🙂
Not sure if this is monitored but your api url is out-of-date. This seems to work:
#make a login request, passing in the user and pass as data
r = client.post(r’https://ssl.reddit.com/api/login’, data=user_pass_dict)