Capturing an image from an HTML5 Canvas or Video Element

Dan Pastori avatar
Dan Pastori October 4th, 2021

Ever want to save your HTML5 canvas element as an image? You totally can! I’ve done this a few times to solve a variety of different issues. With this trick you can capture a screenshot from a video, save a rendered graphic, pretty much anything within the canvas element.

Step 1: Make a Reference To your Canvas Element

There are two approaches to this. First, you may have a canvas element that actually appears on the screen. It will live within your HTML and will display on the screen. The second approach is to have the canvas element represented simply as a javascript object. I’ve used this approach to capture screen shots of HTML5 video elements.

If your canvas is within HTML, make a reference to it in your Javascript like this:

let canvas = document.getElementById('screenshot-canvas');

You can obviously use whatever reference way you choose to select your canvas from the screen.

You can also just have a canvas object behind the screen that can be used to capture what’s within. I just set it up like this:

let canvas = document.createElement('canvas');

Step 2: Capturing your Canvas Element as an Image

Here’s where the magic takes place. I create a method that captures the element like this:

let image = canvas.toDataURL('image/jpeg');

With canvas being the variable of your HTML5 canvas element we set up in step 1. That’s all there is to it! You now have a capture of whatever is in the canvas as an image! You can set the image variable to the src of any image element and you will be good to go.

One thing to note. The size of your image will be the size of your canvas. This is much easier to see if the canvas is on your screen. However, if you are using a Javascript object, you need to set the width and height of the element like so:

let canvas = document.createElement('canvas');

canvas.width = 1920;
canvas.height = 1080;

Taking a Screenshot of an HTML5 Video Element

One of the coolest features of this script is you can take a screen shot of an HTML5 video element using this as well. You just have to pipe the video to the canvas element. Just a heads up, this will work better if the canvas you are referencing is a javascript object, otherwise you will have 2 videos on your screen.

To do this, set up a reference to your HTML5 Video Element. I’m going to assume this element lives on your page. You can however, do the same object instantiation of the video element and hide both the canvas and video element and just output a screen shot. If you are interested in those examples, reach out on the community forum.

Let’s first set up the reference to our HTML5 video element:

let video = document.getElementById('my-video');

Once again, you can use whatever method you want to reference your video. We just need a reference to the element.

Now that we have our video, let’s tie everything together. For best results, I’d recommend keeping the aspect ratio of your canvas to the size of your video. It doesn’t have to be the full size if you want smaller, scaled images, but you also don’t want any funky resizing.

let canvas = document.createElement('canvas');
let video = document.getElementById('my-video');

canvas.width = 1920;
canvas.height = 1080;

let ctx = canvas.getContext('2d');
ctx.drawImage( video, 0, 0, canvas.width, canvas.height );

let image = canvas.toDataURL('image/jpeg');

That’s all there is to it! The meat of the script is to create a “2D” context and draw an image to that context of the video. This will take whatever frame is currently being displayed on the video and capturing it as an image.

Capturing an HTML5 Video Frame at a Timestamp

If you want to capture a frame at a certain timestamp in your video, there’s one little gotcha. You have to use the seeked callback to make sure your video has finished seeking before you capture the frame.

All you have to do is modify your code to look like this:

let canvas = document.createElement('canvas');
let video = document.getElementById('my-video');
let image = '';

video.addEventListener('seeked', function(){
    canvas.width = 1920;
    canvas.height = 1080;

    let ctx = canvas.getContext('2d');
    ctx.drawImage( video, 0, 0, canvas.width, canvas.height );

    image = canvas.toDataURL('image/jpeg');
});

video.currentTime = TIME_IN_SECONDS;

Now whatever you set for the current time on the video in seconds, the video will seek to that location and take a snap shot.

Hopefully this helps! It’s kind of a neat feature of the HTML5 canvas element that you can save it as an image. If you have any questions, definitely feel free to ask on the community forum, I’d be happy to help!

Support future content

The Ultimate Guide to Building APIs and Single-Page Applications with Laravel + VueJS + Capacitor book cover.

Psst... any earnings that we make off of our book is being reinvested to bringing you more content. If you like what you read, consider getting our book or get sweet perks by becoming a sponsor.

Written By Dan

Dan Pastori avatar Dan Pastori

Builder, creator, and maker. Dan Pastori is a Laravel certified developer with over 10 years experience in full stack development. When you aren't finding Dan exploring new techniques in programming, catch him at the beach or hiking in the National Parks.

Like this? Subscribe

We're privacy advocates. We will never spam you and we only want to send you emails that you actually want to receive. One-click unsubscribes are instantly honored.