Screen Capture and Audio Recording in Chrome Extensions: Complete Guide (2026)
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
| Need | API | Context |
|---|---|---|
| Capture any screen/window | getDisplayMedia() | Content script, offscreen doc |
| Capture a specific tab | chrome.tabCapture | Service worker + offscreen doc |
| Audio-only capture | tabCapture.capture() | Popup (limited) |
| Background recording | Offscreen document | Service 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
| Option | Recommended Value | Purpose |
|---|---|---|
mimeType (video) | video/webm;codecs=vp9 | Best quality/size ratio |
mimeType (audio) | audio/webm;codecs=opus | High quality audio |
videoBitsPerSecond | 2500000 (2.5 Mbps) | Good quality at reasonable size |
audioBitsPerSecond | 128000 (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
I Built the Same Chrome Extension With 5 Different Frameworks. Here's What Actually Happened.
WXT vs Plasmo vs CRXJS vs Extension.js vs Bedframe. Real benchmarks, honest opinions, and the framework with 12K stars that's quietly dying.
5 Best Email Marketing Services to Grow Your Chrome Extension (2026)
Compare the top email marketing platforms for SaaS and Chrome extension developers. MailerLite, Mailchimp, Brevo, ActiveCampaign, and Drip reviewed.
15 Best Practices to Build a Browser Extension That Users Love (2026 Guide)
Master browser extension development in 2026. Manifest V3, security, performance, and UX best practices to build extensions users love.