A few months ago, I had been following the Bitcoin explosion and signed up for an account on GDAX. During the verification process, I was prompted to submit a photo id as well as a photo of myself via my computer web camera. This was a pretty cool concept, and it got me thinking. What exactly does it take to be able to integrate web camera usage in the web browser?

Turns out, there are some HTML5 APIs available for interacting with the web camera using JavaScript.

We're going to see how to create a Vue.js web application that captures from the computer web camera directly in the web browser.

Creating a Vue.js Project with the Vue CLI

To keep this project simple to understand, we're going to create one from scratch. For convenience, we're going to scaffold our project using the Vue CLI.

Assuming you've installed the CLI, execute the following:

vue init webpack camera-project

The scaffolding process will ask a few questions. For this particular project, it doesn't matter if you choose to include the compiler and runtime or just the runtime. We won't be creating multiple components, so the router is not necessary for this project.

At this point, we can start developing our application.

Crafting the Application Logic and Interface for Image Capturing

We have a few goals for this particular project. We want to be able to stream the web camera to the UI and capture a frame on demand. A screenshot of what we hope to accomplish can be seen below:

Capture from Web Camera in Vue.js

Every time we capture an image, it will be added to a small list below. If we wanted to, we could send the captured images to a database via an HTTP API.

So how do we meet the goals of this project?

Open the project's src/App.vue file and include the following to start:

    <div id="app">

    export default {
        name: 'app',
        data() {
            return {
                video: {},
                canvas: {},
                captures: []
        mounted() { },
        methods: { }

    body: {
        background-color: #F0F0F0;
    #app {
        text-align: center;
        color: #2c3e50;
        margin-top: 60px;
    #video {
        background-color: #000000;
    #canvas {
        display: none;
    li {
        display: inline;
        padding: 5px;

The <template> block was left empty on purpose for now. Instead, let's focus on the <script> block.

We need to initialize a few UI facing variables, and this can be done via the data method. The video variable will be bound to a <video> element, the canvas variable will be bound to a <canvas> element, and the captures array will be a list of our already captured images.

The mounted method will trigger when the application is loaded. This method should look something like the following:

mounted() {
    this.video = this.$refs.video;
    if(navigator.mediaDevices && navigator.mediaDevices.getUserMedia) {
        navigator.mediaDevices.getUserMedia({ video: true }).then(stream => {
            this.video.src = window.URL.createObjectURL(stream);

We need to be able to interact with HTML elements in the UI. Rather than trying to access the DOM directly, we can make use of Vue.js refs. You'll see shortly, but our HTML element will have a ref attribute that is equal to video.

Once we have a reference to our element, we can check to make sure media capture is supported by the value. If media capturing is supported, we will get a stream from the web camera and load the stream into the HTML video element.

In fairness, the code above was inspired by David Walsh's tutorial, Camera and Video Control with HTML5. I just made use of refs and made it Vue.js friendly.

This brings us to our methods. We will have a single capture method that looks like the following:

methods: {
    capture() {
        this.canvas = this.$refs.canvas;
        var context = this.canvas.getContext("2d").drawImage(this.video, 0, 0, 640, 480);

Again, we are making use of refs to an HTML element. Once we have a reference to the canvas element, we can get an image of the video element, convert it into an image, and push it into our list of captures.

So what does the HTML look like that pairs with the JavaScript logic?

Within the project's src/App.vue file, let's have a look at the <template> block:

    <div id="app">
        <div><video ref="video" id="video" width="640" height="480" autoplay></video></div>
        <div><button id="snap" v-on:click="capture()">Snap Photo</button></div>
        <canvas ref="canvas" id="canvas" width="640" height="480"></canvas>
            <li v-for="c in captures">
                <img v-bind:src="c" height="50" />

Remember the refs that I mentioned earlier? This is where we're assigning them.

    <video ref="video" id="video" width="640" height="480" autoplay></video>

The <video> tag has ref="video" and the <canvas> tag has something similar.

When the button is pressed, the capture method is called. The captures variable is looped through, and each image is rendered to the screen.

That wasn't bad, right?


You just saw how to capture images from a web camera using the web browser in a Vue.js web application. Most of the heavy lifting was done through the HTML5 JavaScript APIs, but how Vue.js is structured makes things very easy.

There were some important Vue.js concepts used in this particular article. The ref attribute for HTML elements allowed us to access them from JavaScript. By using v-bind:src on the <img> tag, we were able to display our captured images.