Heuristic:Puppeteer Puppeteer Timeout Hierarchy
| Knowledge Sources | |
|---|---|
| Domains | Browser_Automation, Debugging, Configuration |
| Last Updated | 2026-02-11 23:30 GMT |
Overview
Puppeteer uses a three-tier timeout hierarchy: navigation timeout > default timeout > 30-second fallback, plus a separate protocol timeout for low-level CDP/BiDi commands.
Description
Puppeteer maintains two independent timeout dimensions. The first is the operation timeout hierarchy: navigation-specific timeout takes priority over the general default timeout, which falls back to a hardcoded 30-second constant. The second is the protocol timeout, which controls how long Puppeteer waits for CDP or BiDi command responses and is configured separately via the `protocolTimeout` launch option.
Usage
Apply this heuristic when debugging timeout errors in Puppeteer. The error message indicates which timeout layer triggered:
- "Navigation timeout of X ms exceeded" — Navigation timeout
- "Waiting for selector X failed: timeout X ms exceeded" — Default timeout
- "timed out. Increase the 'protocolTimeout' setting" — Protocol-level timeout
The Insight (Rule of Thumb)
- Action: Set timeouts at the appropriate level. Use `page.setDefaultNavigationTimeout()` for navigation, `page.setDefaultTimeout()` for general operations, and `protocolTimeout` in launch options for protocol commands.
- Value: Default is 30,000ms (30 seconds) for all operation timeouts.
- Trade-off: Higher timeouts mask performance issues; lower timeouts cause flaky tests. Protocol timeout is separate and must be increased independently.
- Priority Chain:
- `setDefaultNavigationTimeout(ms)` — Highest priority for navigation operations
- `setDefaultTimeout(ms)` — Fallback for all operations including navigation
- `30000` (30s) — Hardcoded constant when nothing is set
Reasoning
The three-tier hierarchy allows fine-grained control over timeout behavior. Navigation operations (page loads, redirects) often need longer timeouts than DOM queries or evaluations. The protocol timeout addresses a different concern: how long to wait for the browser process to respond to individual commands, which can be affected by browser load or complexity of the operation.
From `packages/puppeteer-core/src/common/TimeoutSettings.ts:7-45`:
const DEFAULT_TIMEOUT = 30000;
export class TimeoutSettings {
#defaultTimeout: number | null;
#defaultNavigationTimeout: number | null;
navigationTimeout(): number {
if (this.#defaultNavigationTimeout !== null) {
return this.#defaultNavigationTimeout; // Priority 1
}
if (this.#defaultTimeout !== null) {
return this.#defaultTimeout; // Priority 2
}
return DEFAULT_TIMEOUT; // Priority 3: 30s
}
timeout(): number {
if (this.#defaultTimeout !== null) {
return this.#defaultTimeout;
}
return DEFAULT_TIMEOUT;
}
}
Protocol timeout error from `packages/puppeteer-core/src/common/CallbackRegistry.ts:138-145`:
this.#timer = setTimeout(() => {
this.#deferred.reject(
rewriteError(
this.#error,
`${label} timed out. Increase the 'protocolTimeout' setting in launch/connect calls for a higher timeout if needed.`
),
);
}, timeout);