Working with Twitter's 1.1 API via PHP, OAuth

Twitter has been slowly changing up their API over the last few months. When I first set up a cron to pull my Twitter timeline over a year ago I was able to pull a public RSS feed without too much difficulty. If they were over capacity, either just on the API side or with the entire application, my cron would fail once or twice and catch up during the next run. Things changed this fall. The simple cron started failing days, weeks at a time, and I'd have to do a manual fetch from a local IP address to catch up on the missed data. When I looked into it I realized that the public RSS feed wasn't going to work any more and I'd have to catch up with some of Twitter's recent API 1.1 update, namely OAuth.

Now, I'm not an expert on OAuth or Twitter. I spent a good chunk of time doing research on Twitter's API documentation and a variety of different PHP resources (mostly the cURL section on php.net). All I do with my cron is pull my most recent tweets and update a table on my server, which is later used on my lifestream site. Thanks to Twitter's API changes I'd have to register an application, create an OAuth signature, and construct a cURL request to fetch this data. Below is a rough step-by-step of what I did, which you can follow to fetch your own timeline of tweets using PHP and OAuth.

Step 1: Register an Application

The first part is the easiest. After signing into Twitter you can go to the create an application form and fill out some details of your application. After you fill out the form you'll get four strings of data that are important.

  1. Consumer Key

  2. Consumer Secret

  3. Access Token

  4. Access Token Secret

If you have a hard time finding this fields, just click on the 'OAuth Tool' tab on the application detail page (after you've filled out the form, that is).

Step 2: Create an OAuth Signature

Here is where things get a little tricky. When you make the cURL request to Twitter, you'll be passing an array of fields for authentication. One way they make sure that your request is valid is by checking the signature, which is a hash of those fields and your secret OAuth fields. Below is a rough layout of how this signature is created.

  1. $oauth_hash = '';

  2. $oauth_hash .= 'oauth_consumer_key=YOUR_CONSUMER_KEY&';

  3. $oauth_hash .= 'oauth_nonce=' . time() . '&';

  4. $oauth_hash .= 'oauth_signature_method=HMAC-SHA1&';

  5. $oauth_hash .= 'oauth_timestamp=' . time() . '&';

  6. $oauth_hash .= 'oauth_token=YOUR_ACCESS_TOKEN&';

  7. $oauth_hash .= 'oauth_version=1.0';

  8. $base = '';

  9. $base .= 'GET';

  10. $base .= '&';

  11. $base .= rawurlencode('https://api.twitter.com/1.1/statuses/user_timeline.json');

  12. $base .= '&';

  13. $base .= rawurlencode($oauth_hash);

  14. $key = '';

  15. $key .= rawurlencode('YOUR_CONSUMER_SECRET');

  16. $key .= '&';

  17. $key .= rawurlencode('YOUR_ACCESS_TOKEN_SECRET');

  18. $signature = base64_encode(hash_hmac('sha1', $base, $key, true));

  19. $signature = rawurlencode($signature);

Step 3: Construct the cURL Headers

Now that the signature is created you can go ahead and construct the cURL header. The header is very simple, a two-row array, but one of the rows involves all of the OAuth information. Now that the signature is created we can go ahead and put together the OAuth section and finish up the headers.

  1. $oauth_header = '';

  2. $oauth_header .= 'oauth_consumer_key="YOUR_CONSUMER_KEY", ';

  3. $oauth_header .= 'oauth_nonce="' . time() . '", ';

  4. $oauth_header .= 'oauth_signature="' . $signature . '", ';

  5. $oauth_header .= 'oauth_signature_method="HMAC-SHA1", ';

  6. $oauth_header .= 'oauth_timestamp="' . time() . '", ';

  7. $oauth_header .= 'oauth_token="YOUR_ACCESS_TOKEN", ';

  8. $oauth_header .= 'oauth_version="1.0", ';

  9. $curl_header = array("Authorization: Oauth {$oauth_header}", 'Expect:');

As you might be able to guess already, this would look great broken up in functions and/or class methods. The creation of the OAuth signature and OAuth header is very similar, and there are some chunks of the code that would work great in separate containers. I did write my implementation in a specialized cron class with several abstract helpers, which would be difficult to explain in this short tutorial, but this procedural code also works just fine. If you're interested and capable of object-orientated programming, it is pretty easy to break all this up.

Step 4: Make the cURL Request

Everything is in place to make the actual request! I know that this logic all works fine for fetching a timeline. I'm not sure what, if anything, needs to be modified in the headers if you want to do something more complex like posting an update or manipulating followers.

  1. $curl_request = curl_init();

  2. curl_setopt($curl_request, CURLOPT_HTTPHEADER, $curl_header);

  3. curl_setopt($curl_request, CURLOPT_HEADER, false);

  4. curl_setopt($curl_request, CURLOPT_URL, 'https://api.twitter.com/1.1/statuses/user_timeline.json');

  5. curl_setopt($curl_request, CURLOPT_RETURNTRANSFER, true);

  6. curl_setopt($curl_request, CURLOPT_SSL_VERIFYPEER, false);

  7. $json = curl_exec($curl_request);

  8. curl_close($curl_request);

This will pull the mot recent 20 tweets from your timeline! If you have any questions please leave them in a comment below or feel free to reach out to me via twitter (@jpemeric).