How to access webcam and take photo with JavaScript

Recently, computer vision has been a hot topic, which enable applications to deliver new, engaging user experiences. In order to bring computer vision to the browser, one of the key element is being able to access the webcam with JavaScript.

To contribute to the computer vision open source community, I had built a npm module called ‘webcam-easy‘, which provides an easy to use JavaScript module that can access webcam and take photo. You can try it yourself in the below demo.


Webcam-easy.js demo

Fail to start camera, please allow permision to access camera.
If you are browsing through social media built in browsers, you would need to open the page in Sarafi (iPhone)/ Chrome (Android)

GitHub repository

You can download the complete code of the above demo in the link below:


How to use webcam-easy.js

webcam-easy.js a JavaScript module I built for accessing webcam stream, it can allows us to capture a picture from the webcam. Below are the major features for webcam-easy.js:

  • Streaming webcam on desktop computer or mobile
  • Switch back or front cameras on mobile
  • Take pictures and be able to download.

You can easily add it as a module to your own application. If you are building an web-app that need to access webcam in the browser, this is for you! I will show you step by step instruction below of how to use this module.

# Step 1 : Include webcam-easy.js

First of all, simply include the script webcam-easy.min.js in the <head> section of the html file.

<html>
  <head>
    <script type="text/javascript" src="https://unpkg.com/webcam-easy/dist/webcam-easy.min.js"></script>
  </head> 

Or you can install it via npm for use in a TypeScript / ES6 project

npm install webcam-easy
import Webcam from 'webcam-easy';
npm webcam-easy

# Step 2 : Place elements in HTML

The next thing we will need to do is to add the html elements below

  • webcam video element
  • canvas element for capture picture
  • optional audio element for the snap sound
<video id="webcam" autoplay playsinline width="640" height="480"></video>
<canvas id="canvas" class="d-none"></canvas>
<audio id="snapSound" src="audio/snap.wav" preload = "auto"></audio>

# Step 3 : Initialize webcam object

Then, we will initialize the Webcam object, the constructor accepts below parameters

  • webcamElement – the webcam <video> html element
  • facingMode – ‘user’ or ‘element’, default value is ‘user’
  • canvasElement & snapSoundElement are optional
const webcamElement = document.getElementById('webcam');
const canvasElement = document.getElementById('canvas');
const snapSoundElement = document.getElementById('snapSound');
const webcam = new Webcam(webcamElement, 'user', canvasElement, snapSoundElement);

# Step 4 : Start Webcam

By calling the webcam.start() function, the browser will ask user permission to access the camera, once it is allowed, it will start steaming the webcam to the video element.

webcam.start()
   .then(result =>{
      console.log("webcam started");
   })
   .catch(err => {
       console.log(err);
   });
allow camera permission

# Step 5 : Snapshot

Just call webcam.snap() function to capture snapshot of the webcam. The function returns a data URI containing a representation of the image in the format of PNG. By setting the an html <a> link’s ‘href’ attribute to the image data return, the user can download and save the snapshot.

let picture = webcam.snap();
document.querySelector('#download-photo').href = picture;

# Step 6 : Stop webcam

You also want the user to be able to stop their webcam, simply call the webcam.stop() function.

Mobile front & back camera support

webcam-easy.js not only work for desktop webcam, it also support mobile front and back camera as well. When you initialize the Webcam object, you can pass the facingMode parameter, while ‘user’ represent the front camera that facing the user, and ‘environment’ represent the back camera.

You can also call the webcam.flip() to switch between front and back camera.

$('#cameraFlip').click(function() {
    webcam.flip();
    webcam.start();  
});

How I implemented webcam-easy.js

Here, I would also like to share some technical details of how I implemented this JavaScript module. I had checkout some other open source webcam JS libraries, and find some works on desktop but not on mobile, some works only on front camera but not on rear camera, some is not mirroring the webcam… Below I am going to show you how I overcome those challenges.

Check browser support

Most of the modern browsers do support webcam access on desktop/laptop, but unfortunately, not including IE.

As of Chrome 47, the getUserMedia API cannot be called from insecure origins. It means for security reason, the url required to be in https protocol, http url can not access webcam.

Another important thing to know is on iPhone/iPad, only Safari can access webcam, all other browser apps like Chrome or other social media build in browsers can not access webcam. On Android phones, webcam works fine in Chrome app.

Get media devices and stream

All the functionalities are exposed by the MediaDevices object, which is returned by navigator.mediaDevices. MediaDevices has two methods, enumerateDevices() and getUserMedia().

enumerateDevices()

Returns a Promise giving access to an array of MediaDeviceInfo objects for available devices. It not only contain video inputs, but also audio inputs. The MediaDeviceInfo objects contains some valuable information, below are the properties of the object

  • deviceId – an identifier for the represented device.
  • groupId – a group identifier. Two devices have the same group identifier if they belong to the same physical device — for example a monitor with both a built-in camera and a microphone.
  • kind – an enumerated value that is either "videoinput""audioinput" or "audiooutput"
  • label –  a label describing this device (for example “Front camera”, “Back camera”).

If you only want to retrieve the video input, filter by the kind property.

navigator.mediaDevices.enumerateDevices()
  .then(getVideoInputs)
  .catch(errorCallback);

function getVideoInputs(mediaDevices){
      mediaDevices.forEach(mediaDevice => {
        if (mediaDevice.kind === 'videoinput') {
          this._webcamList.push(mediaDevice);
        }
      });
}

I find out that before the user grant permission to access the webcam, the MediaDeviceInfo objects get return does not expose any information, both the deviceId and label would be empty.

getUserMedia()

Returns a Promise that gives access to a MediaStream. And user will be prompt to grant access to webcam. Then you can set the video html element’s srcObject to be the stream, and call play() to start streaming the webcam.

navigator.mediaDevices.getUserMedia(this.getMediaConstraints())
  .then(stream => {
	  this._webcamElement.srcObject = stream;
	  this._webcamElement.play();
  })
  .catch(error => {
	 //...
  });

And make sure the video html element had include autoplay and playsinline property.

<video id="webcam" autoplay playsinline></video>

Mirror webcam

As an expected user experience, when you are streaming a user facing webcam, the image should mirror what’s captured. You can achieve this by apply the transform style.

if(this._facingMode == 'user'){
    this._webcamElement.style.transform = "scale(-1,1)";
}

JavaScript webcam demo

Conclusion

If you are building a computer vision web-app that need to access the webcam, consider using webcam-easy.js JavaScript module, it will save you a lot of time. Then you can do all sort of cool things like real-time face detection, real-time object tracking, motion detection…

Thank you for reading. If you like this article, please share on Facebook or Twitter. Let me know in the comment if you have any questions. Follow me on Medium, GitHub and Linkedin. Support me on Ko-fi.

62 Comments

  • Hermenegildo Inacio Nhacuonga on May 30, 2020, Reply

    Halo Mr Benson.
    I used you demo in my project and it is ver good. I had difficulties to resize the image in order to easly save in a file. Can you halp me how to resize it please?

    • benson_ruan on May 30, 2020, Reply

      Hi,
      You can have a look at the below function, it takes a data URI and returns the Data URI corresponding to the resized image at the wanted size.
      function resizedataURL(datas, wantedWidth, wantedHeight)
      {
      var img = document.createElement(‘img’);

      img.onload = function(){
      var canvas = document.createElement(‘canvas’);
      var ctx = canvas.getContext(‘2d’);
      canvas.width = wantedWidth;
      canvas.height = wantedHeight;
      ctx.drawImage(this, 0, 0, wantedWidth, wantedHeight);
      var dataURI = canvas.toDataURL();
      return dataURI;
      };

      img.src = datas;
      }

      Use it like that : resizedataURL(‘yourDataURIHere’, 50, 50);

      • Sunny on May 18, 2021, Reply

        It is the picture that is snapped I would like to resize, but have no idea how to know the url, to put in this function /

  • İsa Katırcı on Jul 12, 2020, Reply

    if you work on localhost (127.0.0.1), you should try to set up SSL on your localhost and then use https in your URL, it could be the reason that on mobile it treats http not safe and not allow it to access the camera.

  • kamal deep on Jul 14, 2020, Reply

    Hi, It’s very helpful library.. i’m about to use this library in my Project.

    It’s working on my Localhost but when i uploaded to my server then it’s giving error message :-

    Fail to start camera, please allow permission to access camera.
    If you are browsing through social media built in browsers, you would need to open the page in Sarafi (iPhone)/ Chrome (Android)

    i’m accessing my server with IP.

    can you please help me what i’m missing?

    • benson_ruan on Jul 14, 2020, Reply

      Hi, most likely it is because you are not accessing via https, the browser treats http not safe and not allow it to access the webcam.

      • kamal deep on Jul 15, 2020, Reply

        Hi, Thanks a lot! It works now 🙂

        one more thing, it’s not working on Chrome for IPHONE.

        Is there any solution for this? or any reference how can i resolve this

        i really appreciate

        • Herman on Jul 15, 2020, Reply

          It work for me in chrome too.

        • benson_ruan on Jul 15, 2020, Reply

          Hi, for IPHONE, the only browser that can access camera is Safari, this is purely because Apple doesn’t not allow any other browser to access the camera.

  • Temitope Emmanuel Agboola on Jul 17, 2020, Reply

    Hi. Thanks for this great resource. I am trying to use this in my Express.JS project, which uses EJS as its view engine, and not HTML. EJS does not support the document.getElementById selector as well as the canvas element. Also I need to pass the captured shot through a route to upload to my database; how do you think I can implement this? Please is there a way you could help to work around this? So far, your solution is the best yet I have seen on the web, and I really want and need to implement it. Awaiting your reply!

  • Jorge on Jul 23, 2020, Reply

    Hi, thks for this post.
    I got this error in IE 11:

    SCRIPT1002: Error de sintaxis
    webcam-easy.min.js (1,1)

    Any suggestion ? thks

    • benson_ruan on Jul 26, 2020, Reply

      This is because IE 11 do not support ES6 import syntax. https://caniuse.com/#search=es6
      IE is no longer a modern browser anymore, Microsoft had announced they no longer support IE.
      IE is a time of past, Chrome and Safari is now more popular browsers now.

  • Adhi on Aug 12, 2020, Reply

    thank you for sharing this module, what if i use 2 web camera and want to capture and save to the file?
    regards,
    adhi

  • Ricardo Barros Pereira on Aug 13, 2020, Reply

    Hi Benson, thank you for this awesome plugin! One question, is there any way to change the image resolution when using snap() function?

  • Sebastián Saldaña on Aug 30, 2020, Reply

    How can I reduce the length of the image URI to pass it as a paramter in a POST request? I am currently getting a payload error when submitting the request.

  • Rangga Adi Pratama on Sep 19, 2020, Reply

    Hello, how do you save the picture to app directory?

  • aryan chhajed on Sep 22, 2020, Reply

    can i use this in the visual code studio

  • mre on Oct 9, 2020, Reply

    How to switch to back Camera on Windows 10 device (e.g. A surface)?I can not access the Front cam there. Is there a way to do this with this .js lib? P.S: Switch to front cam does not work in example too…

    • benson_ruan on Dec 6, 2020, Reply

      For mobile phones, the camera usually named with ‘Front Camera’ and ‘Back Camera’. For Windows 10 surface, they could came with different names. In the webcam-easy.js selectCamera() function, you can modify the .includes(‘font’) and .includes(‘back’) to the camera names of your Windows 10 device

  • ermin on Oct 22, 2020, Reply

    Hello mr Benson, i’m enjoying your demo very much.. but have some difficulties implementing socket io. I would like to store captured image on server. Best Regards

  • abu kayis on Oct 27, 2020, Reply

    Hello Mr. Benson,

    thank you for the script. I want to ask how to display the full screen page?

    • benson_ruan on Dec 6, 2020, Reply

      Hi, to display full screen of your camera, you can modify the css of #webcam, with:100vw means full width of your screen, height:100vh means full height of your screen.

  • Tony on Nov 4, 2020, Reply

    If I display controls, they appear backwards; i.e., the stop button appears on the right instead of the left. Playing with scale(-1,1) didn’t seem to work for me.

  • marinetg on Nov 12, 2020, Reply

    Hi Benson, thanks so much for this lovely JavaScript module, it’s exactly what I was looking for! Any advice on how I can use it and add a custom photo frame to the photo? So when the camera is active, you see the photo frame on the screen, and it saves the photo frame with the photo taken. Thanks in advance!

    • benson_ruan on Dec 6, 2020, Reply

      Hi, I would suggest to overlay the photo frame html element over the webcame video object use css, then when you capture the photo, you would need to use some js library like html2canvas https://html2canvas.hertzen.com/

  • Albert Torres on Nov 16, 2020, Reply

    I have a laptop with front and rear camera I can see the rear camera how can I access the front camera?

    • benson_ruan on Dec 6, 2020, Reply

      For mobile phones, the camera usually named with ‘Front Camera’ and ‘Back Camera’. For your laptop, they could came with different names. In the webcam-easy.js selectCamera() function, you can modify the .includes(‘font’) and .includes(‘back’) to the camera names of your cameras

      • Manoux on Dec 6, 2020, Reply

        Hello : this behaviour is broken on iOs phones and iOs pads. ( they are called cam1 and cam2 ) , the only way on iOs is ask in the video constraints ( with “exact” ) . And be careful there is a typo error in your lib on “environment”.

        • Pat on Mar 20, 2021, Reply

          hi to you know, if this library is useful for IOS on mobile for rear cam too ? I can not change on start to enviroment. Have you experience

  • Manoux on Dec 1, 2020, Reply

    Hello thank you for this library : is there a way not to correlate the resolution of the screenshot, and the display size of the html element video ?
    Actually the resolution of the screenshot is decided by the css rules of the video element height and width.
    It should be independant, or customizable.
    I try change canvas height and width but it doesn’t change the behaviour.

  • AJS on Dec 4, 2020, Reply

    Hi, great work here!

    I test drove it, is there a way to improve the quality of the photos taken? I have a good camera on my phone, it takes great pictures when using the default camera app but when I tried it with this the quality of the photos taken by webcam-easy is not that good.

  • Samuel Napitupulu on Dec 7, 2020, Reply

    Hello, I have seen your good work but I am a beginner programmer. So I still can’t implement it on node js with hbs views. Can you help me with that ? Thank you

  • Simon Henkes on Dec 22, 2020, Reply

    I can seem to get your demo file working all it does is start the camera switch – is there something I am doing wrong – sorry novice.

  • TVH on Dec 25, 2020, Reply

    Great app and it worked as advertised. Thank you. One question… in addition to taking a picture I want an option to actually record the stream into a blob object, much like the short repeating clip you post on this page. Do you have a code snippet for that functionality?

  • Jason Oda on Feb 12, 2021, Reply

    Hi Benson,

    I’ve been struggling with these basics for a couple hours. No matter what I get this error:

    TypeError: Cannot read property ‘getUserMedia’ of undefined.

    Your version works on all my computers. I get this error on all of mine.

    Is there something I’m doing wrong here?: https://jsfiddle.net/bau2p7vq/10/

    Thanks! Any help would be appreciated!

    • benson_ruan on Feb 28, 2021, Reply

      I tested your code on that link you provided with Chrome on windows, and the webcam stream do work

  • Jason Oda on Feb 12, 2021, Reply

    MUST USE httpSSSSSSSS It’s important to point out this detail. It will fail every time unless the url you are using includes this. This robbed me of 3 hours of my life.

    • benson_ruan on Feb 28, 2021, Reply

      That’s correct, I did mention that in the above article in the section of “Check browser support”

  • jay on Feb 16, 2021, Reply

    hello,

    will this not work on http and is this only limited to https? I get a message when I run the app through a server . Fail to start camera please allow permission to access camera. Works only when we run the app on localhost .Any help?

    Thanks,
    jay

    • benson_ruan on Feb 28, 2021, Reply

      When you are accessing the camera on a public domain rather than localhost, it would require https. This is because modern browsers like Chrome, Safari, Firefox only allow https to access camera for security concern, you won’t find any javascript library that can access camera on http of a public domain.

  • OP on Mar 22, 2021, Reply

    Hello, does anyone has any code for the following:
    Open the phone camera
    scan QR code
    Save details of the QR code on the database of the member.

    Can anyone help?

  • Stefano Tampieri on Mar 25, 2021, Reply

    Hi,
    I am trying to use your library inside a Google Sheet to take a picture with a LOCAL WEBCAM or HTTP WEBCAM using Google Apps Script.
    It is possible ? Or I must use local NodeJS installation ? Can you help me ?

    • Stefano Tampieri on Mar 25, 2021, Reply

      I explain better, I want to make a DB of objects on GoogleSheet and save also a photo of the object using local webcam and save the jpg on a google sheet cell

  • Marian Boricean on Apr 23, 2021, Reply

    Hello! Thank you for this amazing project. I want to use the camera without the mirror function. How do I implement this using the webcam.easy program without modifying the source file?

    Thank you!

  • Ndjock Michel Junior on May 23, 2021, Reply

    Hello Benson thanks for this awesome plugin. but i have a problem, each time i start the webcam it appears for some seconds and then the video disappears. I don’t know what is wrong

  • Andy on May 24, 2021, Reply

    hello, please help me to add 5sec count down timer before it call webcam.snap() function, thanks

  • dhrumil shah on Jun 24, 2021, Reply

    Hello,

    I want to open my mobile camera with the highest resolution supported. Some mobile devices are capable of 2k whereas some are 4k. I want to make general function which will return highest possible resolution and open the camera with that configuration. Can I do that by using your module?

  • Shahroze Khan on Jun 29, 2021, Reply

    How would one get an image and upload it to a server?

  • Anamay on Sep 5, 2021, Reply

    Hi Benson, I am not able to take a snapshot using webcam.snap(). I want to save the snapshot in my local directory. How do I achieve this? Thanks.

  • John Shahin on Oct 3, 2021, Reply

    So so I need to use the CDN or are the supplied files the full plugin?

  • Suprabhat on Dec 18, 2021, Reply

    I wish to access a webcam through an IP address which is other than the current system in a LAN. How can I?

  • Suprabhat Mohapatra on Dec 20, 2021, Reply

    This is not working even after following all the steps…the following error is appearing

    typeError: Cannot set properties of undefined (setting ‘transform’)
    at webcam-easy.min.js:1

  • Roberto Romano on Apr 26, 2022, Reply

    Dear Mr. Benson,
    we are using your Plug-In in a little warehouse where the Operators would like to catch the photo of packaging and products packaged in 500g,750g boxes.
    We would need of IOS feature (with Safari) that uses the environment camera. The use of the front camera isn’t enough, and it is hard to apply in this case, unfortunately.
    Could you help us in this direction ?
    You can contact me directly in private if you prefer.
    We are available to consider your specific development/support to introduce the feature.
    Thanks a lot.
    Roberto

  • hemant kumar on Jun 17, 2022, Reply

    how to add camraflip on webcam in asp.net

  • Deepali Sonker on Jul 20, 2022, Reply

    Hi, I am using a HTTPS secured URL but still it is showing me permission error when i am trying to open back camera by setting the facinngmode Enviroment .
    It is working fine for the Front Camera only back camera is showing permission error in my android phone,

    Fail to start camera, please allow permission to access camera.
    If you are browsing through social media built in browsers, you would need to open the page in Safari (iPhone)/ Chrome (Android)

    • benson_ruan on Feb 28, 2023, Reply

      It is possible that you have not enabled the permission for the camera in your settings.

      To enable the permission, go to Settings > Apps > [App Name] > Permissions > Camera and enable the permission.

      Once you have enabled the permission, try opening the camera again.

  • Ibrahim.H on Oct 20, 2022, Reply

    Nice, I’ve just update some deps, and fixed webpack config.
    https://github.com/bensonruan/webcam-easy/pull/47

  • Suresh on Aug 13, 2023, Reply

    Hi this is very good help.
    But I want to just know how to allow webcam in CSP content security policy header.
    I m not able to access webcam if I put csp default-src self

    • benson_ruan on Aug 21, 2023, Reply

      Thank you for your comment! I’m glad that you found the information helpful.

      To allow access to the webcam in the Content Security Policy (CSP) header, you need to include the appropriate directive in your policy. The directive you are looking for is `media-src`.

      By default, the `default-src` directive only allows resources to be loaded from the same origin. This means that if you include `default-src self` in your CSP header, it will block any requests to access the webcam.

      To enable webcam access, you can modify your CSP header to include the `media-src` directive along with the `self` keyword. For example, you can set the CSP header as follows:

      “`
      Content-Security-Policy: default-src ‘self’; media-src ‘self’
      “`

      This will allow the browser to load media resources, including the webcam, from the same origin.

      Please note that modifying the CSP header can have security implications, so it’s important to carefully consider the risks and test thoroughly before implementing any changes.

  • César on Sep 28, 2023, Reply

    Hi, I’m using this fantastic plugin but it looks like it doesn’t works for Android devices or maybe I’m missing something.
    It runs very well on iOS devices but when I try with an Android phone, I’m always getting the “notreadableerror could not start video source”. I wonder that it’s due to the multiple cameras of the phone. Any suggestion to fix this?
    Thank you in advance

Leave a Reply