> ## Content Index
> Fetch the complete content index at: https://blog.addpipe.com/llms.txt
> Use this file to discover other available public pages before exploring further.

# Getting Started With getUserMedia in 2026
- URL: https://blog.addpipe.com/getusermedia-getting-started/
- Published: 2025-09-09T08:12:18.000Z
- Updated: 2026-08-19T13:42:36.000Z
- Author: Remus
- Tags: getUserMedia, #Import 2026-05-22 13:18

One of the features enabling today's modern web is [getUserMedia()](https://developer.mozilla.org/en-US/docs/Web/API/MediaDevices/getUserMedia), a powerful JavaScript method that allows developers to access the user's camera and microphone directly from the browser.

The method [has been implemented in browsers since 2012](https://caniuse.com/?search=getusermedia), and over the last 13 years, it has evolved significantly. The method is now core to WebRTC video conferencing, live streaming, taking photos, grabbing video frames, augmented reality, and [audio](https://addpipe.com/audio-recorder/) and [video recording](https://addpipe.com/video-recorder/) via powerful services like the [Pipe Recording Platform](https://addpipe.com/).

This article will cover what you need to know, as a developer, before and after calling `getUserMedia()`.

## Table of Contents

1. [Before The Call: Secure Contexts and Permissions](#before-the-call-secure-contexts-and-permissions)  
  - [Secure Context Requirement](#secure-context-requirement)
  - [Permissions Policy (former Feature Policy)](#permissions-policy-former-feature-policy)
  - [Browser and OS Permissions](#browser-and-os-permissions)
2. [Old variant: navigator.getUserMedia()](#old-variant-navigatorgetusermedia)
3. [Getting a Media Stream](#getting-a-media-stream)
4. [Handling getUserMedia Errors](#handling-getusermedia-errors)
5. [Getting a List of Available Devices](#getting-a-list-of-available-devices)
6. [Listening for Device Changes](#listening-for-device-changes)
7. [Working with Media Streams](#working-with-media-streams)
8. [Video and Audio Codecs](#video-and-audio-codecs)
9. [Understanding the Constraints Object](#understanding-the-constraints-object)  
  - [Browser-Level Support: getSupportedConstraints()](#browser-level-support-getsupportedconstraints)
  - [Device-Level Capabilities: getCapabilities()](#device-level-capabilities-getcapabilities)
10. [Browser Compatibility](#browser-compatibility)

## Before The Call: Secure Contexts and Permissions

Several gatekeepers safeguard the ability to access a user's devices to protect the user's privacy.

### Secure Context Requirement

The first thing you need to know is that the `getUserMedia` method is **only available in** [**secure contexts**](https://developer.mozilla.org/en-US/docs/Web/Security/Secure%5FContexts). What this means exactly is that your code must be served in one of the following ways:

- Using HTTPS: the page is served via `https://`
- Local resources, such as the following origins: `http://localhost`, `http://127.0.0.1`, or file URLS ( `file://`)

Failing to run/host your code in one of the above secure contexts will prevent `getUserMedia` from accessing the user's camera or microphone on modern browsers.

### Permissions Policy (former Feature Policy)

Chromium browsers (Chrome, Edge, Opera, etc.) implement the [Permissions Policy](https://developer.mozilla.org/en-US/docs/Web/HTTP/Guides/Permissions%5FPolicy) (formerly known as Feature Policy). Such a policy can be used to control which features are enabled in different parts of a website. For example, the policy can be configured to block access to the camera and/or microphone, as a result, interfering with your `getUserMedia` calls. 

Some environments, like [cross origin iframes](https://blog.addpipe.com/camera-and-microphone-access-in-cross-oirigin-iframes-with-feature-policy/), will have restrictive policies by default and will block capturing the camera or microphone. In other environments, you might hit a manually imposed permission policy.

To further familiarize yourself with how it works, check out the following materials we've written on the topic:

1. [Camera and Microphone Access In Cross Origin Iframes With getUserMedia](https://blog.addpipe.com/camera-and-microphone-access-in-cross-oirigin-iframes-with-feature-policy/)
2. [Recommended Permissions-Policy Settings](https://addpipe.com/docs/introduction/requirements/#permissions-policy-settings)

### Browser and OS Permissions

To access the user's media devices, the user must grant explicit permission at both the browser and OS levels. These permission prompts [will change over time](https://blog.addpipe.com/screen-sharing-got-smarter-and-more-private-on-macos-understanding-the-system-private-window-picker/) as browsers evolve and mature, so it is essential to keep track of them to ensure this important step is handled carefully and covers both grant and deny cases.

**Browser Level Permissions**

Every browser has a different permission dialog which behaves a bit differently. Chrome and Firefox permissions are persistent by default at the browser tab/session level. Firefox will ask permission for every individual device and always allowed you to change the shared device directly in the permission prompt. Safari's permissions are the least persistent.

**OS Level Permissions**

OS level permissions are prominent on macOS, where every non-Safari browser needs to be given individual permission by the user to capture the microphone, camera, and the screen & system sounds and then it needs to be restarted. But Windows 10 and 11 also have controls for preventing apps from accessing the camera and microphone. 

**Future `<permission>` tag**

Calling `getUserMedia()` is what currently triggers the permission prompt but this might change in the near future with the introduction of the [<permission> HTML tag](https://developer.chrome.com/blog/permission-element-origin-trial).

**Permissions API**

You can use the [Permissions API](https://developer.mozilla.org/en-US/docs/Web/API/Permissions%5FAPI) to check the status of permissions in the current context. If you're interested in learning how to detect how often users allow or deny camera and microphone access, you can read [this post](https://blog.addpipe.com/using-permissions-api-to-detect-getusermedia-responses/), and you can further delve into finding out more about `getUserMedia` [camera and microphone initialization times](https://blog.addpipe.com/getusermedia-camera-microphone-initialization-times/).

## Old Variant: `navigator.getUserMedia()`

You might encounter very old tutorials, code or documentation that mention the callback based `navigator.getUserMedia()`. The functionality has been moved to the promise based `navigator.mediaDevices.getUserMedia()` \- [with Chrome this happened in Chrome 53](https://chromestatus.com/feature/5755699816562688) \- and it's the version you should be using (even tough the older syntax might still be supported).

## Getting a Media Stream

Now that you are in a secure context and have navigated through all the permission hoops, you can finally gain access to the user's devices and obtain the prize: the [media stream](https://developer.mozilla.org/en-US/docs/Web/API/MediaStream).

To do so, you must call `navigator.mediaDevices.getUserMedia()`. This method takes a `MediaStreamConstraints` object as a parameter, which allows you to specify the type of media you want to access: audio, video, or both. Optionally, you can add specific granular requirements for both video and audio like the frame rate, resolution or preferred camera (front or back) on mobile devices. 

We will cover constraints in a bit more detail later. For now, here is a basic example of how to get the video and audio stream from a webcam:

```JavaScript
const constraints = {
  video: true,
  audio: true
};

navigator.mediaDevices.getUserMedia(constraints)
  .then(stream => {
    // You have a media stream, attribute it to the HTML video element
    const videoElement = document.querySelector('video');
    videoElement.srcObject = stream;
  })
  .catch(error => {
    // Handle errors
    console.error('Error accessing media devices.', error);
  });
```

Note that `getUserMedia` returns a `Promise`. This means you need to use `.then()` and `.catch()` to handle both success and failure cases.

## Handling `getUserMedia` Errors

In the code above, there's a `catch` statement, which, in a production environment, needs to be extended to gracefully handle a few common situations:

1. When no camera or microphone device exists you'll be met with a `NotFoundError`.
2. The camera device is already in use by another app results in a `NotReadableError`.
3. When the user has not granted permissions at the browser or OS level will result in a `NotAllowedError`.
4. Specific constraints cannot be met (exact resolution, aspect ratio or fps, etc.), an `OverconstrainedError` will be thrown.

We go over the [getUserMedia errors](https://blog.addpipe.com/common-getusermedia-errors/) in more detail in a separate post.

Even after a successful `getUserMedia` call, you might encounter error situations that need to be handled:

1. User mutes, disables or pulls out the camera or microphone device
2. User's device disconnects from Bluetooth or is out of battery (the iPhone can be used as a camera)
3. Computer/laptop is left unattended and it goes to sleep while device is accessed

Our own [Pipe recording client](https://addpipe.com/recording-client/) [handles many of these errors](https://blog.addpipe.com/building-the-best-camera-microphone-selector/).

## Getting a List of Available Devices

It is crucial to give your users the option to choose which camera and microphone they want to grant access to and use. Once permission is given, you can list the available media devices by calling `navigator.mediaDevices.enumerateDevices()`. This method will return an array of `MediaDeviceInfo` objects, and each of them will contain information about one particular device.

Here is a quick example:

```JavaScript
navigator.mediaDevices.enumerateDevices()
  .then(devices => {
    devices.forEach(device => {
      console.log(`${device.kind}: ${device.label} id = ${device.deviceId}`);
    });
  })
  .catch(error => {
    console.error('Error enumerating devices.', error);
  });
```

This apparently simple functionality is important for any app. **Allowing users to choose their preferred camera and microphone devices is crucial for ensuring privacy and that the correct device is used.** 

We've worked hard to build one of [the best camera and microphone selectors](https://blog.addpipe.com/building-the-best-camera-microphone-selector/) for our [Pipe recording client](https://addpipe.com/recording-client/).

## Listening for Device Changes

But what happens if a user plugs in a new microphone or connects a new Bluetooth headset while your application is running or after you've called `enumerateDevices()`? This is where the [ondevicechange event handler](https://developer.mozilla.org/en-US/docs/Web/API/MediaDevices/devicechange%5Fevent) comes in, which can be attached to the `navigator.mediaDevices` object:

```JavaScript
navigator.mediaDevices.ondevicechange = event => {
  // Handle device change
  console.log('A media device has been connected or disconnected.');
  // You can then call enumerateDevices() again to get the updated list
};
```

With it, you can gracefully handle changes in the list of devices.

****Start recording on your website today**

Add audio, video, and screen recordings to your website and explore the Pipe Platform for 2 weeks with our 14-day trial.

[Sign Up for a Trial ](https://dashboard.addpipe.com/signup) 

## Working with Media Streams

After `getUserMedia` is called successfully, you receive a `MediaStream` object that allows you to perform various actions. Here are a few examples:

- **Show the stream in an HTML video element**: This is the most basic use case, but it is a great way to provide immediate feedback of the user's camera and microphone.
- **Send the stream over WebRTC**: This implementation will enable real-time peer-to-peer communication with other users, allowing for video and audio calls. Integrations with services like [OpenAI's Realtime API](https://platform.openai.com/docs/guides/realtime) are another good example of streaming over WebRTC.
- **Record the stream using the** [MediaStream Recording API](https://developer.mozilla.org/en-US/docs/Web/API/MediaRecorder) to easily create and store video or audio files.
- **Process the stream in real time with the** [Canvas API](https://developer.mozilla.org/en-US/docs/Web/API/Canvas%5FAPI)for advanced visual effects (e.g., background blurring), image recognition, or analytical data gathering.
- **Capture a frame** using [ImageCapture.grabFrame()](https://developer.mozilla.org/en-US/docs/Web/API/ImageCapture) or **a photo** using [ImageCapture.takePhoto()](https://developer.mozilla.org/en-US/docs/Web/API/ImageCapture/takePhoto)

At [Pipe](https://addpipe.com/), we've developed a robust [audio and video recording client](https://addpipe.com/recording-client/) that does much of the heavy lifting for you, allowing for seamless recording of [video](https://addpipe.com/video-recorder/), [audio](https://addpipe.com/audio-recorder/), and [screen ](https://addpipe.com/screen-recorder/)directly from the browser. This way, our clients can focus on implementing their solutions instead of navigating the complexity of accessing the devices, recording, streaming, storage, etc..

## Video and Audio Codecs

After capturing the audio and video streams via `getUserMedia` method, using those streams in WebRTC or recording them will result in the data being encoded using varying audio and video codecs (and containers). 

For example, when recording the stream using the **MediaStream Recording API**, there are a bunch of codecs and containers that are available for audio and video encoding.

Here's a summary of the maximal audio and video capabilities of current major browsers:

| Browser         | Container   | Video Codecs                       | Audio Codecs |
| --------------- | ----------- | ---------------------------------- | ------------ |
| Google Chrome   | mp4 or webm | VP8, VP9, H.264, HEVC (H.265), AV1 | Opus, PCM    |
| Mozilla Firefox | webm        | VP8                                | Opus         |
| Apple Safari    | webm, mp4   | H264, VP8, VP9, HEVC (H.265), AV1  | AAC, Opus    |

Keep in mind, the available codecs differ based on the browser, OS, and hardware capabilities. On a simple `getUserMedia()` implementation you might get MP4 with H.264 and AAC audio from Safari and a WebM with H.265 and Opus from Chrome. You will definitely get VP8 video from Firefox.

Our [MediaStream Recording API demo](https://addpipe.com/media-recorder-api-demo/) has been updated so that you can play with these codecs and test what your current browser/OS/hardware supports.

Given the variety of possible codec combinations, in order to ensure maximum compatibility across devices, dedicated video recording platforms like [Pipe](https://addpipe.com/) will transcode the captured stream, server side, to a cross platform compatible .mp4 file.

## Understanding the Constraints Object

Remember when we talked earlier about the constraints object (`MediaStreamConstraints` actually) that is being passed to `getUserMedia` ? This object is key to getting the media stream that best fits the needs of your applications.

The most important thing to know about the `constraints` object is that it allows you to request certain media characteristics, but these are *requests,* not commands. The browser will do its best to meet your constraints, but the results may vary depending on the device's hardware capabilities.

The simplest constraints that you can specify are, as seen in the example we gave earlier, `{ video: true, audio: true }` .

You can also specify detailed requirements for:

- **Video constraints:** You can request a specific resolution (`width`, `height`), `framerate`, `aspectRatio` or `facingMode` (useful for selecting specific cameras on mobile devices)
- **Audio constraints:** You can control features like `echoCancellation`, `noiseSuppression` , and `autoGainControl`a
- **Screen constraints:** When it comes to screen capture, the counterpart for `getUserMedia` , is `getDisplayMedia` . Similarly, you can specify constraints for it. We will cover the specifics in an upcoming post.

For a deep dive into each type of constraint, you can check out our detailed articles on [video constraints](https://blog.addpipe.com/getusermedia-video-constraints/), [audio constraints](https://blog.addpipe.com/getusermedia-audio-constraints/), and our [examples page](https://addpipe.com/getusermedia-examples) to see some of them in action.

#### Browser-Level Support: `getSupportedConstraints()`

There is a helpful function to learn which constraints the browser itself supports, before even attempting to request a certain constraint.

`navigator.mediaDevices.getSupportedConstraints()` will return an object containing keys with the name of the constraint and their values, either `true` or `false` :

```JavaScript
const supportedConstraints = navigator.mediaDevices.getSupportedConstraints();
console.log(supportedConstraints);
// { "width": true, "height": true, "aspectRatio": true, ... }
```

#### Device-Level Capabilities: `getCapabilities()`

You can query the capabilities of the active camera or microphone directly. This can only be done once you get hold of the media stream, by calling the function `getCapabilities()` on the `MediaStreamTrack` .

This method will return a range of values that the device can support for each constraint (e.g, the minimum and maximum video resolution).

```JavaScript
// We assume you already have a stream object from getUserMedia()
const videoTrack = stream.getVideoTracks()[0];
const capabilities = videoTrack.getCapabilities();

console.log(capabilities);
// {
//   "width": { "min": 1, "max": 1920 },
//   "height": { "min": 1, "max": 1080 },
//   "frameRate": { "min": 0, "max": 30 },
//   ...
// }
```

Together, these two functions can help you build more robust applications. For example, you can display only the options that the user's hardware actually supports.

## Browser Compatibility

The core `getUserMedia` functionality has the advantage of being well-established with [wide browser support](https://developer.mozilla.org/en-US/docs/Web/API/MediaDevices/getUserMedia#browser%5Fcompatibility) including Chrome, Firefox, Safari, Edge, Brave, Opera, etc..

Other parts of the `getUserMedia` tech might not have as wide a support, so it is always wise to check with services like [caniuse.com](https://caniuse.com/) when making your implementation.