0

Working on a small concept of taking screenshots of website by url now. By referring lot of websites used wkhtmltoimage. Currently using Mac. Installed wkhtmltoimage successfully, Also tried

wkhtmltoimage www.google.com ggss.png

in terminal. It successfully outputs the screenshot of website. But when i try executing the above command using PHP i dont see the output image or any errors. Below is the code i tried

<?php
$output = shell_exec('wkhtmltoimage http://www.bbc.com bbc.jpg');
?>

Any help would be appreciated

Karthik Nk
  • 377
  • 1
  • 8
  • 25

4 Answers4

2

The other way for taking a screenshot using PHP without any additional server resource is by using Google's PageSpeed Insights API, which doesn't need any authentication of any kind. It's free and open right now, so make use of it.

Implementation details for the same are here: Generating Screenshots of URLs using Google's secret magic API.

Source Code

<?php
  // Creating a proxy to use GET request to hit the Google Page Speed API and receive a screenshot.
  // Check if the URL parameter for our proxy is set.
  if (!empty($_GET['url'])) {
    // Make sure the given value is a URL.
    if (filter_var($_GET['url'], FILTER_VALIDATE_URL)) {
      // Hit the Google PageSpeed Insights API.
      // Catch: Your server needs to allow file_get_contents() to make this run. Or you need to use cURL.
      $googlePagespeedResponse = file_get_contents("https://www.googleapis.com/pagespeedonline/v2/runPagespeed?screenshot=true&url={$_GET['url']}");

      // Convert the JSON response into an array.
      $googlePagespeedObject = json_decode($googlePagespeedResponse, true);

      // Grab the Screenshot data.
      $screenshot = $googlePagespeedObject['screenshot']['data'];
      // Replace Google's anamolies.
      $screenshot = str_replace(array('_','-'), array('/','+'), $screenshot);

      // Build the Data URI scheme and spit out an <img /> Tag.
      echo "<img src=\"data:image/jpeg;base64,{$screenshot}\" alt=\"Screenshot\" />";
    } else {
      // If not a valid URL.
      echo "Given URL is not valid.";
    }
  } else {
    // URL not set.
    echo "You need to specify the URL.";
  }
?>

You can also do it using Client Side:

$(function () {
  // Get the URL.
  var url = "https://praveen.science/";
  // Prepare the URL.
  url = encodeURIComponent(url);
  // Hit the Google Page Speed API.
  $.get("https://www.googleapis.com/pagespeedonline/v1/runPagespeed?screenshot=true&strategy=mobile&url=" + url, function (data) {
    // Get the screenshot data.
    var screenshot = data.screenshot;
    // Convert the Google's Data to Data URI scheme.
    var imageData = screenshot.data.replace(/_/g, "/").replace(/-/g, "+");
    // Build the Data URI.
    var dataURI = "data:" + screenshot.mime_type + ";base64," + imageData;
    // Set the image's source.
    $("img").attr("src", dataURI);
  });
});
<script src="https://ajax.googleapis.com/ajax/libs/jquery/2.1.1/jquery.min.js"></script>
<h1>Hard Coded Screenshot of my Website:</h1>
<img src="//placehold.it/300x50?text=Loading+Screenshot..." alt="Screenshot" />
Praveen Kumar Purushothaman
  • 164,888
  • 24
  • 203
  • 252
  • You have a typo $googlePagespeedObject['screenshot']['data']; – MrPHP Jul 16 '18 at 13:14
  • @PraveenKumarPurushothaman Hi Praveen. I have been using your hack for more than 7 months now. But currently it does not work now. It does not the generate the screenshot of web urls I provide. – Du-Lacoste Oct 15 '19 at 10:08
  • @DulithDeCosta Thanks for reporting... Lemme see if Google has found out we are misusing and let me find an alternative. – Praveen Kumar Purushothaman Oct 15 '19 at 10:09
  • @DulithDeCosta I just checked it works. Did you exceed your limit or something? Check your console for errors... – Praveen Kumar Purushothaman Oct 15 '19 at 10:10
  • @PraveenKumarPurushothaman Wow. Speedy reply. I have 500 URLs, which I need to get screenshots. When I automated it using a Python script. Only the first 50 URLs work then it does not generate images. Is there a limit for it ? – Du-Lacoste Oct 15 '19 at 10:12
  • @DulithDeCosta I believe that's the reason. Google crazily puts limit on these things.. – Praveen Kumar Purushothaman Oct 15 '19 at 10:32
  • 1
    @PraveenKumarPurushothaman Oh is it ? Is there a way to check the limit of it ? I have been googling, but still no luck with it. I need to write off with a proper closure. hehe. Thanks alot Praveen. – Du-Lacoste Oct 15 '19 at 10:37
1

Try specify full path to command wkhtmltoimage.

EDIT

to get command wkhtmltoimage full path run this command: whereis wkhtmltoimage

So you must it like:

<?php
$output = shell_exec('/full_path_to_wkhtmltoimage_here/wkhtmltoimage http://www.bbc.com /full_path_to_img_here/bbc.jpg');
?>
stepozer
  • 1,143
  • 1
  • 10
  • 22
  • its not an answer buddy, use comment for this – Saqueib Feb 04 '15 at 09:49
  • @Saqueib This question similar: http://stackoverflow.com/questions/28211963/failed-to-call-dwebp-in-php. I think problem in full path – stepozer Feb 04 '15 at 09:52
  • try giving example and refer the similar answer – Saqueib Feb 04 '15 at 09:53
  • @KarthikNk No, try full path to **command** `wkhtmltoimage`, not to file! You can get full path use `whereis wkhtmltoimage` – stepozer Feb 04 '15 at 09:55
  • @stepozer alright found the path.. used this path /usr/local/bin/wkhtmltoimage www.google.com /Applications/XAMPP/xamppfiles/htdocs/demotasks/phpexec.png in terminal works perfectly but when using the same path using shell_exec in php still no output – Karthik Nk Feb 04 '15 at 11:31
  • @stepozer type -p wkhtmltoimage helped to get the path of applicaion – Karthik Nk Feb 04 '15 at 11:34
1

Ok finally executed the shell command through php via browser. So i thought i could share might be useful for someone. So the real problem is permission.

So when i used whoami command on terminal output was macuser. But when i tried executing the command using shell_exec in php output was nobody. Its because apache didnt have permission. So i did the following to execute the shell command via PHP

locate the httpd.conf file in /etc and find

User nobody Group nogroup

change the nobody to the username you'd like to set as the user you want to execute. For me its User macuser

Then execute the following commands. (To make sure i executed them as su in terminal)

  • cd /directory/of/htdocs(for me cd /Applications/XAMPP/xamppfiles/htdocs)
  • find . -exec chown macuser:macuser {} \;
  • cd ..
  • chown macuser htdocs

now when i execute the following code it works

<?php
$output = shell_exec('/usr/local/bin/wkhtmltoimage http://www.google.com /Applications/XAMPP/xamppfiles/htdocs/demotasks/google.jpg');
?>

Thanks to boulderapps!

Karthik Nk
  • 377
  • 1
  • 8
  • 25
0

I would suggest using an API such as this one

If you create an account you can call the API, for example.

// The parameters.
$token = 'YOUR_TOKEN';
$url = urlencode('https://github.com');
$width = 1920;
$height = 1080;
$output = 'image';

// Create the query URL.
$query = "https://screenshotapi.net/api/v1/screenshot";
$query .= "?token=$token&url=$url&width=$width&height=$height&output=$output";

// Call the API.
$image = file_get_contents($query);

// Store the screenshot image.
file_put_contents('./screenshot.png', $image);

Check out the docs for more information.

Dirk
  • 1
  • 1