reddit API Part 1: Logging In

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)
Tagged , , , , , , , . Bookmark the permalink.

14 Responses to reddit API Part 1: Logging In

  1. Sachin says:

    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?

    • Tankor Smash says:

      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

  2. Anonymous says:

    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

    • Tankor Smash says:

      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.

  3. Matt Adams says:

    Thanks for this tutorial!
    One little thing: you never actually use the headers variable. Did you mean to do client = requests.session(headers=headers)?

    • Tankor Smash says:

      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!

  4. Brian Hanna says:

    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.

    • Tankor Smash says:

      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

      • Nile says:

        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

        • Tankor Smash says:

          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!

  5. Core123 says:

    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.

    • Tankor Smash says:

      Thanks! They’ve been changing around the reddit API a bunch recently, so this might be a bit out of date.

  6. Sevena says:

    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!

Leave a Reply

Your email address will not be published.

You may use these HTML tags and attributes: <a href="" title=""> <abbr title=""> <acronym title=""> <b> <blockquote cite=""> <cite> <code> <del datetime=""> <em> <i> <q cite=""> <strike> <strong>