Yes, it is possible to make a screenshot (create a canvas replica) of an HTML page (or rather of a selected node) on client-side using JavaScript.

html2canvas

And like everything in JS world, it is done via some library. This time it’s html2canvas.

Download the file and put it in your project folder:

├── html2canvas.min.js
└── index.html

Include it into index.html:

<head>
  ...
  <script src="html2canvas.min.js"></script>
  ...
</head>

Now, let’s say, you want to make a screenshot (generate a raster image) of some <div id="screenshot"> from your page. Here’s how you do it:

...
<script>
    function makeScreenshot() {
        html2canvas(document.getElementById("screenshot"), {scale: 1}).then(canvas => {
            document.body.appendChild(canvas);
        });
    }
</script>
</body>

You’ll get a canvas element at the end of your page. This canvas can then be saved as a regular image file.

To make it more interesting, here’s what we will do:

  1. Create a rather complex <div id="screenshot"> node inside some <div id="main">;
  2. Assign onclick="makeScreenshot();" to the <div id="screenshot">;
  3. Generate a <canvas> with twice the size (scale to 200%), replacing the original <div>.

Here’s the code:

<script>
    function makeScreenshot() {
        html2canvas(document.getElementById("screenshot"), {scale: 2}).then(canvas => {
            var main = document.getElementById("main");
            while (main.firstChild) {
              main.removeChild(main.firstChild);
            }

            // for Firefox
            main.appendChild(canvas);

            // for Safari
            //canvas.toBlob(function(blob) {
            //  var newImg = document.createElement('img'),
            //      url = URL.createObjectURL(blob);
              
            //  newImg.onload = function() {
            //    URL.revokeObjectURL(url);
            //  };

            //  newImg.src = url;
            //  newImg.title = "some title";
            //  newImg.alt = "some alternative text";
            //  main.appendChild(newImg);
            //});
        });
    }
</script>

Note the commented section for Safari. Apparently, canvas element is still not really cross-browser yet, because what’s okay for Firefox is not okay for Safari and vice versa, so if you need it for this or that browser, then comment/uncomment the corresponding section.

And here’s a demo:

If video doesn’t play in your browser, you can download it here.

Pay attention to the bottom part, where the Inspector is - you’ll see how <div> is replaced by <canvas>.


[24.07.2018] Update: More universal solution

A bit later I found an universal solution that works in both Firefox and Safari:

<div>
    <a id="a-make" href="#">Make a screenshot</a>
    <a id="a-download" href="#" style="display:none;">Download a screenshot</a>
</div>

<div id="main">
    <div id="screenshot">
        ...
    </div>
</div>

<script>
    function makeScreenshot()
    {
        html2canvas(document.getElementById("screenshot"), {scale: 2}).then(canvas =>
        {
            canvas.id = "canvasID";
            var main = document.getElementById("main");
            while (main.firstChild) { main.removeChild(main.firstChild); }
            main.appendChild(canvas);
        });
    }

    document.getElementById("a-make").addEventListener('click', function()
    {
        document.getElementById("a-make").style.display = "none";
        makeScreenshot();
        document.getElementById("a-download").style.display = "inline";
    }, false);

    document.getElementById("a-download").addEventListener('click', function()
    {
        this.href = document.getElementById("canvasID").toDataURL();
        this.download = "canvas-image.png";
    }, false);
</script>

That way you’ll get a proper Save File dialog in your browser:

Canvas Save File

Full source code and a live demo are available in this repository.


[29.07.2018] Update: More about cross-browser support

As usual in the web-world, you can get all sorts of results in different browsers.

First of all, even before getting to canvas, custom fonts are not picked up in some browsers. Hilarious enough, even the same browser (Safari) on one Mac shows fonts as it should, and on another Mac it just doesn’t.

But forget about fonts, take a look how different browser create the canvas.

Firefox moves the content down a bit:

If video doesn’t play in your browser, you can download it here.

Vivaldi messes up the font a bit:

If video doesn’t play in your browser, you can download it here.

And only Safari works fine (at least on my Mac):

If video doesn’t play in your browser, you can download it here.

So, I can conclude that creating a screenshot (canvas) of a web-page is not reliable (or cross-browser enough) at the moment.


[22.04.2019] Update: Making a screenshot from the Firefox console

What works awesome though is making a screenshot from the Firefox console: Tools ▸ Web Developer ▸ Web Console, and there:

:screenshot --selector "#some-id" --dpr 1 ololo.png

Sadly, this functionality is not available from the page JS.