Record Screen and Windows with Screen Capture API

This article explains how the Screen Capture API works in modern web browsers to capture and record screen, window, or tab contents using JavaScript. You will learn how to prompt users for screen access, handle the resulting media stream, and use the MediaRecorder API to save the captured content as a video file.

1. Capturing the Screen with getDisplayMedia()

The foundation of screen recording in the browser is the navigator.mediaDevices.getDisplayMedia() method. When invoked, the browser displays a native permission prompt allowing the user to select an entire screen, an application window, or a specific browser tab.

async function startCapture(displayMediaOptions) {
  let captureStream = null;
  try {
    captureStream = await navigator.mediaDevices.getDisplayMedia(displayMediaOptions);
  } catch (err) {
    console.error("Error: " + err);
  }
  return captureStream;
}

Calling this method returns a Promise that resolves to a MediaStream object containing at least one MediaStreamTrack representing the video feed of the captured screen.

2. Configuring Capture Options

You can pass a configuration object to getDisplayMedia() to specify constraints, such as capturing system audio or controlling cursor visibility.

const displayMediaOptions = {
  video: {
    displaySurface: "browser", // or "window", "monitor"
    cursor: "always" // or "motion", "never"
  },
  audio: {
    suppressLocalAudioPlayback: false
  }
};

Note: The browser enforces security restrictions. The user ultimately decides which surface to share, regardless of the suggested constraints.

3. Recording the Stream with MediaRecorder

Once you obtain the MediaStream, use the MediaRecorder API to encode and record the incoming frames.

Step 1: Initialize the Recorder

Pass the stream and desired MIME type to the MediaRecorder constructor.

const stream = await navigator.mediaDevices.getDisplayMedia({ video: true, audio: true });
const mediaRecorder = new MediaRecorder(stream, { mimeType: 'video/webm; codecs=vp9' });

Step 2: Collect Recorded Data

Listen for the dataavailable event, which fires periodically or when recording stops, to collect chunks of binary video data.

const recordedChunks = [];

mediaRecorder.ondataavailable = (event) => {
  if (event.data.size > 0) {
    recordedChunks.push(event.data);
  }
};

Step 3: Handle Recording Stop and Export

When the recording ends, assemble the chunks into a Blob. You can generate an object URL to preview the video in an HTML <video> element or download it directly.

mediaRecorder.onstop = () => {
  const blob = new Blob(recordedChunks, { type: 'video/webm' });
  const url = URL.createObjectURL(blob);
  
  // Create download link
  const a = document.createElement('a');
  a.href = url;
  a.download = 'screen-recording.webm';
  a.click();
  
  URL.revokeObjectURL(url);
};

// Start recording
mediaRecorder.start();

4. Handling User Termination

Users can stop sharing at any time using the browser’s built-in sharing bar. To handle this event gracefully, attach a listener to the video track’s ended event.

const videoTrack = stream.getVideoTracks()[0];

videoTrack.onended = () => {
  if (mediaRecorder.state !== 'inactive') {
    mediaRecorder.stop();
  }
  console.log('Screen sharing stopped by user.');
};

This workflow enables robust, native screen recording directly within the browser without requiring external software or browser extensions.