Skip to main content

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.jsin 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 Promisesand 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 !

Comments

Popular posts from this blog

How to use Ngx-Charts in Angular ?

Charts helps us to visualize large amount of data in an easy to understand and interactive way. This helps businesses to grow more by taking important decisions from the data. For example, e-commerce can have charts or reports for product sales, with various categories like product type, year, etc. In angular, we have various charting libraries to create charts.  Ngx-charts  is one of them. Check out the list of  best angular chart libraries .  In this article, we will see data visualization with ngx-charts and how to use ngx-charts in angular application ? We will see, How to install ngx-charts in angular ? Create a vertical bar chart Create a pie chart, advanced pie chart and pie chart grid Introduction ngx-charts  is an open-source and declarative charting framework for angular2+. It is maintained by  Swimlane . It is using Angular to render and animate the SVG elements with all of its binding and speed goodness and uses d3 for the excellent math functions, scales, axis and shape ge

JavaScript new features in ES2019(ES10)

The 2019 edition of the ECMAScript specification has many new features. Among them, I will summarize the ones that seem most useful to me. First, you can run these examples in  node.js ≥12 . To Install Node.js 12 on Ubuntu-Debian-Mint you can do the following: $sudo apt update $sudo apt -y upgrade $sudo apt update $sudo apt -y install curl dirmngr apt-transport-https lsb-release ca-certificates $curl -sL https://deb.nodesource.com/setup_12.x | sudo -E bash - $sudo apt -y install nodejs Or, in  Chrome Version ≥72,  you can try those features in the developer console(Alt +j). Array.prototype.flat && Array.prototype. flatMap The  flat()  method creates a new array with all sub-array elements concatenated into it recursively up to the specified depth. let array1 = ['a','b', [1, 2, 3]]; let array2 = array1.flat(); //['a', 'b', 1, 2, 3] We should also note that the method excludes gaps or empty elements in the array: let array1

Understand Angular’s forRoot and forChild

  forRoot   /   forChild   is a pattern for singleton services that most of us know from routing. Routing is actually the main use case for it and as it is not commonly used outside of it, I wouldn’t be surprised if most Angular developers haven’t given it a second thought. However, as the official Angular documentation puts it: “Understanding how  forRoot()  works to make sure a service is a singleton will inform your development at a deeper level.” So let’s go. Providers & Injectors Angular comes with a dependency injection (DI) mechanism. When a component depends on a service, you don’t manually create an instance of the service. You  inject  the service and the dependency injection system takes care of providing an instance. import { Component, OnInit } from '@angular/core'; import { TestService } from 'src/app/services/test.service'; @Component({ selector: 'app-test', templateUrl: './test.component.html', styleUrls: ['./test.component