Screen Capture and Audio Recording in Chrome Extensions: Complete Guide (2026)

AppBooster Team · · 4 min read
Screen recording interface on a monitor

Screen Capture and Audio Recording for Chrome Extensions

Building a screen recorder, tab capturer, or audio recording extension? Chrome provides multiple APIs depending on what you need to capture: entire screens, specific tabs, or audio streams. This guide covers every approach with production-ready code.


Choosing the Right API

NeedAPIContext
Capture any screen/windowgetDisplayMedia()Content script, offscreen doc
Capture a specific tabchrome.tabCaptureService worker + offscreen doc
Audio-only capturetabCapture.capture()Popup (limited)
Background recordingOffscreen documentService worker orchestrated

Screen Recording with getDisplayMedia

The standard Web API triggers a system dialog letting users choose which screen, window, or tab to share:

async function startScreenCapture() {
  const stream = await navigator.mediaDevices.getDisplayMedia({
    video: {
      width: { ideal: 1920 },
      height: { ideal: 1080 },
      frameRate: { ideal: 30 }
    },
    audio: true
  });

  const recorder = new MediaRecorder(stream, {
    mimeType: 'video/webm;codecs=vp9',
    videoBitsPerSecond: 2500000
  });

  const chunks = [];
  recorder.ondataavailable = (e) => chunks.push(e.data);
  recorder.onstop = () => {
    const blob = new Blob(chunks, { type: 'video/webm' });
    const url = URL.createObjectURL(blob);
    downloadRecording(url);
  };

  recorder.start(1000); // Capture in 1-second chunks
  return { stream, recorder };
}

Important: When called from a content script, recording stops if the user navigates away from the page. For persistent recording, use an offscreen document.


Tab Capture with Offscreen Documents (Chrome 116+)

The recommended modern approach for capturing a specific tab’s content:

service-worker.js

chrome.action.onClicked.addListener(async (tab) => {
  // Get a media stream ID for the current tab
  const streamId = await chrome.tabCapture.getMediaStreamId({
    targetTabId: tab.id
  });

  // Create offscreen document for recording
  const existingContexts = await chrome.runtime.getContexts({
    contextTypes: ['OFFSCREEN_DOCUMENT']
  });

  if (existingContexts.length === 0) {
    await chrome.offscreen.createDocument({
      url: 'offscreen.html',
      reasons: [chrome.offscreen.Reason.DISPLAY_MEDIA],
      justification: 'Tab capture for recording'
    });
  }

  // Send stream ID to offscreen document
  chrome.runtime.sendMessage({
    action: 'startCapture',
    streamId: streamId,
    tabId: tab.id
  });
});

offscreen.js

let recorder = null;
let chunks = [];

chrome.runtime.onMessage.addListener(async (message) => {
  if (message.action === 'startCapture') {
    const stream = await navigator.mediaDevices.getUserMedia({
      audio: {
        mandatory: {
          chromeMediaSource: 'tab',
          chromeMediaSourceId: message.streamId
        }
      },
      video: {
        mandatory: {
          chromeMediaSource: 'tab',
          chromeMediaSourceId: message.streamId
        }
      }
    });

    recorder = new MediaRecorder(stream, {
      mimeType: 'video/webm;codecs=vp9'
    });

    chunks = [];
    recorder.ondataavailable = (e) => chunks.push(e.data);
    recorder.onstop = () => {
      const blob = new Blob(chunks, { type: 'video/webm' });
      // Send blob URL back to service worker or popup
      chrome.runtime.sendMessage({
        action: 'recordingComplete',
        url: URL.createObjectURL(blob),
        size: blob.size
      });
    };

    recorder.start(1000);
  }

  if (message.action === 'stopCapture' && recorder) {
    recorder.stop();
    recorder.stream.getTracks().forEach((track) => track.stop());
  }
});

Audio-Only Tab Capture

For extensions that only need audio (podcast recorders, transcription tools):

// Works in popup context
async function captureTabAudio(tabId) {
  const streamId = await chrome.tabCapture.getMediaStreamId({
    targetTabId: tabId
  });

  const stream = await navigator.mediaDevices.getUserMedia({
    audio: {
      mandatory: {
        chromeMediaSource: 'tab',
        chromeMediaSourceId: streamId
      }
    },
    video: false
  });

  const recorder = new MediaRecorder(stream, {
    mimeType: 'audio/webm;codecs=opus'
  });

  const chunks = [];
  recorder.ondataavailable = (e) => chunks.push(e.data);
  recorder.onstop = () => {
    const blob = new Blob(chunks, { type: 'audio/webm' });
    const url = URL.createObjectURL(blob);
    // Download or process the audio
  };

  recorder.start();
  return { stream, recorder };
}

Recording Controls UI

Build a minimal popup to control recording:

<!DOCTYPE html>
<html>
<head>
  <style>
    body { width: 240px; padding: 16px; font-family: system-ui; }
    .btn { width: 100%; padding: 10px; border: none; border-radius: 6px; font-size: 14px; cursor: pointer; margin: 4px 0; }
    .start { background: #22c55e; color: white; }
    .stop { background: #ef4444; color: white; }
    .status { text-align: center; font-size: 13px; color: #666; margin-top: 8px; }
    .recording { color: #ef4444; font-weight: 600; }
  </style>
</head>
<body>
  <button class="btn start" id="startBtn">Start Recording</button>
  <button class="btn stop" id="stopBtn" disabled>Stop Recording</button>
  <div class="status" id="status">Ready</div>
  <script src="popup.js"></script>
</body>
</html>

MediaRecorder Options

OptionRecommended ValuePurpose
mimeType (video)video/webm;codecs=vp9Best quality/size ratio
mimeType (audio)audio/webm;codecs=opusHigh quality audio
videoBitsPerSecond2500000 (2.5 Mbps)Good quality at reasonable size
audioBitsPerSecond128000 (128 kbps)Standard audio quality

Permissions Required

{
  "permissions": ["tabCapture", "offscreen"],
  "host_permissions": ["<all_urls>"]
}

What’s Next

Screen capture and audio recording are high-value features that set extensions apart. Use tabCapture with offscreen documents for the most reliable approach, and always give users clear recording controls.

Build and grow your recording extension with ExtensionBooster’s developer tools.

Share this article

Build better extensions with free tools

Icon generator, MV3 converter, review exporter, and more — no signup needed.

Related Articles