How to create a screenshot of your website with JavaScript using html2canvas

How to create a screenshot of your website with JavaScript using html2canvas

The errors on a Web App are part of our daily lives unless you are a superior being from another world. Sometimes, although exceptions should be reported automatically by your code, there are cases where the user would want to report an error by himself and in most of the cases, words are not enough to explain what an error on your awesome app looks like. This is just one of many uses that you could give to the utility of taking screenshots directly in the browser with Javascript.

In order to create a screenshot of your website without using a third party service, we recommend you to use the awesome html2canvas library. The script allows you to take "screenshots" of webpages or parts of it, directly on the users browser. The screenshot is based on the DOM and as such may not be 100% accurate to the real representation as it does not make an actual screenshot, but builds the screenshot based on the information available on the page. The library should work fine on the following browsers (with Promise polyfill):

  • Firefox 3.5+
  • Google Chrome
  • Opera 12+
  • IE9+
  • Safari 6+

As each CSS property needs to be manually built to be supported, there are a number of properties that are not yet supported. It does not require any rendering from the server, as the whole image is created on the clients browser. However, as it is heavily dependent on the browser, this library is not suitable to be used in nodejs. It doesn't magically circumvent any browser content policy restrictions either, so rendering cross-origin content will require a proxy to get the content to the same origin.

Requirements

As previously mentioned, in order to create a screenshot of an element of your DOM, we'll use the html2canvas library. You can download this library with NPM using the following command:

npm install html2canvas

Or if you prefer bower:

bower install html2canvas

Otherwise, just get a copy of the distributables (html2canvas.min.js) in the repository here and then add simply the reference to the script with a script tag:

<script src="/path/to/html2canvas.min.js"></script>

If you need more information about the library, please visit the official repository in Github here.

Important

The html2canvas library utilizesJavascript Promises and expects them to be available in the global context. If you wish to support older browsers that do not natively support Promises, you need to include a polyfill such as es6-promise before including html2canvas.

Create a screenshot of your website

The html2canvas library is very straightforward (only it's usage, as the library itself is pretty impresive), the html2canvas function will be exposed in the window (or just require it as a module if you use browserify), this function expects as first argument the element of the DOM that you want to export as an image. Therefore if you want to create a screenshot of your entire website, you need to pass the body element of your document as first argument of the html2canvas function. As it returns a Promise, you need to add the then function that will be executed once the exportation is ready.

In this example, the screenshot will be generated in png format and it will be shown in a new window once it's ready:

html2canvas(document.body).then(function(canvas) {
    // Export the canvas to its data URI representation
    var base64image = canvas.toDataURL("image/png");

    // Open the image in a new window
    window.open(base64image , "_blank");
});

Pretty clear and easy to understand isn't?

Create and download the screenshot

You may need to add the download screenshot feature to your app. For this you will need the FileSaver plugin in your document, read more about this plugin in the official Github repository here. The FileSaver plugin will allow you to generate a download from a Blob directly in the browser. To download the generated screenshot there are 2 options:

With the toBlob method

With HTML5, the canvas introduced the new method canvas.toBlob() that unlike toDataURL, exports the content of the canvas directly as a Blob. The method however is not available in all browsers, but there's a Polyfill in case you decide to use it in this way. With html2canvas, the toBlob method and  and filesaver you can generate the download of a screenshot of your website easily:

html2canvas(document.body).then(function(canvas) {
    // Export canvas as a blob 
    canvas.toBlob(function(blob) {
        // Generate file download
        window.saveAs(blob, "yourwebsite_screenshot.png");
    });
});

Convert base64 to Blob

If you don't want to mess with a lot of polyfills in case your app needs to provide support for outdated browsers, convert directly the base64 image to a Blob and then save it with FileSaver (you will need to mess up with more code though). You will need however, to create a function that converts the data URI to a blob:

/**
 * Convert a base64 string in a Blob according to the data and contentType.
 * 
 * @param b64Data {String} Pure base64 string without contentType
 * @param contentType {String} the content type of the file i.e (image/jpeg - image/png - text/plain)
 * @param sliceSize {Int} SliceSize to process the byteCharacters
 * @see http://stackoverflow.com/questions/16245767/creating-a-blob-from-a-base64-string-in-javascript
 * @return Blob
 */
function b64toBlob(b64Data, contentType, sliceSize) {
        contentType = contentType || '';
        sliceSize = sliceSize || 512;

        var byteCharacters = atob(b64Data);
        var byteArrays = [];

        for (var offset = 0; offset < byteCharacters.length; offset += sliceSize) {
            var slice = byteCharacters.slice(offset, offset + sliceSize);

            var byteNumbers = new Array(slice.length);
            for (var i = 0; i < slice.length; i++) {
                byteNumbers[i] = slice.charCodeAt(i);
            }

            var byteArray = new Uint8Array(byteNumbers);

            byteArrays.push(byteArray);
        }

      var blob = new Blob(byteArrays, {type: contentType});
      return blob;
}

// Generate screenshot and download
html2canvas(document.body).then(function(canvas) {
    // Generate the base64 representation of the canvas
    var base64image = canvas.toDataURL("image/png");

    // Split the base64 string in data and contentType
    var block = base64image.split(";");
    // Get the content type
    var mimeType = block[0].split(":")[1];// In this case "image/png"
    // get the real base64 content of the file
    var realData = block[1].split(",")[1];// For example:  iVBORw0KGgouqw23....

    // Convert b64 to blob and store it into a variable (with real base64 as value)
    var canvasBlob = b64toBlob(realData, mimeType);

    // Generate file download
    window.saveAs(canvasBlob, "yourwebsite_screenshot.png");
});

Doesn't matter the method you choose, both of them work in the same way.

Create an image from a dom element

Additionally you can create an image from any DOM element, however as we said at the beginning of the article, unlike the DOM to image library, html2canvas doesn't work well with things created or dinamically modified with JavaScript.

To create an image from a specifical div or element in your document, just select it and pass it as first argument to the html2canvas function:

var element = document.getElementById("some-element-of-your-document");

html2canvas(element).then(function(canvas) {
    // Export the canvas to its data URI representation
    var base64image = canvas.toDataURL("image/png");

    // Open the image in a new window
    window.open(base64image , "_blank");
});

Happy coding !

Become a more social person