Implementation:Puppeteer Puppeteer Cdp TargetManager
| Property | Value |
|---|---|
| sources | packages/puppeteer-core/src/cdp/TargetManager.ts |
| domains | Target Discovery, Auto-Attach, CDP |
| last_updated | 2026-02-12 00:00 GMT |
Overview
Description
The TargetManager class encapsulates all interactions with CDP targets and is responsible for coordinating target discovery, auto-attachment, and lifecycle management. It is the single source of truth for target tracking within a browser instance, and all other Puppeteer code relies on TargetManager events rather than subscribing directly to CDP Target.* events.
Key responsibilities include:
- Target discovery -- Subscribing to
Target.targetCreated,Target.targetDestroyed, andTarget.targetInfoChangedCDP events viaTarget.setDiscoverTargets. - Auto-attachment -- Using CDP's auto-attach mechanism (
Target.setAutoAttachwithwaitForDebuggerOnStart: true) to intercept new targets while they are paused, allowing Puppeteer to configure listeners before the target resumes. - Target factory -- Using a
TargetFactoryfunction (provided byCdpBrowser) to create the appropriate target type (PageTarget, WorkerTarget, etc.) based on target info. - Target filtering -- Supporting a
TargetFilterCallbackto selectively ignore targets. Filtered-out targets are silently detached. - Session management -- Setting up attachment/detachment listeners on each CDP session, routing
Target.attachedToTargetandTarget.detachedFromTargetevents, and managing the relationship between sessions and targets. - Parent-child tracking -- Maintaining parent-child relationships between targets for hierarchical target trees.
- Service worker handling -- Silently detaching from auto-attached service workers to prevent blocking their destruction, while still reporting them as available targets.
- Initialization coordination -- Tracking tab targets discovered during initial auto-attach and resolving initialization only after all tab targets have had their sub-targets attached. This prevents flakiness in
puppeteer.connect()andpuppeteer.launch(). - Page activation detection -- Detecting when a prerendered page becomes the primary page (subtype changes from non-empty to empty) and emitting
CDPSessionEvent.Swapped.
The TargetManager maintains three key maps:
#discoveredTargetsByTargetId-- All targets reported byTarget.targetCreated.#attachedTargetsByTargetId-- Targets that have been created and attached at least once.#attachedTargetsBySessionId-- Mapping from session IDs to their targets.
Usage
The TargetManager is created internally by CdpBrowser and is not directly exposed to users. Users interact with targets through browser.targets(), browser.waitForTarget(), and target-related browser events.
Code Reference
Source Location: packages/puppeteer-core/src/cdp/TargetManager.ts (442 lines)
Signature:
export type TargetFactory = (
targetInfo: Protocol.Target.TargetInfo,
session?: CdpCDPSession,
parentSession?: CdpCDPSession,
) => CdpTarget;
export class TargetManager extends EventEmitter<TargetManagerEvents> {
constructor(
connection: Connection,
targetFactory: TargetFactory,
targetFilterCallback?: TargetFilterCallback,
waitForInitiallyDiscoveredTargets?: boolean,
);
async initialize(): Promise<void>;
dispose(): void;
getAvailableTargets(): ReadonlyMap<string, CdpTarget>;
getChildTargets(target: CdpTarget): ReadonlySet<CdpTarget>;
}
Import:
import { TargetManager, type TargetFactory } from 'puppeteer-core/lib/cdp/TargetManager.js';
I/O Contract
Inputs:
| Parameter | Type | Required | Description |
|---|---|---|---|
| connection | Connection |
Yes | The CDP connection for sending target discovery and auto-attach commands |
| targetFactory | TargetFactory |
Yes | Factory function that creates CdpTarget instances from target info
|
| targetFilterCallback | TargetFilterCallback |
No | Optional callback to filter which targets are tracked |
| waitForInitiallyDiscoveredTargets | boolean |
No | Whether to wait for all initially discovered tab targets to have sub-targets attached before resolving initialization (default: true) |
Outputs:
| Output | Type | Description |
|---|---|---|
| getAvailableTargets() | ReadonlyMap<string, CdpTarget> |
All currently attached targets indexed by target ID |
| getChildTargets() | ReadonlySet<CdpTarget> |
Child targets of a given target |
| TargetManagerEvent.TargetAvailable | CdpTarget |
Emitted when a new target is available (created and attached) |
| TargetManagerEvent.TargetGone | CdpTarget |
Emitted when a target is destroyed or detached |
| TargetManagerEvent.TargetChanged | {target, wasInitialized, previousURL} |
Emitted when a target's URL changes |
| TargetManagerEvent.TargetDiscovered | Protocol.Target.TargetInfo |
Emitted when a target is discovered (before attachment) |
Usage Examples
// TargetManager is used internally by CdpBrowser.
// Users interact through the Browser API:
// List all targets
const targets = browser.targets();
console.log(`Found ${targets.length} targets`);
// Wait for a target to appear
const target = await browser.waitForTarget(
t => t.url() === 'https://example.com/popup',
{ timeout: 5000 },
);
// Listen for target events (emitted by Browser, sourced from TargetManager)
browser.on('targetcreated', target => {
console.log('New target:', target.type(), target.url());
});
browser.on('targetdestroyed', target => {
console.log('Target destroyed:', target.url());
});
browser.on('targetchanged', target => {
console.log('Target changed:', target.url());
});
// Filter targets during browser creation
const browser = await puppeteer.launch({
targetFilter: target => target.type() !== 'other',
});