I've long wanted to take screenshots on my own terms, no bullcrap API, no restful services, I wanted independence from those types of services.

Surprisingly took me quite a while to end up figuring it out because there are multiple ways this can be done, and it depends entirely on your server setup, but I will share everything I have in the way of taking screenshots with a Linux Server and PHP.

Edit

As @Andyhmltn pointed out, there is no sanitization of the incoming data that will be sent to the command line, for that, you should use escapeshellargs. I wanted to focus solely on the flow of taking screenshots, how you implement this is up to you!

Original Post

Firstly, head on over to wkhtmltopdf on Google Code. On their downloads list, look for wkhtmltoimage (i386 or amd64).

Once you've downloaded a static binary executable, upload it to your server and grant it permissions to allow execution, don't forget that step.

It may be worth your while to test out the binary through bash before attempting to do it through PHP, just so you know it works.

./wkhtmltoimage --width 1200 --height 1200 --quality 100 http://streetleague.com sls.png

View Raw Code →


Run that from your command line, and hopefully streetleague.com will have its screenshot taken and saved to the same directory as the binary as sls.png.

If it does not work for you or you're getting an error, make sure you have all of your dependencies installed, or try downgrading your version of the binary (I have found later releases to not work compared to older ones.)

If you got a screenshot, we're in business.

screenshot.php

function screenshot($site, $path){
    $cmd = LIB_DIR."wkhtmltoimage/wkhtmltoimage --width 1200 --height 1200 --quality 100 http://".$site." ".$path;
    exec($cmd);
}

screenshot('http://streetleague.com', 'sls.png');

View Raw Code →


That is a simple example of how you could call the binary from PHP, allowing you to pass parameters to it dynamically.

This will take a few seconds to generate possibly, and that could bother your users. What about doing this in the background?

Save the following script as screenshot_background.php and if you wanted to start the screenshot process in the background, call it from another part of your script like so:

screenshot_background.php

function screenshot($site, $path){
    $cmd = LIB_DIR."wkhtmltoimage/wkhtmltoimage --width 1200 --height 1200 --quality 100 http://".$site." ".$path;
    exec($cmd);
}

if(isset($argv[1]) && isset($argv[2])){
    screenshot($argv[1], $argv[2]);
}

View Raw Code →


Elsewhere in your script, such as...

ajax.php

function backgroundScreenshot($site, $path){
    $cmd = 'php relative/path/to/screenshot_background.php "'.$site.'" "'.$path.'" &';
    pclose(popen($cmd, 'r'));
}

View Raw Code →


This will start a new process in the background and pass some parameters to the screenshot_background.php, which are then interpreted, passed, and executed, all while keeping (for instance) your ajax requests nice and quick.

I seperated the scripts for simplicity of explanation.

To view what I believe is unofficial documentation, refer to the link here. I don't believe all parameters are valid for wkhtmltoimage as this api list is for wkhtmltopdf.

Tweak around with the settings. Some of the options I've used or found handy in the past are things like --javascript delay, --crop-h, and --disable-javascript.

If you have any feedback or critique, see anything I am doing wrong, please share and I will gladly update this post.

Cheers!

@Gillis

Post Script

@mike: I tried emailing support [at] forrst.com and was met with nothing. The beginning indentations on the code multipost makes my work look sloppy and has been an issue ever since its inception. I just don't understand why that isn't fixed. Thanks