Implementation:Puppeteer Puppeteer Cdp ExtensionTransport
| Property | Value |
|---|---|
| sources | packages/puppeteer-core/src/cdp/ExtensionTransport.ts
|
| domains | CDP, Transport, Chrome Extensions |
| last_updated | 2026-02-12 00:00 GMT |
Overview
Description
The ExtensionTransport class is an experimental ConnectionTransport implementation that enables Puppeteer to communicate with a Chrome tab through the chrome.debugger extension API. This is designed for use when Puppeteer runs inside a Chrome extension, where direct WebSocket connections to the browser's DevTools protocol are not available.
Since the chrome.debugger API provides a restricted subset of CDP, the transport synthetically implements several commands that are normally handled by the browser:
- Browser.getVersion -- Returns hardcoded Chrome protocol version info.
- Target.getBrowserContexts -- Returns an empty browser contexts list.
- Target.setDiscoverTargets -- Simulates target discovery by dispatching synthetic
Target.targetCreatedevents for a tab target and a page target. - Target.setAutoAttach -- Simulates auto-attach behavior by dispatching synthetic
Target.attachedToTargetevents with fixed session IDs (tabTargetSessionIdandpageTargetSessionId).
For all other CDP commands, it forwards them to the actual chrome.debugger.sendCommand API, mapping the synthetic pageTargetSessionId back to the real tab connection.
Usage
This transport is used via the static ExtensionTransport.connectTab(tabId) factory method, which attaches the chrome.debugger to the specified tab using protocol version 1.3 and returns a transport instance. It is then passed to Puppeteer's Connection class as the underlying transport layer.
Code Reference
Source Location
packages/puppeteer-core/src/cdp/ExtensionTransport.ts (197 lines)
Signature
export class ExtensionTransport implements ConnectionTransport {
static async connectTab(tabId: number): Promise<ExtensionTransport>;
onmessage?: (message: string) => void;
onclose?: () => void;
constructor(tabId: number);
send(message: string): void;
close(): void;
}
Import
import { ExtensionTransport } from '../cdp/ExtensionTransport.js';
I/O Contract
ExtensionTransport.connectTab
| Direction | Name | Type | Description |
|---|---|---|---|
| Input | tabId | number |
Chrome tab ID to attach the debugger to |
| Output | result | Promise<ExtensionTransport> |
A transport instance connected to the tab |
send
| Direction | Name | Type | Description |
|---|---|---|---|
| Input | message | string |
JSON-encoded CDP message containing method, params, id, and optionally sessionId
|
| Output | (async dispatch) | void |
Responses are dispatched asynchronously via onmessage
|
close
| Direction | Name | Type | Description |
|---|---|---|---|
| Output | (void) | void |
Removes the debugger event listener and detaches from the tab |
Usage Examples
import { ExtensionTransport } from 'puppeteer-core/lib/cdp/ExtensionTransport.js';
import puppeteer from 'puppeteer-core/lib/puppeteer/puppeteer-core.js';
// Inside a Chrome extension's service worker or background script
const tab = await chrome.tabs.create({ url: 'https://example.com' });
// Connect Puppeteer to the tab via the extension debugger API
const transport = await ExtensionTransport.connectTab(tab.id);
const browser = await puppeteer.connect({ transport });
// Use Puppeteer as normal
const [page] = await browser.pages();
const title = await page.title();
console.log('Page title:', title);
// Clean up
await browser.disconnect();