# Screen Capture API (getDisplayMedia)

> getDisplayMedia() lets a page prompt the user to capture a screen, window, or tab as a MediaStream, for recording locally or sending over WebRTC.

The **Screen Capture API** extends Media Capture and Streams with
`navigator.mediaDevices.getDisplayMedia()`, which prompts the user to pick a screen,
window, or tab and returns a `MediaStream` of that display surface for recording or
sending over the network.

## Where it's supported

Per MDN's browser-compat-data, `getDisplayMedia()` is supported on desktop Chrome
(since version 72), Edge (79), Firefox (66), and Safari (13). Chrome for Android
(72–88) and Firefox for Android (66–79) previously exposed the method but calls
always failed with `NotAllowedError`; current browser-compat-data records both
platforms as unsupported, and Safari on iOS does not support it either. Per MDN,
the feature has "Limited availability" and is not part of the Baseline
widely-available set, so treat it as unavailable until you confirm support on your
target browser rather than assuming it works everywhere `MediaDevices` does.

## How to use it

```js
async function startCapture() {
  try {
    const stream = await navigator.mediaDevices.getDisplayMedia({
      video: { displaySurface: 'browser' },
      audio: false,
    });
    return stream;
  } catch (err) {
    console.error(`getDisplayMedia failed: ${err.name}`);
    return null;
  }
}
```

Per MDN, `getDisplayMedia()` requires transient user activation (it must be called
from a user gesture such as a click handler) and prompts the user every time — the
choice of source cannot be persisted or made automatically. The `video` option
defaults to `true`, so a video track is always requested unless you explicitly
pass `video: false` — which MDN says rejects with a `TypeError`, since capturing
audio alone is not supported.

## How to detect it at runtime

Feature-detect `getDisplayMedia` before calling it, and fall back to a UI that
explains screen sharing isn't available when it's missing or the call fails:

```js
async function captureScreenOrFallback() {
  if (!navigator.mediaDevices?.getDisplayMedia) {
    // Not supported in this browser — show a message instead of a blank screen.
    return null;
  }
  try {
    return await navigator.mediaDevices.getDisplayMedia({ video: true });
  } catch {
    // User declined the prompt, or no capture source was available.
    return null;
  }
}
```

## Practical checklist

- Per MDN, `getDisplayMedia()` is only available in secure contexts (HTTPS) and
  requires the `display-capture` Permissions Policy, which defaults to `self`
  (same-origin) — a cross-origin embedding iframe needs an explicit
  `allow="display-capture"` to use it.
- Per the MDN guide, capture sources cannot be enumerated with
  `enumerateDevices()` and never fire `devicechange` events, so build your own UI
  around the picker the browser shows rather than listing sources yourself.
- Per the MDN guide, constraints you pass do not filter what the user is offered —
  they are applied to the stream only after the user has already chosen a source,
  so a constraint you need cannot be used to narrow the picker.
- Per the MDN guide, an audio track is optional and browser-dependent: even when
  you request `audio: true`, the returned stream may carry video only.
- Per browser-compat-data, Chrome for Android 72–88 and Firefox for Android 66–79
  exposed `getDisplayMedia` but calls always failed with `NotAllowedError`; current
  entries mark both platforms unsupported, so feature-detecting the method's
  presence alone is not a reliable signal of support on older releases.

## Where to go next

- [WebRTC](/reference/capabilities/webrtc/) — sending a captured stream to
  another peer.
- [Web Share API](/reference/capabilities/web-share/)