puppeteer
semver
>=1.0.0postconditions16functions16last verified2026-04-04coverage score100%Postconditions — what we check
- launch · launch-rejects-on-errorerrorWhenbrowser launch fails (timeout, protocol error, missing Chrome)Throws
Promise rejection with TimeoutError, ProtocolError, or ErrorRequired handlingCaller MUST use try-catch to handle Promise rejections from puppeteer.launch(). Common failures: timeout (default 30s), protocol errors in Docker/containers, missing Chrome binary. Browser instance MUST be closed in finally block to prevent zombie processes. Use pattern: let browser; try { browser = await puppeteer.launch(); } catch (error) { /* handle */ } finally { if (browser) await browser.close(); }costmediumin prodimmediate exceptionusers seeservice unavailablevisibilityvisibleSources[1] - goto · goto-rejects-on-timeouterrorWhennavigation timeout (default 30s) or network errorThrows
Promise rejection with TimeoutErrorRequired handlingCaller MUST use try-catch to handle Promise rejections from page.goto(). This is the #1 cause of production failures. Timeouts occur with slow networks, Cloudflare protection, heavy JavaScript pages. CRITICAL: In headless shell mode, HTTP 404/500 do NOT throw - must check response.ok(). Use pattern: const response = await page.goto(url, { timeout: 60000 }); if (!response || !response.ok()) throw new Error('Navigation failed');costmediumin prodimmediate exceptionusers seeservice unavailablevisibilityvisibleSources[2] - newPage · newpage-rejects-on-errorerrorWhenpage creation timeout or protocol errorThrows
Promise rejection with ProtocolError (Target.createTarget timed out)Required handlingCaller MUST use try-catch to handle Promise rejections from browser.newPage(). Common in Docker/containers with rapid page creation cycles. Increase protocolTimeout in launch options for containers. Use pattern: try { const page = await browser.newPage(); } catch (error) { /* handle */ }costmediumin prodimmediate exceptionusers seeservice unavailablevisibilityvisibleSources[3] - close · browser-close-must-runwarningWhenbrowser instance exists after operationsThrows
May throw Error if browser already closed or connection lostRequired handlingBrowser.close() MUST be called in finally block to prevent zombie Chrome processes. Each zombie process consumes 80-90MB. Accumulation causes memory exhaustion and server crashes. Close can itself throw errors - wrap in try-catch within finally to avoid masking original errors. Use pattern: finally { if (browser) { try { await browser.close(); } catch (e) {} } }costmediumin prodimmediate exceptionusers seeservice unavailablevisibilityvisibleSources[4] - waitForSelector · waitforselector-rejects-on-timeoutwarningWhenelement not found within timeout (default 30s)Throws
Promise rejection with TimeoutErrorRequired handlingCaller MUST use try-catch to handle TimeoutError from page.waitForSelector(). Timeouts common when element never appears or takes longer than expected. Consider increasing timeout for slow-loading pages. Use pattern: try { await page.waitForSelector('selector', { timeout: 10000 }); } catch (error) { /* handle */ }costmediumin prodimmediate exceptionusers seeservice unavailablevisibilityvisibleSources[5] - click · click-rejects-on-errorwarningWhenelement not found or not clickableThrows
Promise rejection with ErrorRequired handlingCaller MUST use try-catch to handle errors from page.click(). Common failures: selector not found, element not clickable, element moved. CRITICAL: When click triggers navigation, use Promise.all([page.waitForNavigation(), page.click()]) to avoid race conditions. Use pattern: try { await page.click('button'); } catch (error) { /* handle */ }costmediumin prodimmediate exceptionusers seeservice unavailablevisibilityvisibleSources[6] - evaluate · evaluate-execution-errorerrorWhenJavaScript execution fails in page context (page closed, navigation during eval, unserializable return)Throws
TargetCloseError if page navigated/closed during evaluation, Error if function throws in browser contextRequired handlingCaller MUST wrap page.evaluate() in try-catch. Common failures: (1) Page navigated away during evaluation — throws TargetCloseError. (2) Function throws in browser context — error propagated to Node.js. (3) Return value not serializable — throws Error. (4) Execution context destroyed (SPA navigation) — throws ProtocolError. In scraping/automation pipelines, evaluate() failures are the #1 cause of silent data loss — the scrape returns undefined instead of crashing.costmediumin prodimmediate exceptionusers seedegraded performancevisibilitysilentSources[7] - screenshot · screenshot-protocol-errorerrorWhenScreenshot capture fails (page closed, protocol error, invalid options)Throws
TargetCloseError if page closed during capture, Error on invalid crop/options, ProtocolError on CDP failureRequired handlingCaller MUST wrap page.screenshot() in try-catch. Failures include: (1) Page navigated/closed during capture — TargetCloseError. (2) Invalid crop dimensions (negative, exceeds viewport) — throws Error. (3) fullPage screenshot of infinite-scroll pages — may cause OOM. (4) ProtocolError when page is mid-navigation. CRITICAL: In image generation services, unhandled screenshot errors return empty/corrupt images to users without alerting.costmediumin prodimmediate exceptionusers seedegraded performancevisibilitysilentSources[8] - pdf · pdf-headless-only-errorerrorWhenpdf() called in headed (non-headless) browser modeThrows
Error indicating PDF generation only works in headless modeRequired handlingCaller MUST wrap page.pdf() in try-catch. Key failure modes: (1) Called in headed mode — throws immediately. (2) Page navigated/closed during generation — TargetCloseError. (3) ProtocolError on CDP failure during rendering. CRITICAL: PDF generation services that don't catch errors return empty PDFs or crash the worker process. Always verify the returned buffer has non-zero length before serving to users.costhighin prodimmediate exceptionusers seedegraded performancevisibilitysilentSources[9] - setContent · setcontent-timeout-errorerrorWhenPage content loading exceeds timeout (default 30s)Throws
TimeoutError when waitUntil condition not met within timeoutRequired handlingCaller MUST wrap page.setContent() in try-catch. setContent() waits for the page to reach the specified load state (default: 'load'). Complex HTML with external resources can timeout. In HTML-to-PDF pipelines, timeout on setContent silently aborts the generation. Set explicit timeout and handle: page.setContent(html, { timeout: 60000 }).costmediumin prodimmediate exceptionusers seedegraded performancevisibilitysilentSources[10] - waitForNavigation · waitfornavigation-timeout-errorerrorWhenNavigation does not complete within timeout (default 30s)Throws
TimeoutError when navigation exceeds timeout, TargetCloseError if page closes during waitRequired handlingCaller MUST wrap page.waitForNavigation() in try-catch. This is the most common source of flaky Puppeteer tests and production failures. Key patterns: (1) Must be called BEFORE the action that triggers navigation — use Promise.all([page.waitForNavigation(), page.click()]). (2) SPA route changes may resolve with null response. (3) Multiple rapid navigations cause race conditions. (4) Timeout in CI/Docker environments due to slow rendering.costmediumin prodimmediate exceptionusers seeservice unavailablevisibilityvisibleSources[11] - waitForNetworkIdle · waitfornetworkidle-timeout-errorwarningWhenNetwork does not become idle within timeoutThrows
TimeoutError when network remains active past timeout, TargetCloseError if page closesRequired handlingCaller MUST wrap page.waitForNetworkIdle() in try-catch. Common failures: (1) Pages with persistent WebSocket/SSE connections never reach idle — timeout guaranteed. (2) Analytics/tracking scripts continually fire requests. (3) Long-polling APIs keep network busy. Always set an explicit timeout and handle TimeoutError gracefully rather than treating it as a hard failure.costmediumin prodimmediate exceptionusers seeservice unavailablevisibilityvisibleSources[12] - waitForFunction · waitforfunction-timeout-errorwarningWhenFunction does not return truthy value within timeoutThrows
TimeoutError when condition not met within timeout, TargetCloseError if page closes during waitRequired handlingCaller MUST wrap page.waitForFunction() in try-catch. Timeout occurs when the evaluated function never returns truthy. Common in scraping when waiting for dynamic content that may not appear. The function re-evaluates on every animation frame or on DOM mutation (depending on polling option), so infinite loops in the function will not throw — they just timeout silently.costmediumin prodimmediate exceptionusers seeservice unavailablevisibilityvisibleSources[13] - type · type-element-not-foundwarningWhenTarget element selector not found on pageThrows
Error when no element matches the provided selectorRequired handlingCaller MUST wrap page.type() in try-catch. The method throws if the selector does not match any element. Common in form automation when pages load dynamically — always waitForSelector() before type(). Also throws TargetCloseError if page navigates during typing (e.g., auto-submit forms).costlowin prodimmediate exceptionusers seeservice unavailablevisibilityvisibleSources[14] - $eval · eval-element-not-founderrorWhenNo element matches the provided selectorThrows
Error indicating no element found for selectorRequired handlingCaller MUST wrap page.$eval() in try-catch. Unlike page.$() which returns null when no element is found, $eval() THROWS an error. This is a critical distinction — code that works with $() will crash with $eval() on missing elements. Use page.$() first to check existence, or wrap in try-catch. Common in scraping when page structure varies across different pages.costmediumin prodimmediate exceptionusers seedegraded performancevisibilitysilentSources[15] - connect · connect-websocket-errorerrorWhenWebSocket connection to browser fails (wrong URL, browser not running, network error)Throws
Error on WebSocket connection failure, TimeoutError if connection times outRequired handlingCaller MUST wrap puppeteer.connect() in try-catch. Connection failures common with: (1) Browser process crashed/exited before connect. (2) Wrong WebSocket URL (port changed, container restarted). (3) Network partition between Puppeteer and remote browser. CRITICAL: In browser pool architectures, connect() failures without error handling cause the entire worker to crash instead of gracefully acquiring a new browser.costmediumin prodimmediate exceptionusers seeservice unavailablevisibilityvisibleSources[16]
Sources
Every postcondition cites at least one of these. Numbered to match the footnotes above.
- [1]pptr.dev/api/puppeteer.puppeteernode.launchhttps://pptr.dev/api/puppeteer.puppeteernode.launch
- [2]pptr.dev/api/puppeteer.page.gotohttps://pptr.dev/api/puppeteer.page.goto
- [3]pptr.dev/api/puppeteer.browser.newpagehttps://pptr.dev/api/puppeteer.browser.newpage
- [4]pptr.dev/api/puppeteer.browser.closehttps://pptr.dev/api/puppeteer.browser.close
- [5]pptr.dev/api/puppeteer.page.waitforselectorhttps://pptr.dev/api/puppeteer.page.waitforselector
- [6]pptr.dev/api/puppeteer.page.clickhttps://pptr.dev/api/puppeteer.page.click
- [7]pptr.dev/api/puppeteer.page.evaluatehttps://pptr.dev/api/puppeteer.page.evaluate
- [8]pptr.dev/api/puppeteer.page.screenshothttps://pptr.dev/api/puppeteer.page.screenshot
- [9]pptr.dev/api/puppeteer.page.pdfhttps://pptr.dev/api/puppeteer.page.pdf
- [10]pptr.dev/api/puppeteer.page.setcontenthttps://pptr.dev/api/puppeteer.page.setcontent
- [11]pptr.dev/api/puppeteer.page.waitfornavigationhttps://pptr.dev/api/puppeteer.page.waitfornavigation
- [12]pptr.dev/api/puppeteer.page.waitfornetworkidlehttps://pptr.dev/api/puppeteer.page.waitfornetworkidle
- [13]pptr.dev/api/puppeteer.page.waitforfunctionhttps://pptr.dev/api/puppeteer.page.waitforfunction
- [14]pptr.dev/api/puppeteer.page.typehttps://pptr.dev/api/puppeteer.page.type
- [15]pptr.dev/api/puppeteer.page._evalhttps://pptr.dev/api/puppeteer.page._eval
- [16]pptr.dev/api/puppeteer.puppeteer.connecthttps://pptr.dev/api/puppeteer.puppeteer.connect
Need a different package?
Request a profile