The MediaDevices.getUserMedia() method prompts the user for permission to use a media input which produces a MediaStream with tracks containing the requested types of media. That stream can include, for example, a video track (produced by either a hardware or virtual video source such as a camera, video recording device, screen sharing service, and so forth), an audio track (similarly, produced by a physical or virtual audio source like a microphone, A/D converter, or the like), and possibly other track types.

It returns a Promise that resolves to a MediaStream object. If the user denies permission, or matching media is not available, then the promise is rejected with NotAllowedError or NotFoundError respectively.

Note: It's possible for the returned promise to neither resolve nor reject, as the user is not required to make a choice at all and may simply ignore the request.

Generally, you will access the MediaDevices singleton object using navigator.mediaDevices, like this:

async function getMedia(pc) {
  let stream = null;

  try {
    stream = await navigator.mediaDevices.getUserMedia(constraints);
    /* use the stream */
  } catch(err) {
    /* handle the error */
  }
}

Similarly, using the raw promises directly, the code looks like this:

navigator.mediaDevices.getUserMedia(constraints)
.then(function(stream) {
  /* use the stream */
})
.catch(function(err) {
  /* handle the error */
});

Note: If the current document isn't loaded securely, navigator.mediaDevices will be undefined, and you cannot use getUserMedia(). See Security for more information on this and other security issues related to using getUserMedia().

Syntax

var promise = navigator.mediaDevices.getUserMedia(constraints);

Parameters

constraints

A MediaStreamConstraints object specifying the types of media to request, along with any requirements for each type.

The constraints parameter is a MediaStreamConstraints object with two members: video and audio, describing the media types requested. Either or both must be specified. If the browser cannot find all media tracks with the specified types that meet the constraints given, then the returned promise is rejected with NotFoundError.

The following requests both audio and video without any specific requirements:

{ audio: true, video: true }

If true is specified for a media type, the resulting stream is required to have that type of track in it. If one cannot be included for any reason, the call to getUserMedia() will result in an error.

While information about a user's cameras and microphones are inaccessible for privacy reasons, an application can request the camera and microphone capabilities it needs and wants, using additional constraints. The following expresses a preference for 1280x720 camera resolution:

{
  audio: true,
  video: { width: 1280, height: 720 }
}

The browser will try to honor this, but may return other resolutions if an exact match is not available, or the user overrides it.

To require a capability, use the keywords min, max, or exact (a.k.a. min == max). The following demands a minimum resolution of 1280x720:

{
  audio: true,
  video: {
    width: { min: 1280 },
    height: { min: 720 }
  }
}

If no camera exists with this resolution or higher, then the returned promise will be rejected with OverconstrainedError, and the user will not be prompted.

The reason for the difference in behavior is that the keywords min, max, and exact are inherently mandatory, whereas plain values and a keyword called ideal are not. Here's a fuller example:

{
  audio: true,
  video: {
    width: { min: 1024, ideal: 1280, max: 1920 },
    height: { min: 776, ideal: 720, max: 1080 }
  }
}

An ideal value, when used, has gravity, which means that the browser will try to find the setting (and camera, if you have more than one), with the smallest fitness distance from the ideal values given.

Plain values are inherently ideal, which means that the first of our resolution examples above could have been written like this:

{
  audio: true,
  video: {
    width: { ideal: 1280 },
    height: { ideal: 720 }
  }
}

Not all constraints are numbers. For example, on mobile devices, the following will prefer the front camera (if one is available) over the rear one:

{ audio: true, video: { facingMode: "user" } }

To require the rear camera, use:

{ audio: true, video: { facingMode: { exact: "environment" } } }

Another non-number constraint is the deviceId constraint. if you have a deviceId from mediaDevices.enumerateDevices(), you can use it to request a specific device:

{ video: { deviceId: myPreferredCameraDeviceId } }

The above will return the camera you requested, or a different camera if that specific camera is no longer available. Again, to require the specific camera, you would use:

{ video: { deviceId: { exact: myExactCameraOrBustDeviceId } } }

Return value

A Promise whose fulfillment handler receives a MediaStream object when the requested media has successfully been obtained.

Exceptions

Rejections of the returned promise are made by passing a DOMException error object to the promise's failure handler. Possible errors are:

AbortError
Although the user and operating system both granted access to the hardware device, and no hardware issues occurred that would cause a NotReadableError, some problem occurred which prevented the device from being used.
NotAllowedError
One or more of the requested source devices cannot be used at this time. This will happen if the browsing context is insecure (that is, the page was loaded using HTTP rather than HTTPS). It also happens if the user has specified that the current browsing instance is not permitted access to the device, the user has denied access for the current session, or the user has denied all access to user media devices globally. On browsers that support managing media permissions with Feature Policy, this error is returned if Feature Policy is not configured to allow access to the input source(s).
Older versions of the specification used SecurityError for this instead; SecurityError has taken on a new meaning.
NotFoundError
No media tracks of the type specified were found that satisfy the given constraints.
NotReadableError
Although the user granted permission to use the matching devices, a hardware error occurred at the operating system, browser, or Web page level which prevented access to the device.
OverconstrainedError
The specified constraints resulted in no candidate devices which met the criteria requested. The error is an object of type OverconstrainedError, and has a constraint property whose string value is the name of a constraint which was impossible to meet, and a message property containing a human-readable string explaining the problem.
Because this error can occur even when the user has not yet granted permission to use the underlying device, it can potentially be used as a fingerprinting surface.
SecurityError
User media support is disabled on the Document on which getUserMedia() was called. The mechanism by which user media support is enabled and disabled is left up to the individual user agent.
TypeError
The list of constraints specified is empty, or has all constraints set to false. This can also happen if you try to call getUserMedia() in an insecure context, since navigator.mediaDevices is undefined in an insecure context.

Privacy and security

As an API that may involve significant privacy concerns, getUserMedia()'s specification lays out a wide array of privacy and security requirements that browsers are obligated to meet.

getUserMedia() is a powerful feature which can only be used in secure contexts; in insecure contexts, navigator.mediaDevices is undefined, preventing access to getUserMedia(). In addition, user permission is always required to access the user's audio and video inputs. Only a window's top-level document context for a valid origin can even request permission to use getUserMedia(), unless the top-level context expressly grants permission for a given <iframe> to do so using Feature Policy. Otherwise, the user will never even be asked for permission to use the input devices.

For additional details on these requirements and rules, how they are reflected in the context in which your code is running, and about how browsers manage user privacy and security issues, read on.

User privacy

As an API that may involve significant privacy concerns, getUserMedia() is held by the specification to very specific requirements for user notification and permission management. First, getUserMedia() must always get user permission before opening any media gathering input such as a webcam or microphone. Browsers may offer a once-per-domain permission feature, but they must ask at least the first time, and the user must specifically grant ongoing permission if they choose to do so.

Of equal importance are the rules around notification. Browsers are required to display an indicator that shows that a camera or microphone is in use, above and beyond any hardware indicator that may exist. They must also show an indicator that permission has been granted to use a device for input, even if the device is not actively recording at the moment.

In Firefox, for example, the URL bar displays a pulsing red icon to indicate that recording is underway. The icon is gray if the permission is in place but recording is not currently underway. The device's physical light is used to indicate whether or not recording is currently active. If you've muted your camera (so-called "facemuting"), your camera's activity light goes out to indicate that the camera is not actively recording you, without discarding the permission to resume using the camera once muting is over.

Security

There are a number of ways security management and controls in a user agent can cause getUserMedia() to return a security-related error.

Note: The security model for getUserMedia() is still somewhat in flux. The originally-designed security mechanism is in the process of being replaced with Feature Policy, so various browsers have different levels of security support, using different mechanisms. You should test your code carefully on a variety of devices and browsers to be sure it is as broadly compatible as possible

Feature Policy

getUserMedia() permissions will, in the future, be managed using Feature Policy. Not all browsers support this yet (Chrome being the current exception), so for the time being, you need to use some care while developing your code, to be sure it works whether Feature Policy is supported or not. On Chrome, Feature Policy is required in order to do things like use getUserMedia() in a cross-origin <iframe>.

Read our guide, Using Feature Policy, to learn more about how it works.

Encryption based security

The getUserMedia() method is only available in secure contexts. A secure context is one the browser is reasonably confident contains a document which was loaded securely, using HTTPS/TLS, and has limited exposure to insecure contexts. If a document isn't loaded in a secure context, the navigator.mediaDevices property is undefined, making access to getUserMedia() impossible.

Attempting to access getUserMedia() in this situation will result in a TypeError.

Document source security

Because of the obvious security concern associated with getUserMedia() if used unexpectedly or without security being carefully managed, it can only be used in secure contexts. There are a number of insecure ways to load a document that might, in turn, attempt to call getUserMedia(). The following are examples of situations in which getUserMedia() is not permitted to be called:

  • A document loaded into a sandboxed <iframe> element cannot call getUserMedia() unless the <iframe> has its sandbox attribute set to allow-same-origin.
  • A document loaded using a data:// or blob:// URL which has no origin (such as when one of these URLs is typed by the user into the address bar) cannot call getUserMedia(). These kinds of URLs loaded from JavaScript code inherit the script's permissions.
  • Any other situation in which there is no origin, such as when the srcdoc attribute is used to specify the contents of a frame.

Examples

Width and height

This example gives a preference for camera resolution, and assigns the resulting MediaStream object to a video element.

// Prefer camera resolution nearest to 1280x720.
var constraints = { audio: true, video: { width: 1280, height: 720 } }; 

navigator.mediaDevices.getUserMedia(constraints)
.then(function(mediaStream) {
  var video = document.querySelector('video');
  video.srcObject = mediaStream;
  video.onloadedmetadata = function(e) {
    video.play();
  };
})
.catch(function(err) { console.log(err.name + ": " + err.message); }); // always check for errors at the end.

Using the new API in older browsers

Here's an example of using navigator.mediaDevices.getUserMedia(), with a polyfill to cope with older browsers. Note that this polyfill does not correct for legacy differences in constraints syntax, which means constraints won't work well across browsers. It is recommended to use the adapter.js polyfill instead, which does handle constraints.

// Older browsers might not implement mediaDevices at all, so we set an empty object first
if (navigator.mediaDevices === undefined) {
  navigator.mediaDevices = {};
}

// Some browsers partially implement mediaDevices. We can't just assign an object
// with getUserMedia as it would overwrite existing properties.
// Here, we will just add the getUserMedia property if it's missing.
if (navigator.mediaDevices.getUserMedia === undefined) {
  navigator.mediaDevices.getUserMedia = function(constraints) {

    // First get ahold of the legacy getUserMedia, if present
    var getUserMedia = navigator.webkitGetUserMedia || navigator.mozGetUserMedia;

    // Some browsers just don't implement it - return a rejected promise with an error
    // to keep a consistent interface
    if (!getUserMedia) {
      return Promise.reject(new Error('getUserMedia is not implemented in this browser'));
    }

    // Otherwise, wrap the call to the old navigator.getUserMedia with a Promise
    return new Promise(function(resolve, reject) {
      getUserMedia.call(navigator, constraints, resolve, reject);
    });
  }
}

navigator.mediaDevices.getUserMedia({ audio: true, video: true })
.then(function(stream) {
  var video = document.querySelector('video');
  // Older browsers may not have srcObject
  if ("srcObject" in video) {
    video.srcObject = stream;
  } else {
    // Avoid using this in new browsers, as it is going away.
    video.src = window.URL.createObjectURL(stream);
  }
  video.onloadedmetadata = function(e) {
    video.play();
  };
})
.catch(function(err) {
  console.log(err.name + ": " + err.message);
});

Frame rate

Lower frame-rates may be desirable in some cases, like WebRTC transmissions with bandwidth restrictions.

var constraints = { video: { frameRate: { ideal: 10, max: 15 } } };

Front and back camera

On mobile phones.

var front = false;
document.getElementById('flip-button').onclick = function() { front = !front; };

var constraints = { video: { facingMode: (front? "user" : "environment") } };

Specifications

Specification Status Comment
Media Capture and Streams
The definition of 'MediaDevices.getUserMedia()' in that specification.
Candidate Recommendation Initial definition

Browser compatibility

Update compatibility data on GitHub
DesktopMobile
ChromeEdgeFirefoxInternet ExplorerOperaSafariAndroid webviewChrome for AndroidEdge MobileFirefox for AndroidOpera for AndroidSafari on iOSSamsung Internet
getUserMediaChrome Full support 52
Full support 52
No support 47 — 52
Notes Disabled
Notes Older versions of Chrome implement navigator.webkitGetUserMedia, a prefixed form of the legacy navigator.getUserMedia API.
Disabled From version 47 until version 52 (exclusive): this feature is behind the Experimental Web Platform features preference (needs to be set to Enabled). To change preferences in Chrome, visit chrome://flags.
Edge Full support 12Firefox Full support 36
Notes
Full support 36
Notes
Notes Older versions of Firefox implement navigator.mozGetUserMedia, a prefixed form of the legacy navigator.getUserMedia API.
Notes Before Firefox 55, getUserMedia() incorrectly returns NotSupportedError when the list of constraints specified is empty, or has all constraints set to false. Starting in Firefox 55, this situation now correctly calls the failure handler with a TypeError.
Notes When using the Firefox-specific video constraint called mediaSource to request display capture, Firefox 66 and later consider values of screen and window to both cause a list of screens and windows to be shown.
Notes Starting in Firefox 66, getUserMedia() can no longer be used in sandboxed <iframe>s or data URLs entered in the address bar by the user.
IE No support NoOpera Full support 40
Full support 40
No support 34 — 40
Notes Disabled
Notes Older versions of Opera implement navigator.webkitGetUserMedia, a prefixed form of the legacy navigator.getUserMedia API.
Disabled From version 34 until version 40 (exclusive): this feature is behind the Experimental Web Platform features preference (needs to be set to Enabled).
Safari Full support 11WebView Android Full support 53Chrome Android Full support 52
Full support 52
No support 47 — 52
Notes Disabled
Notes Older versions of Chrome implement navigator.webkitGetUserMedia, a prefixed form of the legacy navigator.getUserMedia API.
Disabled From version 47 until version 52 (exclusive): this feature is behind the Experimental Web Platform features preference (needs to be set to Enabled). To change preferences in Chrome, visit chrome://flags.
Edge Mobile Full support YesFirefox Android Full support 36
Notes
Full support 36
Notes
Notes Older versions of Firefox implement navigator.mozGetUserMedia, a prefixed form of the legacy navigator.getUserMedia API.
Notes Before Firefox 55, getUserMedia() incorrectly returns NotSupportedError when the list of constraints specified is empty, or has all constraints set to false. Starting in Firefox 55, this situation now correctly calls the failure handler with a TypeError.
Notes When using the Firefox-specific video constraint called mediaSource to request display capture, Firefox 66 and later consider values of screen and window to both cause a list of screens and windows to be shown.
Notes Starting in Firefox 66, getUserMedia() can no longer be used in sandboxed <iframe>s or data URLs entered in the address bar by the user.
Opera Android Full support 40
Full support 40
No support 34 — 40
Notes Disabled
Notes Older versions of Opera implement navigator.webkitGetUserMedia, a prefixed form of the legacy navigator.getUserMedia API.
Disabled From version 34 until version 40 (exclusive): this feature is behind the Experimental Web Platform features preference (needs to be set to Enabled).
Safari iOS Full support 11Samsung Internet Android ?
Secure context requiredChrome Full support YesEdge ? Firefox ? IE No support NoOpera ? Safari ? WebView Android ? Chrome Android Full support YesEdge Mobile ? Firefox Android ? Opera Android ? Safari iOS ? Samsung Internet Android ?

Legend

Full support  
Full support
No support  
No support
Compatibility unknown  
Compatibility unknown
See implementation notes.
See implementation notes.
User must explicitly enable this feature.
User must explicitly enable this feature.

See also