How to Access the Device Camera Using the MediaDevices API: A Complete Guide

You can access the device camera using the MediaDevices API by calling navigator.mediaDevices.getUserMedia({ video: true }), which returns a Promise that resolves to a MediaStream you can attach to a <video> element's srcObject property.

The jisan-mia/dom-projects repository contains a practical Camera App implementation that demonstrates this pattern with clean, production-ready code. This guide breaks down the exact implementation found in the repository, showing you how to request camera permissions, display live video streams, and capture still images without external dependencies.

Understanding the MediaDevices API

The MediaDevices API is a Web API interface that provides access to connected media input devices such as cameras and microphones. The entry point is the navigator.mediaDevices object, which exposes the getUserMedia() method for requesting permission and obtaining media streams.

According to the source code in jisan-mia/dom-projects, the implementation relies on two core Web APIs working together:

  • MediaDevices.getUserMedia(): Requests permission and returns a MediaStream containing video tracks
  • HTMLCanvasElement.drawImage(): Captures individual frames from the video stream for still images

Project Structure and File Overview

The Camera App in the jisan-mia/dom-projects repository follows a standard three-file structure located in projects/camera-app/:

File Purpose Key Components
projects/camera-app/index.html Markup structure <video> element for streaming, <canvas> for snapshots, capture button
projects/camera-app/camera.js Core logic startCamera() and capturePhoto() functions
projects/camera-app/style.css Visual styling Responsive layout and UI polish

You can view the complete source code in the camera-app directory.

Implementing Camera Access in JavaScript

The camera.js file contains the essential logic for accessing the device camera using the MediaDevices API. The implementation breaks down into three distinct operations: requesting the media stream, binding it to the video element, and capturing still images.

Requesting Camera Permission with getUserMedia

The startCamera() function initiates the camera access flow. It uses navigator.mediaDevices.getUserMedia() with a constraints object specifying video access:

async function startCamera() {
  const video = document.getElementById('video');
  try {
    // Request webcam access – core Media Devices API call
    const stream = await navigator.mediaDevices.getUserMedia({ video: true });
    video.srcObject = stream;
  } catch (error) {
    console.error('Error accessing the camera:', error);
  }
}

The { video: true } constraint tells the browser to request access to the default video input device. This method returns a Promise that resolves to a MediaStream object containing the video track.

Binding the MediaStream to the Video Element

Once the Promise resolves, the code assigns the MediaStream to the srcObject property of the <video> element:

video.srcObject = await navigator.mediaDevices.getUserMedia({ video: true });

This binding is what causes the live camera feed to display in the browser. The autoplay attribute on the video element (set in the HTML) ensures the stream begins playing immediately after assignment.

Capturing Still Images with Canvas

The capturePhoto() function handles converting the live video frame into a static image. It uses the HTML5 Canvas API to draw the current video frame:

function capturePhoto() {
  const video = document.getElementById('video');
  const canvas = document.getElementById('canvas');
  const ctx = canvas.getContext('2d');

  // Size canvas to current video frame dimensions
  canvas.width = video.videoWidth;
  canvas.height = video.videoHeight;

  // Draw current frame onto canvas
  ctx.drawImage(video, 0, 0, canvas.width, canvas.height);
  canvas.style.display = 'block'; // Reveal captured image
}

Setting the canvas dimensions to match video.videoWidth and video.videoHeight ensures the captured image maintains the native resolution of the camera stream.

Complete Code Implementation

Here is the complete, runnable implementation based on the jisan-mia/dom-projects repository:

HTML (index.html):

<!DOCTYPE html>
<html lang="en">
<head>
  <meta charset="UTF-8">
  <meta name="viewport" content="width=device-width, initial-scale=1.0">
  <title>Camera App</title>
  <link rel="stylesheet" href="style.css">
</head>
<body>
  <div class="container">
    <h1>Camera App</h1>
    <video id="video" autoplay></video>
    <button id="capture">Capture Photo</button>
    <canvas id="canvas"></canvas>
  </div>
  <script src="camera.js"></script>
</body>
</html>

JavaScript (camera.js):

async function startCamera() {
  const video = document.getElementById('video');
  try {
    // Core MediaDevices API call to access device camera
    const stream = await navigator.mediaDevices.getUserMedia({ video: true });
    video.srcObject = stream;
  } catch (error) {
    console.error('Error accessing the camera:', error);
    alert('Unable to access camera. Please ensure you have granted permission.');
  }
}

function capturePhoto() {
  const video = document.getElementById('video');
  const canvas = document.getElementById('canvas');
  const ctx = canvas.getContext('2d');

  // Set canvas dimensions to match video stream
  canvas.width = video.videoWidth;
  canvas.height = video.videoHeight;

  // Draw current video frame to canvas
  ctx.drawImage(video, 0, 0, canvas.width, canvas.height);
  
  // Display the captured image
  canvas.style.display = 'block';
}

// Initialize camera when page loads
window.onload = startCamera;

// Wire up capture button
document.getElementById('capture').addEventListener('click', capturePhoto);

Error Handling and Browser Compatibility

The implementation in projects/camera-app/camera.js includes basic error handling using a try/catch block around the getUserMedia() call. This catches common failure scenarios including:

  • Permission denied: User blocks camera access through the browser dialog
  • No camera device: Hardware not detected or currently in use by another application
  • Insecure context: API only works on HTTPS or localhost environments

The MediaDevices API is supported in all modern browsers including Chrome, Firefox, Safari, and Edge. However, it requires a secure context (HTTPS or localhost) to function. Legacy browsers may require the deprecated navigator.getUserMedia() method with vendor prefixes, though modern applications should use the standard navigator.mediaDevices.getUserMedia() as implemented in the jisan-mia/dom-projects repository.

Summary

  • Access the device camera by calling navigator.mediaDevices.getUserMedia({ video: true }), which returns a Promise resolving to a MediaStream.
  • Bind the stream to a <video> element using video.srcObject = stream to display the live feed.
  • Capture still images by drawing the current video frame onto a <canvas> element using ctx.drawImage().
  • Handle errors with try/catch blocks to manage permission denials and missing hardware gracefully.
  • The jisan-mia/dom-projects repository provides a complete working example in projects/camera-app/ with camera.js, index.html, and style.css.

Frequently Asked Questions

What is the MediaDevices API?

The MediaDevices API is a Web API interface that provides access to connected media input devices such as cameras and microphones. It is accessed through the navigator.mediaDevices object and provides methods like getUserMedia() to request user permission and obtain media streams for processing or display in web applications.

How do I handle permission denials when accessing the camera?

Wrap your navigator.mediaDevices.getUserMedia() call in a try/catch block. If the user denies permission, the Promise rejects and execution jumps to the catch block. Log the error to the console and display a user-friendly alert or message explaining that camera access is required for the application to function properly.

Can I access the rear camera on mobile devices using this API?

Yes, you can specify which camera to use by passing constraints to getUserMedia(). Instead of { video: true }, use { video: { facingMode: "environment" } } to access the rear camera, or { video: { facingMode: "user" } } for the front camera. The jisan-mia/dom-projects implementation uses the default camera, but you can modify the constraints object in camera.js to target specific devices.

Is the MediaDevices API supported in all browsers?

The MediaDevices API is supported in all modern browsers including Chrome, Firefox, Safari, and Edge. However, it requires a secure context (HTTPS or localhost) to function. Legacy browsers may require the deprecated navigator.getUserMedia() method with vendor prefixes, though modern applications should use the standard navigator.mediaDevices.getUserMedia() as implemented in the jisan-mia/dom-projects repository.

Have a question about this repo?

These articles cover the highlights, but your codebase questions are specific. Give your agent direct access to the source. Share this with your agent to get started:

Share the following with your agent to get started:
curl -s "https://instagit.com/install.md"

Works with
Claude Codex Cursor VS Code OpenClaw Any MCP Client

Maintain an open-source project? Get it listed too →