← Capability Elements: <usermedia> MVP

v151 · html · method + dictionary reference

setConstraints() / HTMLMediaStreamConstraints

The configuration channel for the getUserMedia() call a <usermedia> element makes: call setConstraints() with an HTMLMediaStreamConstraints dictionary (video and audio MediaTrackConstraintSet members) before the user interacts.

Syntax

// Specification IDL (Media Capture and Streams Extensions):
undefined setConstraints(optional HTMLMediaStreamConstraints constraints = {});

dictionary HTMLMediaStreamConstraints {
  MediaTrackConstraintSet video;
  MediaTrackConstraintSet audio;
};

// Usage:
const el = document.querySelector("usermedia");
el.setConstraints({
  video: { width: 1280, facingMode: "user" },
  audio: { echoCancellation: true, noiseSuppression: true }
});

Chromium ships the method and dictionary in user_media_element_constraints.idl (as a partial mixin on HTMLMediaCaptureElementBase). The MediaTrackConstraintSet members accept the same constraint properties as getUserMedia()width, height, frameRate, facingMode, echoCancellation, sampleRate, and so on — defined by Media Capture and Streams.

Source: Media Capture and Streams Extensions — The <usermedia> HTML element.

Inputs

One optional parameter, an HTMLMediaStreamConstraints dictionary, defaulting to {}:

HTMLMediaStreamConstraints members
MemberTypeMeaning
videoMediaTrackConstraintSetConstraints for the camera track. Omitting it does not disable video — see the backfill rule below.
audioMediaTrackConstraintSetConstraints for the microphone track. Omitting it does not disable audio — see the backfill rule below.

Two input rules matter, and both are defined by the shipping Chromium implementation, not the raw dictionary shape:

Source: Chromium user_media_element_constraints.cc — setConstraints backfill and SanitizeTrackConstraints; WPT set-constraints-combinations.tentative.https.html; Specification — constraint filter steps.

setConstraints() — outputs

Returns undefined. The observable effect is stored state — but only on the first call: Chromium's implementation is first-call-wins (if (did_set_constraints_) return;), so every later setConstraints() call is a permanent no-op that silently keeps the constraints from the first call. There is no way to reset or replace them afterwards, and no getter to read the stored constraints back — keep your own copy if you need it.

Source: Chromium user_media_element_constraints.cc — setConstraints() first-call-wins; Specification — setConstraints() steps. Source: Specification — setConstraints() steps; Chromium user_media_request_provider_impl.cc — StartRequest.

HTMLMediaStreamConstraints — outputs

The dictionary is a pure input shape — it has no methods and produces no value itself. Its observable effect is the shape of the eventual MediaStream: on a successful acquisition, el.stream contains a video track when video was present and an audio track when audio was present, configured as close to the constraints as the device allows (after the user agent's filtering). Constraint keys the device can't honor as preferences are simply approximated, per the standard Constrainable pattern.

Source: Specification — activation start stream and constraint filter; Media Capture and Streams — MediaTrackConstraintSet.

Errors

setConstraints() itself does not surface exceptions for ordinary dictionary input — it sanitizes and stores what you pass. Because missing members are always backfilled (and the never-configured path substitutes the { video: {}, audio: {} } default), there is no page-reachable “no constraints set” failure: a call like el.setConstraints({}) simply stores the audio+video default. Per WebIDL conversion, passing null or undefined is treated as an empty dictionary (same default outcome), while a throwing getter on the input object propagates its exception out of the call before any constraints are stored.

Source: Chromium user_media_element_constraints.cc — backfill makes the empty-request branch unreachable; Specification — setConstraints() steps. Source: Chromium user_media_request_provider_impl.cc — StartRequest constraint checks; Specification — setConstraints() steps.

Context

Receiver: any HTMLUserMediaElement instance (the method lives on the shared HTMLMediaCaptureElementBase mixin, so the same call exists on the experimental <camera>/<microphone> elements). Exposure: window only; the element operates only in secure contexts. Timing contract: call it before the user first interacts with the element — the method exists precisely because there is no declarative constraint syntax on the shipping MVP, so configuration is imperative-but-early. Feature-detect with "HTMLUserMediaElement" in window.

Source: Explainer — constraints configuration; Chromium runtime_enabled_features.json5; chromestatus.com/feature/4926233538330624.

Lifecycle

The constraints slot starts unset. If no setConstraints() call has happened when the first acquisition runs, the browser substitutes the secure default { video: {}, audio: {} }. The first setConstraints() call stores the sanitized dictionary; every later call is ignored — there is no merge, no replace, and no reset for the life of the element. Configure exactly once, before the user can click. If you need different constraints later, replace the element node in the DOM and configure the fresh instance before its first activation.

Source: Chromium user_media_element_constraints.cc — did_set_constraints_ first-call-wins; Explainer — constraints configuration.

Examples

const el = document.querySelector("usermedia");

// 1. Configure exactly once, early — before any click. Later calls are ignored.
el.setConstraints({
  video: { width: 1280, height: 720 },
  audio: { echoCancellation: true }
});

// 2. Omitting a member does NOT disable that kind — both camera and
//    microphone are always requested; missing members default to enabled:
document.querySelector("#defaults").setConstraints({ video: {} }); // still asks for mic too

// 3. Use bare scalars — parameterized forms are dropped entirely by
//    Chromium's sanitizer:
el.setConstraints({ video: { width: 1920 } });              // width kept
// el.setConstraints({ video: { width: { ideal: 1920 } } }); // width silently dropped

// 4. There is no reset: a second call is a no-op. To reconfigure, replace
//    the element node and configure the fresh instance before first use.
Source: WPT set-constraints-combinations.tentative.https.html; Chromium user_media_element_constraints.cc.

Compatibility

setConstraints() and HTMLMediaStreamConstraints — checked 2026-07-26
Engine / runtimeSupportNotes
Chrome / Edge (desktop)151Enabled by default (milestone listing; UserMediaElement status stable)
Chrome (Android)151Per the ChromeStatus feature detail (desktop + Android 151); not supported on Android WebView
FirefoxNot supported“Under consideration” (mozilla/standards-positions #1392)
SafariNot supportedNo signal (WebKit/standards-positions #651; WICG/PEPC #62)
BCDNo entryNo api/HTMLUserMediaElement.json in browser-compat-data as of 2026-07-26
WPTUpstream WPT coverage existshtml/semantics/permission-element/usermedia (incl. the setConstraints combinations test); also unit-tested in Chromium (core, modules)
Source: ChromeStatus API feature record.

Security and privacy

Declarative-style constraints carry the same device-fingerprinting weight as an imperative getUserMedia() constraints object — highly specific values probe camera capabilities. The explainer holds this API to the same mitigations as getUserMedia() (fuzzing exact values, withholding deviceId until a grant), and the required-constraint stripping doubles as an abuse guard: a site cannot force an OverconstrainedError oracle to learn device capabilities. Constraints never widen what the user consents to — the browser's prompt text reflects the actual camera/microphone request regardless of what the dictionary asked for.

Source: Explainer — constraint fingerprinting; Specification — constraint filter.