Screen and Tab Capture: getDisplayMedia, System Audio, and the Privacy UX That Matters

Capturing screens, windows, and tabs in the browser — what getDisplayMedia can and can't do, which system audio you actually get, and the privacy indicators users see.

getDisplayMedia() is the API behind every in-browser screen recorder, lecture capture tool, and “show me your screen” feature. It’s also the one with the most browser-specific behavior and the clearest privacy contract — which is exactly why it’s worth understanding properly.

What You Can and Cannot Capture

TargetChromeFirefoxSafariSystem Audio?
Full screenYesYesYes (15.1+)Chrome/Edge only
WindowYesYesYesNo (app-level, Chrome only)
TabYesYesYesYes (tab audio)

The key: browser choice determines what the user can pick — Chrome’s picker shows screen/window/tab; Firefox and Safari limit options. Design for the common denominator.

The Constraints That Matter

const stream = await navigator.mediaDevices.getDisplayMedia({
  video: {
    frameRate: { ideal: 30, max: 60 },
    width: { max: 1920 },
    height: { max: 1080 },
    displaySurface: 'monitor' // hint: prefer full screen over window/tab
  },
  audio: {
    echoCancellation: false, // don't suppress what you're trying to capture
    noiseSuppression: false,
    autoGainControl: false
  }
});

The System Audio Trap

audio: true in getDisplayMedia captures tab audio only (Chrome/Edge) — not system-wide audio. If you’re recording a video playing in another app, or system sounds, you get silence. The correct pattern: capture the screen with audio: true, then if the user needs app audio, they enable the “share audio” toggle in Chrome’s picker — the API can’t force it.

Privacy Indicators Are Mandatory

The browser forces a persistent indicator — screen recording shows a banner or icon the user cannot hide. This is a feature: it means the user always knows they’re being recorded. The UX implication is the opposite of camera capture: users trust screen recording more because the indicator is unavoidable.

The getDisplayMedia Flow

  1. User gesture required — same as getUserMedia; call from a click, not on load.
  2. Picker is browser-controlled — you can’t pre-select the screen; the user chooses.
  3. Track stops when the user ends sharing — listen for track.onended to clean up UI; the OS “Stop sharing” button kills your stream without a stop() call from your code.

“The picker is your UX bottleneck. Chrome’s tab picker is three clicks; the first-time user almost always picks the wrong thing. Put a one-line hint in your UI — ‘share the browser tab, not the screen’ — before they open it.”

Capture-recording recipes, audio capture workarounds, and the indicator UX we ship are in the screen capture production guide.