How to convert HTML to an image using wkhtmltoimage and Laravel

Table of contents

    How to convert HTML to an image using wkhtmltoimage and Laravel
    Render HTML to PNG, JPG, or WebP with one API call

    Pixel-accurate images of HTML and CSS through the Nutrient HTML-to-image API, without a headless browser to run. Start with 50 free credits.

    TL;DR
    • Install wkhtmltoimage and integrate it with Laravel
    • Create a custom Artisan command for HTML-to-image conversion
    • Convert any HTML file to PNG format via command line

    Converting HTML to images lets developers generate screenshots, thumbnails, and visual previews of webpages. wkhtmltoimage(opens in a new tab) is a command-line tool that uses the WebKit rendering engine. It’s lightweight, fast, and runs headless (no GUI required). It’s available for macOS, Linux, and Windows.

    In this tutorial, you’ll learn how to use wkhtmltoimage with Laravel to convert HTML to an image.

    The demo repository(opens in a new tab) for this tutorial is no longer maintained. Its code may require changes to work with current PHP and Laravel versions.

    wkhtmltoimage was archived on 2 January 2023(opens in a new tab) and is now read-only. The library still works, but it receives no security patches, browser-engine updates, or bug fixes. For new projects, consider maintained alternatives — Browsershot(opens in a new tab) (PHP wrapper around Puppeteer, MIT), Puppeteer(opens in a new tab) or Playwright(opens in a new tab) for direct Node.js use, or Nutrient’s HTML-to-image API for a managed cloud option (covered later in this guide).

    Development considerations

    Nutrient’s HTML-to-image API provides hosted conversion without installing wkhtmltoimage on the application server. The Processor API free plan includes 50 credits per month and adds an evaluation watermark to output. Credit usage depends on the operations in the request. See Processor API pricing for paid plans and pay-as-you-go options that remove the watermark.

    Requirements

    To check if you have PHP installed on your system, you can open a terminal and run the command php -v.

    Running laravel -v checks whether the Laravel installer is available; it doesn’t identify a project’s Laravel framework version. If the installer is missing, install it with Composer:

    Terminal window
    composer global require laravel/installer

    Add Composer’s global binary directory to PATH so the shell can find the Laravel installer. Use the Composer global command documentation(opens in a new tab) to locate that directory. The following example assumes a Unix-like shell and a global binary directory at $HOME/.composer/vendor/bin; substitute the actual path if it differs:

    Terminal window
    export PATH="$HOME/.composer/vendor/bin:$PATH"

    Setting up the project

    Create a new Laravel project by running the following:

    Terminal window
    laravel new html-to-image

    This will create a new directory called html-to-image with the basic Laravel structure.

    Navigate to the project directory by running the following command:

    Terminal window
    cd html-to-image

    Installing wkhtmltoimage

    Install wkhtmltoimage on your system. You can download the appropriate version for your operating system from the official website(opens in a new tab).

    Check if wkhtmltoimage is installed by running the following command:

    Terminal window
    wkhtmltoimage -V

    It’ll display the version number of the library like this:

    Terminal window
    wkhtmltoimage 0.12.6 (with patched qt)

    Make sure you have wkhtmltoimage installed on your system and that the binary is in the system’s PATH. You can check this by running the following command:

    Terminal window
    which wkhtmltoimage

    Terminal output showing wkhtmltoimage binary location in PATH

    If it’s not in the PATH, you can add the location to the PATH variable.

    Integrating wkhtmltoimage with Laravel

    1. Once you have wkhtmltoimage installed, you can integrate it with Laravel by creating a new command that utilizes the library. To do this, use the following command to generate a new command class:

      Terminal window
      php artisan make:command ConvertHtmlToImage

      This will create a new file in the app/Console/Commands directory.

    2. Open the app/Console/Commands/ConvertHtmlToImage.php file and update the handle method to use the wkhtmltoimage library to convert HTML to an image:

      public function handle(): int
      {
      $html = $this->argument('html');
      $output = $this->argument('output');
      // Escape shell arguments to prevent command injection.
      $escapedHtml = escapeshellarg($html);
      $escapedOutput = escapeshellarg($output);
      $outputLines = [];
      $resultCode = null;
      exec("wkhtmltoimage --format png {$escapedHtml} {$escapedOutput} 2>&1", $outputLines, $resultCode);
      if ($resultCode !== 0) {
      $this->error("Failed to convert HTML to image");
      if (!empty($outputLines)) {
      $this->error(implode("\n", $outputLines));
      }
      return Command::FAILURE;
      }
      $this->info("HTML converted to image and saved to {$output}");
      return Command::SUCCESS;
      }

      This method takes the html and output arguments and passes them to the wkhtmltoimage command. The --format option specifies the output format (PNG in this case).

      The escapeshellarg() function sanitizes the input arguments to prevent command injection attacks. The exec() function executes the wkhtmltoimage command, capturing both output and the result code for error handling.

    3. In the signature property of the class, define the arguments and options that this command accepts:

      protected $signature = 'convert:html-to-image {html=public/index.html} {output=public/image.png}';

      The html argument is the path to the HTML file that will be converted to an image, and the output argument is the path to the output image file. The = syntax sets default values for these arguments.

    4. Here’s the full code for the command:

      app/Console/Commands/ConvertHtmlToImage.php
      <?php
      namespace App\Console\Commands;
      use Illuminate\Console\Command;
      class ConvertHtmlToImage extends Command
      {
      /**
      * The name and signature of the console command.
      *
      * @var string
      */
      protected $signature = 'convert:html-to-image {html=public/index.html} {output=public/image.png}';
      /**
      * The console command description.
      *
      * @var string
      */
      protected $description = 'Convert HTML to image using wkhtmltoimage';
      /**
      * Execute the console command.
      *
      * @return int
      */
      public function handle(): int
      {
      $html = $this->argument('html');
      $output = $this->argument('output');
      // Escape shell arguments to prevent command injection.
      $escapedHtml = escapeshellarg($html);
      $escapedOutput = escapeshellarg($output);
      $outputLines = [];
      $resultCode = null;
      exec("wkhtmltoimage --format png {$escapedHtml} {$escapedOutput} 2>&1", $outputLines, $resultCode);
      if ($resultCode !== 0) {
      $this->error("Failed to convert HTML to image");
      if (!empty($outputLines)) {
      $this->error(implode("\n", $outputLines));
      }
      return Command::FAILURE;
      }
      $this->info("HTML converted to image and saved to {$output}");
      return Command::SUCCESS;
      }
      }

    Creating the HTML file

    Currently, there isn’t an HTML file inside the public directory. So, create a file called index.html and paste the following code into it:

    index.html
    193 collapsed lines
    <!DOCTYPE html>
    <html>
    <head>
    <meta charset="utf-8" />
    <title>
    A simple, clean, and responsive HTML invoice template
    </title>
    <style>
    .invoice-box {
    max-width: 800px;
    margin: auto;
    padding: 30px;
    border: 1px solid #eee;
    box-shadow: 0 0 10px rgba(0, 0, 0, 0.15);
    font-size: 16px;
    line-height: 24px;
    font-family: 'Helvetica Neue', 'Helvetica', Helvetica,
    Arial, sans-serif;
    color: #555;
    }
    .invoice-box table {
    width: 100%;
    line-height: inherit;
    text-align: left;
    }
    .invoice-box table td {
    padding: 5px;
    vertical-align: top;
    }
    .invoice-box table tr td:nth-child(2) {
    text-align: right;
    }
    .invoice-box table tr.top table td {
    padding-bottom: 20px;
    }
    .invoice-box table tr.top table td.title {
    font-size: 45px;
    line-height: 45px;
    color: #333;
    }
    .invoice-box table tr.information table td {
    padding-bottom: 40px;
    }
    .invoice-box table tr.heading td {
    background: #eee;
    border-bottom: 1px solid #ddd;
    font-weight: bold;
    }
    .invoice-box table tr.details td {
    padding-bottom: 20px;
    }
    .invoice-box table tr.item td {
    border-bottom: 1px solid #eee;
    }
    .invoice-box table tr.item.last td {
    border-bottom: none;
    }
    .invoice-box table tr.total td:nth-child(2) {
    border-top: 2px solid #eee;
    font-weight: bold;
    }
    @media only screen and (max-width: 600px) {
    .invoice-box table tr.top table td {
    width: 100%;
    display: block;
    text-align: center;
    }
    .invoice-box table tr.information table td {
    width: 100%;
    display: block;
    text-align: center;
    }
    }
    /** RTL **/
    .invoice-box.rtl {
    direction: rtl;
    font-family: Tahoma, 'Helvetica Neue', 'Helvetica',
    Helvetica, Arial, sans-serif;
    }
    .invoice-box.rtl table {
    text-align: right;
    }
    .invoice-box.rtl table tr td:nth-child(2) {
    text-align: left;
    }
    </style>
    </head>
    <body>
    <div class="invoice-box">
    <table cellpadding="0" cellspacing="0">
    <tr class="top">
    <td colspan="2">
    <table>
    <tr>
    <td>
    Invoice #: 123
    Created: January 23, 2023
    Due: January 31, 2023
    </td>
    </tr>
    </table>
    </td>
    </tr>
    <tr class="information">
    <td colspan="2">
    <table>
    <tr>
    <td>
    Acme, Inc.
    12345 Sunny Road
    Sunnyville, TX 12345
    </td>
    <td>
    Acme Corp.
    John Doe
    john@example.com
    </td>
    </tr>
    </table>
    </td>
    </tr>
    <tr class="heading">
    <td>Payment Method</td>
    <td>Check #</td>
    </tr>
    <tr class="details">
    <td>Check</td>
    <td>1000</td>
    </tr>
    <tr class="heading">
    <td>Item</td>
    <td>Price</td>
    </tr>
    <tr class="item">
    <td>Website design</td>
    <td>$300.00</td>
    </tr>
    <tr class="item">
    <td>Hosting (3 months)</td>
    <td>$75.00</td>
    </tr>
    <tr class="item last">
    <td>Domain name (1 year)</td>
    <td>$10.00</td>
    </tr>
    <tr class="total">
    <td></td>
    <td>Total: $385.00</td>
    </tr>
    </table>
    </div>
    </body>
    </html>

    Converting HTML to PNG

    Navigate to the project directory and run the following command:

    Terminal window
    php artisan convert:html-to-image public/index.html public/image.png

    This runs the ConvertHtmlToImage command, which is defined in the app/Console/Commands/ConvertHtmlToImage.php file.

    It takes two arguments:

    • The first argument is the path to the input HTML file (public/index.html).
    • The second argument is the path to the output image file (public/image.png).

    This command will convert the HTML file to an image and save it to the public/image.png file.

    Generated PNG invoice image converted from HTML using wkhtmltoimage

    You can check the source code of the demo project on GitHub(opens in a new tab).

    Conclusion

    This tutorial covered setting up a Laravel project and integrating wkhtmltoimage to convert HTML to images. The combination works well for generating visual snapshots of webpages within PHP applications.

    An alternative approach is Spatie/Browsershot(opens in a new tab), which uses headless Chrome to convert HTML to an image. This requires Chrome and Puppeteer installed on your system.

    For hosted conversion, use Nutrient’s HTML-to-image API. Create a Processor API account(opens in a new tab) to test conversion with the free plan, and check the pricing page before production use.

    FAQ

    How can I convert HTML to an image using `wkhtmltoimage` in a Laravel application?

    You can convert HTML to an image using the wkhtmltoimage command-line tool in a Laravel application. This involves generating the HTML content and using the tool to convert it to an image format like PNG or JPEG.

    What are the steps to install and use `wkhtmltoimage` in a Laravel project?

    Install wkhtmltoimage and make it available in the server’s PATH. Create the ConvertHtmlToImage Artisan command shown in this tutorial. Then run it with the input HTML and output image paths.

    Can I customize the output image generated by `wkhtmltoimage`?

    Yes, you can customize the output image by passing various options to the wkhtmltoimage command, such as specifying the image format, setting the width and height, and adjusting the quality and compression.

    Hulya Masharipov

    Hulya Masharipov

    Technical Writer

    Hulya is a frontend web developer and technical writer who enjoys creating responsive, scalable, and maintainable web experiences. She’s passionate about open source, web accessibility, cybersecurity privacy, and blockchain.

    Explore related topics

    Try for free Render HTML to images in the cloud