cURL wrapper class for PHP (How to easily use PHP cURL)

March 1, 2013 by Asbra — 6 Comments

Since I use cURL alot for different PHP-projects, I’ve written up this handy PHP cURL class that I use.

I will show you how easily you can use this class to fetch data from websites, scrape website, and how to log in to Facebook using cURL. You can also use it to read RSS-feeds, create bots to automate tasks such as registering on websites, monitoring/playing browser-based games for you (which we will delve deeper into later) etc. ๐Ÿ™‚

You can download the class here; PHP cURL wrapper [GitHub]

First of all, here is the entire class

<?php
/* cURL helper class
 * Author:  Johan / Asbra.net
 * Created: 2011-02-19
 * Updated: 2011-07-27
 * Updated: 2011-09-10
 * Updated: 2011-10-04
 * Updated: 2012-07-21
 * Updated: 2013-01-15
 * Updated: 2013-02-04
 */

class cURL
{
  private $useragent; // user agent string
  private $handle;    // handle to the cURL object
  private $cookies;   // boolean value whether to use/store cookies or not
  private $redirs;    // boolean value whether to follow redirects or not
  public $cookiejar;  // filename of the cookie jar
  public $data;       // last data returned from a cURL transfer
  public $code;       // the last HTTP code returned
  public $url;        // URL of the page we are currently at
  public $info;       // information about the last cURL transfer
  private $proxy;     // proxy adress
  private $proxypwd;  // proxy password
  public $xhr;        // boolean value whether to use XHR (XMLHttpRequest) or not

  function __construct( $redirs = true, $cookies = true, $useragent = 'Mozilla/5.0 (Windows NT 6.1; WOW64; rv:13.0) Gecko/20100101 Firefox/13.0' )
  {
    $this->useragent = $useragent;
    $this->handle    = null;
    $this->cookies   = $cookies;
    $this->redirs    = $redirs;
    $this->cookiejar = 'cookies.txt';
    $this->proxy     = '';
    $this->proxypwd  = '';
    $this->xhr       = false;
  }

  public function set_proxy( $proxy, $auth = '' )
  {
    $this->proxy    = $proxy;
    $this->proxypwd = $auth;
  }

  private function setopt( $url, $referer )
  {
    curl_setopt( $this->handle, CURLOPT_URL, $url );
    curl_setopt( $this->handle, CURLOPT_HEADER, 0 );

    if( $this->redirs )
    {
      curl_setopt( $this->handle, CURLOPT_FOLLOWLOCATION, 1 );
      curl_setopt( $this->handle, CURLOPT_MAXREDIRS, 10 );
    }
    else
    {
      curl_setopt( $this->handle, CURLOPT_FOLLOWLOCATION, 0 );
      curl_setopt( $this->handle, CURLOPT_MAXREDIRS, 0 );
    }

    curl_setopt( $this->handle, CURLOPT_RETURNTRANSFER, 1 );
    curl_setopt( $this->handle, CURLOPT_USERAGENT, $this->useragent );

    if( substr( $url, 4, 1 ) == 's' )
    {
      curl_setopt( $this->handle, CURLOPT_SSL_VERIFYPEER, false );
      curl_setopt( $this->handle, CURLOPT_SSL_VERIFYHOST, false );
    }

    if( $this->cookies )
    {
      curl_setopt( $this->handle, CURLOPT_COOKIEJAR, $this->cookiejar );
      curl_setopt( $this->handle, CURLOPT_COOKIEFILE, $this->cookiejar );
    }

    if( $this->proxy != '' )
    {
      curl_setopt( $this->handle, CURLOPT_PROXY, $this->proxy );

      if( $this->proxypwd != '' )
      {
        curl_setopt( $this->handle, CURLOPT_PROXYUSERPWD, $this->proxypwd );
      }
    }

    if( $referer != '' )
    {
      curl_setopt( $this->handle, CURLOPT_REFERER, $referer );
    }

    if( $this->xhr == true )
    {
      curl_setopt( $this->handle, CURLOPT_HTTPHEADER, array( "X-Requested-With: XMLHttpRequest" ) );
    }
  }

  function post( $url, $data, $referer = '', $xhr = false )
  {
    $this->handle = curl_init();

    $fields_string = '';
    if( is_array( $data ) )
    {
      foreach( $data as $key => $value )
      {
        $fields_string .= $key . '=' . $value . '&';
      }
      rtrim( $fields_string, '&' );
    }
    else
    {
      $fields_string = $data;
    }

    $this->xhr = $xhr;
    $this->setopt( $url, $referer );

    curl_setopt( $this->handle, CURLOPT_POST, 1 );
    curl_setopt( $this->handle, CURLOPT_POSTFIELDS, $fields_string );

    $this->data = curl_exec( $this->handle );
    $this->code = curl_getinfo( $this->handle, CURLINFO_HTTP_CODE );
    $this->info = curl_getinfo( $this->handle );
    $this->url  = ( isset( $this->info['redirect_url'] ) && !empty( $this->info['redirect_url'] ) != '' ? $this->info['redirect_url'] : $this->info['url'] );
    curl_close( $this->handle );

    return $this->data;
  }

  function get( $url, $referer = '', $xhr = false )
  {
    $this->handle = curl_init();

    $this->xhr = $xhr;
    $this->setopt( $url, $referer );

    $this->data = curl_exec( $this->handle );
    $this->code = curl_getinfo( $this->handle, CURLINFO_HTTP_CODE );
    $this->info = curl_getinfo( $this->handle );
    $this->url  = ( isset( $this->info['redirect_url'] ) && !empty( $this->info['redirect_url'] ) != '' ? $this->info['redirect_url'] : $this->info['url'] );
    curl_close( $this->handle );

    return $this->data;
  }

  public function cleanup()
  {
    if( file_exists( $this->cookiejar ) )
    {
      unlink( $this->cookiejar );
    }
  }
}

For more information about PHP cURL you can consult the information at http://php.net/manual/en/book.curl.php

Using PHP cURL to check our IP-address

Using PHP cURL to get current IP adress
An example of a GET request with this class, and a simple regexp pattern. To get our current IP-address we read the web page http://checkip.dyndns.org/, it displays the following HTML markup

<?php
require_once( 'curl.class.php' );
$curl = new cURL( true, false ); // follow redirects, don't use cookies

$url = 'http://checkip.dyndns.org/';
$data = $curl->get( $url );

if( preg_match( '/([0-9]+\.[0-9]+\.[0-9]+\.[0-9]+)/', $data, $match ) )
{
  echo $match[1];
}

Using PHP cURL to log in to Facebook

Now I will show you a more extensive, and practical example usage of this class; logging into Facebook mobile.
Facebook mobile login page
Let’s start by pulling up the Facebook mobile login page, https://m.facebook.com/login.php

Right-click on the page and go to view source.

Search the source code for <form and you will find the following markup:

<form method="post" id="login_form" novalidate="1" action="https://m.facebook.com/login.php?refsrc=http%3A%2F%2Fm.facebook.com%2Flogin.php&amp;refid=9">
  <input type="hidden" name="lsd" value="AVpos8Sz" autocomplete="off" />
  <input type="hidden" name="charset_test" value="โ‚ฌ,ยด,โ‚ฌ,ยด,?,?,?" />
  <input type="hidden" name="version" value="1" />
  <input type="hidden" id="ajax" name="ajax" value="0" />
  <input type="hidden" id="width" name="width" value="0" />
  <input type="hidden" id="pxr" name="pxr" value="0" />
  <input type="hidden" id="gps" name="gps" value="0" />
  <input type="hidden" autocomplete="off" name="m_ts" value="1362118902" />
  <input type="hidden" autocomplete="off" name="li" value="9kgwUSdFkzZKZmS1xKv9r9oa" />
  <input type="hidden" autocomplete="off" name="signup_layout" value="layout|lower_subdued_button||s_btn|special||l_btn|confirm||signupinstr||logininstr||st|createfb" />

  <div class="_al8">
    Already have an account?
  </div>
  <div class="grouped inset aclb">
    <div class="mobile-login-field mobile-login-field-email first area textInputArea acw" data-sigil="marea">
      <div class="input inputWrapper" id="u_0_0">
        <input class="tiapl input" autocorrect="off" autocapitalize="off" name="email" placeholder="Email address or phone number" type="text" data-sigil="clearableInput" />

        <div class="mClearButtonWrapper" style="display:none" data-sigil="touchable clearButton">
          <div class="mClearButton">
            ร—
          </div>
        </div>
      </div>
    </div>
    <div class="mobile-login-field last area textInputArea acw abt" data-sigil="marea">
      <div class="input inputWrapper" id="u_0_1">
        <input class="tiapl input" autocorrect="off" autocapitalize="off" name="pass" placeholder="Password" type="password" data-sigil="clearableInput" />

        <div class="mClearButtonWrapper" style="display:none" data-sigil="touchable clearButton">
          <div class="mClearButton">
            ร—
          </div>
        </div>
      </div>
    </div>
  </div>
  <div class="button_area aclb apl" data-sigil="marea">
    <button type="submit" value="Log in" class="btn btnC largeBtn bglb mfsl touchable" name="login" role="button" data-sigil="touchable">
      Log in
    </button>
  </div>
  <div class="_4xdr aclb" data-sigil="marea">
    <div class="_al8">
      New to Facebook?
    </div>
    <div class="button_area aclb apl" data-sigil="marea">
      <button type="submit" value="Create Facebook Account" class="btn btnS largeBtn bglb mfsl touchable" name="signup" role="button" data-sigil="touchable">
        Create Facebook Account
      </button>
    </div>
  </div>
  <noscript>
    <input type="hidden" autocomplete="off" name="_fb_noscript" value="true" />
  </noscript>
</form>

This might look daunting, but let’s boil it down to essentials, the data that is actually sent to the server via the form..

<input type="hidden" name="lsd" value="AVpos8Sz" autocomplete="off" />
<input type="hidden" name="charset_test" value="โ‚ฌ,ยด,โ‚ฌ,ยด,?,?,?" />
<input type="hidden" name="version" value="1" />
<input type="hidden" id="ajax" name="ajax" value="0" />
<input type="hidden" id="width" name="width" value="0" />
<input type="hidden" id="pxr" name="pxr" value="0" />
<input type="hidden" id="gps" name="gps" value="0" />
<input type="hidden" autocomplete="off" name="m_ts" value="1362118902" />
<input type="hidden" autocomplete="off" name="li" value="9kgwUSdFkzZKZmS1xKv9r9oa" />
<input type="hidden" autocomplete="off" name="signup_layout" value="layout|lower_subdued_button||s_btn|special||l_btn|confirm||signupinstr||logininstr||st|createfb" />
<input class="tiapl input" autocorrect="off" autocapitalize="off" name="email" placeholder="Email address or phone number" type="text" data-sigil="clearableInput" />
<input class="tiapl input" autocorrect="off" autocapitalize="off" name="pass" placeholder="Password" type="password" data-sigil="clearableInput" />
<input type="hidden" autocomplete="off" name="_fb_noscript" value="true" />

That looks a bit better. This is the part of the markup that is relevant to us, this is the data that will be sent to the server when logging in.

Now, some of these values are generated when you fetch the login-page. This is a simple way for websites to try and prevent login-scripts / webbots. This is easily avoidable however by first fetching the content of the website with a GET-request and parsing the form values.

$url = 'https://m.facebook.com/login.php';
$data = $curl->get( $url );

// use a regexp to get the value of "lsd" from the form
if( !preg_match( '/"lsd" value="([^"]+)"/', $data, $match ) )
{
  die( 'Failed to fetch `lsd` value from website' );
}
$lsd = $match[1];

Like that ๐Ÿ™‚

Now that we have the values, we build the POSTDATA array to send to the server, and finally we POST the data to the server!

$url = 'https://m.facebook.com/login.php?refsrc=http%3A%2F%2Fm.facebook.com%2F&amp;refid=8';
$data = array(
          'lsd'          => $lsd,
          'version'      => '1',
          'ajax'         => '0',
          'width'        => '0',
          'pxr'          => '0',
          'gps'          => '0',
          'email'        => 'YOUR_FACEBOOK_USERNAME',
          'pass'         => 'YOUR_FACEBOOK_PASSWORD',
          '_fb_noscript' => 'true', // to make it easier on us
        );
echo $curl->post( $url, $data );

And here is the final, complete Facebook login script

<?php
require_once( 'curl.class.php' );

// useragent of a Samsung Galaxy SII, source: http://www.zytrax.com/tech/web/mobile_ids.html
$user_agent = 'Mozilla/5.0 (Linux; U; Android 4.0.4; en-ca; SGH-I757M Build/IMM76D) AppleWebKit/534.30 (KHTML, like Gecko) Version/4.0 Mobile Safari/534.30';
// we use this to make Facebook think that we are a mobile device

$curl = new cURL( true, true, $user_agent ); // follow redirects, store cookies, use the useragent string specified above

// their login uses a token, so first we need to fetch the login-page once with a GET request
// this will generate the cookies for us and give us an opportunity to grab the form-values we need
$url = 'https://m.facebook.com/login.php';
$data = $curl->get( $url );

// use a regexp to get the value of "lsd" from the form
if( !preg_match( '/"lsd" value="([^"]+)"/', $data, $match ) )
{
  die( 'Failed to fetch `lsd` value from website' );
}
$lsd = $match[1];

$url = 'https://m.facebook.com/login.php?refsrc=http%3A%2F%2Fm.facebook.com%2F&amp;refid=8';
$data = array(
          'lsd'          => $lsd,
          'version'      => '1',
          'ajax'         => '0',
          'width'        => '0',
          'pxr'          => '0',
          'gps'          => '0',
          'email'        => 'YOUR_FACEBOOK_USERNAME',
          'pass'         => 'YOUR_FACEBOOK_PASSWORD',
          '_fb_noscript' => 'true', // to make it easier on us
        );
echo $curl->post( $url, $data );

Here is a link to download the entire PHP cURL class

Incoming search terms:

  • https://m facebook com/login php?refsrc=https://m facebook com/
  • store php5?refsrc=

Asbra

Posts Facebook

Blogging out of many years of experience with gamehacking, programming, reverse-engineering and general tomfoolery.

6 responses to cURL wrapper class for PHP (How to easily use PHP cURL)

  1. Hello john , Gr8 tutorial
    I’ve trid this on my hosting but it needed PHP Safe_Mode Off and they dont support this.
    so I’m going to change my hosting to another one. ๐Ÿ™‚
    Facebook, youtube and many other sites are blocked here and I want to know how can I use this tutorial in my joomla website using mod_wrapper module?
    and is it possible to load desktop version of facebook using this tutorial ?
    I tried many scripts and codes but they always support Facebook Mobile ๐Ÿ™
    I’m trying to make a website with membership via joomla , users buy membership and login to their accounts , then in the menu there are blocked websites like youtube , twitter , facebook and other… , when a user clicks on facebook an article shows up with an iFrame using your code displaying facebook (Desktop Version).
    I want to make it possible for users to surf inside this iFrame using cURL.

    I have written some codes but always show the home page of facebook and after login i got a message “this website is blocked”.
    I need this to make surfing proccess in websites completely use cURL and load in server side like a proxy.

    would you please help me about this ?

    Thanks.

  2. Hello Pasha!

    The reason you need PHP safe_mode off is due to the script using CURLOPT_FOLLOWLOCATION turned on. You can disable this behavior by initializing the class with the first argument set to false. However then your requests will not follow redirects, you will have to follow them manually.

    It might be possible to interact with Facebook desktop version, however the desktop version of Facebook relies heavily on JavaScript, hence it is a lot of work for you to process each script and replicate its behavior.. This is why most people take the easy way out and use mobile versions of websites to bot ๐Ÿ˜‰

    However! For the purpose you are doing this I would suggest you use something like Squid Proxy ( http://www.squid-cache.org/ ) instead. It is not very difficult to set up and will allow users of your website to surf through your server. You can set up a whitelist of sites you want the user to be able to access (so they don’t surf something that might be hurtful for you). It is a very commonly used software among web proxies.

    Hope this helps you out, let me know if there’s anything else ๐Ÿ™‚

  3. You should start a github project for this! And by the way your link to the actual php file is broken/blank.

    • Thank you for letting me know about the link! When I switched over to nginx from Apache I have forgot to rewrite some of the htaccess rules into nginx ๐Ÿ™‚
      I am using bitbucket for a few projects, been meaning to upload on github aswell.

  4. Chris, if you’re talking to me I dont know which link u mean ? by the way Im newbie in php and never used Github before ! I have to try it ๐Ÿ™‚

  5. Hello Johan congrats and thaks, this is the best tought curl wrapper I have seen

Leave a Reply