Screen Capture API (getDisplayMedia)
Published Updated
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
Section titled “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
Section titled “How to use it”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
Section titled “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:
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
Section titled “Practical checklist”- Per MDN,
getDisplayMedia()is only available in secure contexts (HTTPS) and requires thedisplay-capturePermissions Policy, which defaults toself(same-origin) — a cross-origin embedding iframe needs an explicitallow="display-capture"to use it. - Per the MDN guide, capture sources cannot be enumerated with
enumerateDevices()and never firedevicechangeevents, 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
getDisplayMediabut calls always failed withNotAllowedError; 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
Section titled “Where to go next”- WebRTC — sending a captured stream to another peer.
- Web Share API