tabCapture Permission

5 min read

tabCapture Permission

What It Grants

Access to the chrome.tabCapture API for capturing the visible area of a tab as a media stream (audio and/or video).

Manifest

{
  "permissions": ["tabCapture"]
}

User Warning

“Capture content of your screen” — this triggers a warning.

API Access

Events

Capture Options

interface CaptureOptions {
  audio: boolean;
  video: boolean;
  audioConstraints?: MediaStreamConstraints;
  videoConstraints?: MediaStreamConstraints;
}

Basic Tab Capture

chrome.tabCapture Basic Usage

// Must be called from a user gesture (popup click, action click)
chrome.tabCapture.capture(
  { audio: true, video: true },
  (stream) => {
    if (chrome.runtime.lastError || !stream) {
      console.error('Capture failed:', chrome.runtime.lastError?.message);
      return;
    }
    // Use the MediaStream
    const video = document.createElement('video');
    video.srcObject = stream;
    video.play();
  }
);

MV3 with getMediaStreamId

// In service worker — get stream ID
chrome.action.onClicked.addListener(async (tab) => {
  const streamId = await chrome.tabCapture.getMediaStreamId({ targetTabId: tab.id });

  // Send to offscreen document or popup to use with getUserMedia
  chrome.runtime.sendMessage({ type: 'START_CAPTURE', streamId });
});

// In offscreen.html or popup
chrome.runtime.onMessage.addListener(async (msg) => {
  if (msg.type === 'START_CAPTURE') {
    const stream = await navigator.mediaDevices.getUserMedia({
      audio: {
        mandatory: { chromeMediaSource: 'tab', chromeMediaSourceId: msg.streamId }
      },
      video: {
        mandatory: { chromeMediaSource: 'tab', chromeMediaSourceId: msg.streamId }
      }
    } as any);
    // Record or process the stream
  }
});

Recording Pattern

import { createMessenger } from '@theluckystrike/webext-messaging';

type Messages = {
  START_RECORDING: { request: { tabId: number }; response: { streamId: string } };
  STOP_RECORDING: { request: {}; response: { ok: boolean } };
};
const m = createMessenger<Messages>();

m.onMessage('START_RECORDING', async ({ tabId }) => {
  const streamId = await chrome.tabCapture.getMediaStreamId({ targetTabId: tabId });
  return { streamId };
});

Capture Status

chrome.tabCapture.onStatusChanged.addListener((info) => {
  console.log(`Tab ${info.tabId}: ${info.status}`);
  // status: 'pending', 'active', 'stopped', 'error'
});

// Check what's currently captured
const captured = await chrome.tabCapture.getCapturedTabs();
captured.forEach(info => {
  console.log(`Tab ${info.tabId}: ${info.status}`);
});

Storage Integration

import { createStorage, defineSchema } from '@theluckystrike/webext-storage';

const schema = defineSchema({
  isRecording: 'boolean',
  recordingTabId: 'number',
  recordingStartTime: 'number'
});
const storage = createStorage(schema, 'local');

Key Constraints

When to Use

When NOT to Use

Permission Check

import { checkPermission } from '@theluckystrike/webext-permissions';
const granted = await checkPermission('tabCapture');

Cross-References

Frequently Asked Questions

How do I capture tab content?

Use chrome.tabCapture.capture() to capture the visible area of a tab as a media stream. You’ll need the tabCapture permission.

Can I record tab audio?

Yes, include “audio” in the mediaType options to capture both video and audio from the tab. —

Part of the Chrome Extension Guide by theluckystrike. Built at zovo.one.

No previous article
No next article