Detect a failed screenshot request by observing the whole lifecycle, not by treating every timeout as proof of failure. In Playwright, log requestfailed events for requests that never receive an HTTP response, inspect response.status() for HTTP errors such as 404 or 503, and capture screenshot promise or assertion failures separately. Preserve the complete error and stack, the operation and stage, and tool and browser versions. Before retrying an action with side effects, verify the application state.
Three different failures hide behind “the screenshot failed”
A browser automation job can fail before a page responds, after the server returns an error status, or while the page is being captured or compared. These are different signals with different fixes.
| Failure layer | What happened | Evidence to collect |
|---|---|---|
| Transport or network | No HTTP response was obtained. Playwright emits requestfailed. |
Request URL (redacted), request.failure().errorText, full error and stack. |
| HTTP response | The server answered with a status such as 404 or 503. This is still a completed HTTP exchange. | response.status(), response URL, redirect chain and relevant headers. |
| Capture or assertion | The screenshot promise rejected, or a visual assertion timed out or did not match. | Screenshot options, assertion output, viewport, browser version and page state. |
| Wait timeout | The expected event, selector or response did not arrive within the configured period. | Wait condition, timeout value, stage and resulting application state. |
Playwright explicitly distinguishes HTTP errors from network failures: a 404 or 503 emits response and then request-finished events, not requestfailed. A listener that watches only requestfailed therefore misses many failed page loads.
Build a diagnostic record before changing code
Keep the entire exception and stack trace. Record the exact operation (navigation, click, response wait, screenshot, or visual assertion), the stage at which execution stopped, the Playwright or Puppeteer version, the browser and revision, operating system, URL host and status, timeout, viewport, and whether request interception was enabled.
#1 Best Overall
- CRISP CLARITY: This 23.8″ Philips V line monitor delivers crisp Full HD 1920x1080 visuals. Enjoy movies, shows and videos with remarkable detail
- INCREDIBLE CONTRAST: The VA panel produces brighter whites and deeper blacks. You get true-to-life images and more gradients with 16.7 million colors
- THE PERFECT VIEW: The 178/178 degree extra wide viewing angle prevents the shifting of colors when viewed from an offset angle, so you always get consistent colors
- WORK SEAMLESSLY: This sleek monitor is virtually bezel-free on three sides, so the screen looks even bigger for the viewer. This minimalistic design also allows for seamless multi-monitor setups that enhance your workflow and boost productivity
- A BETTER READING EXPERIENCE: For busy office workers, EasyRead mode provides a more paper-like experience for when viewing lengthy documents
URLs can contain credentials, bearer tokens, session identifiers or private query values. Store a redacted URL and never log cookies, authorization headers, page contents or secrets. Keep the unredacted values only in a controlled system when they are genuinely required for diagnosis.
Do not catch an exception and return an empty image or empty result unless that is an explicit, observable failure result. Swallowing the error makes a broken job look successful to its caller. If the caller must know that the operation failed, rethrow the original exception after adding safe context.
A compact diagnostic helper
function redactUrl(raw) {
const u = new URL(raw);
for (const key of ['token', 'access_token', 'code', 'key']) {
if (u.searchParams.has(key)) u.searchParams.set(key, '[redacted]');
}
return u.toString();
}
function describeError(error, operation, versions) {
return {
operation,
message: error?.message,
stack: error?.stack,
versions,
capturedAt: new Date().toISOString()
};
}
Observe Playwright network events correctly
Attach listeners before navigation or the click that triggers the request. Log failed transport requests and independently inspect statuses for the request that matters.
import { chromium } from 'playwright';
const browser = await chromium.launch();
const page = await browser.newPage();
page.on('requestfailed', request => {
const failure = request.failure();
console.error('requestfailed', {
url: redactUrl(request.url()),
method: request.method(),
errorText: failure?.errorText
});
});
page.on('response', response => {
if (response.status() >= 400) {
console.error('HTTP error response', {
url: redactUrl(response.url()),
status: response.status(),
statusText: response.statusText()
});
}
});
try {
await page.goto('https://example.com', { waitUntil: 'domcontentloaded' });
await page.screenshot({ path: 'page.png', fullPage: true });
} catch (error) {
console.error(describeError(error, 'navigate-and-screenshot', {
playwright: process.env.npm_package_version,
browser: await browser.version()
}));
throw error;
} finally {
await browser.close();
}
A failed request can be a DNS problem, connection refusal, certificate failure, blocked resource, proxy issue or browser-level net::ERR_... condition. The failure text narrows the layer, but it does not by itself identify the permanent fix.
Rank #2
- CRISP CLARITY: This 22 inch class (21.5″ viewable) Philips V line monitor delivers crisp Full HD 1920x1080 visuals. Enjoy movies, shows and videos with remarkable detail
- 100HZ FAST REFRESH RATE: 100Hz brings your favorite movies and video games to life. Stream, binge, and play effortlessly
- SMOOTH ACTION WITH ADAPTIVE-SYNC: Adaptive-Sync technology ensures fluid action sequences and rapid response time. Every frame will be rendered smoothly with crystal clarity and without stutter
- INCREDIBLE CONTRAST: The VA panel produces brighter whites and deeper blacks. You get true-to-life images and more gradients with 16.7 million colors
- THE PERFECT VIEW: The 178/178 degree extra wide viewing angle prevents the shifting of colors when viewed from an offset angle, so you always get consistent colors
Wait for the intended response, not an arbitrary request
Register a response wait before triggering the action. Match the precise URL or use a predicate that checks method, path and status. Set a timeout appropriate to the operation and verify the installed library version’s defaults.
const responsePromise = page.waitForResponse(response =>
response.url().includes('/api/render') &&
response.request().method() === 'POST'
);
await page.getByRole('button', { name: 'Render' }).click();
const response = await responsePromise;
if (!response.ok()) {
throw new Error(`Render API returned ${response.status()} ${response.statusText()}`);
}
await page.screenshot({ path: 'rendered.png' });
Puppeteer’s documented response-wait API has a 30-second default in the referenced API documentation; you can change the default or pass zero to disable the timeout. Confirm the behavior against your installed release rather than assuming every version uses the same value.
A timeout means the expected observation did not arrive in time. It does not prove that an action or server-side effect did not happen. A form submission may have succeeded while its response was lost. For payments, emails, account creation, deletion and other side-effecting operations, query application state or use the service’s idempotency mechanism before retrying.
Replace fixed sleeps with meaningful signals
Use a matching response, a visible result, a URL change, or a selector becoming ready. Playwright describes page.waitForTimeout() as discouraged for production tests because timer-based synchronization is inherently flaky; its guidance is to wait for a real signal instead.
Rank #3
- Clear visuals. Fluid motion: A 144Hz refresh rate and 1ms MPRT deliver smooth, tear‑free motion across work, gaming, and streaming for clearer, more fluid viewing.
- Eye comfort: TÜV Rheinland 3‑star* certification reduces harmful blue light while preserving stunning color quality without compromise. *TÜV Rheinland 3-star eye comfort certification.
- Wide viewing angle: Get consistent views across a wide 178° /178° viewing angle.
- In-Plane Switching (IPS): See excellent color accuracy and consistency across wide viewing angles with In-plane Switching (IPS) technology.
- Ultra-thin bezels: Maximize your viewing experience with thin bezels.
await page.getByRole('button', { name: 'Load report' }).click();
await page.getByTestId('report-ready').waitFor({ state: 'visible' });
await page.screenshot({ path: 'report.png' });
Use a short delay only when debugging a live page, never as the primary production condition. If the page performs animations or lazy loading, wait for the selector or network-idle condition that represents completion, then capture.
Diagnose by stage
Browser startup
Check that the browser revision is installed, the executable path exists, the process can start in the deployment environment, and sandbox or container permissions are correct. A screenshot call cannot succeed if launch failed or the browser exited immediately.
Navigation and redirects
Log the final URL and redirect chain. Check DNS, TLS, proxy settings, authentication and redirect loops. An HTTP 404 or 503 is an application response: handle its status explicitly instead of waiting for requestfailed.
Waiting for content
Confirm that the selector or response predicate still matches the current application. Increase a timeout only after measuring realistic latency; an indefinitely large timeout hides outages. Check whether content is inside an iframe and whether the frame changed after navigation.
The Tool Desk
Outbyte PC Repair FREERepair Windows errors before they cause bigger problemsFix Now →Outbyte Driver Updater FREEScan for outdated or missing drivers - takes under a minuteDriver Scan →Rank #4
- CURVED FOR ENHANCED ENGAGEMENT: An immersive viewing experience with a curved monitor that wraps more closely around your field of vision; It creates a wider view, enhancing depth perception and minimizing peripheral distraction
- SMOOTH PERFORMANCE FOR SEAMLESS CONTENT: Stay in the action when playing games, watching videos, or working on creative projects; The 100Hz refresh rate reduces lag and motion blur so you don't miss a thing in fast-paced moments¹
- MORE GAMING POWER: Gain the edge with optimizable game settings; Color and image contrast can be adjusted to see scenes more vividly and spot enemies hiding in the dark; Game Mode adjusts any game to fill the screen so you can view every detail²
- KEEP IT EASY ON THE EYES: Care for your eyes and stay comfortable, even during long sessions; Advanced eye comfort technology certified by TÜV reduces eye strain by minimizing blue light and reducing irritating screen flicker²
- INCREASED VERSATILITY: Connect to more; Plug devices straight into your monitor for increased flexibility, making your computing environment even more convenient
Interaction and handles
After navigation or a frame replacement, reacquire locators or element handles. A handle obtained from the old document can become detached. Use locators where possible so the framework resolves the current element.
Request interception
If interception is enabled, every intercepted request must be continued, fulfilled or aborted exactly once. A request left unresolved can make navigation and screenshot waits appear to hang.
Keep screenshot capture evidence separate
Puppeteer’s Page.screenshot() returns image data through a promise and accepts screenshot options. Treat rejection of that promise as a capture-layer error, not as proof that an earlier API request failed.
Playwright’s toHaveScreenshot() is a visual assertion. It waits for two consecutive screenshots to stabilize before comparing the last image with the expected snapshot. A mismatch or assertion timeout identifies visual instability or regression; it does not tell you whether a network request received an HTTP response. Log network events and response statuses alongside the assertion.
Best Value
- 【INTEGRATED SPEAKERS】Whether you're at work or in the midst of an intense gaming session, our built-in speakers provide rich and seamless audio, all while keeping your desk clutter-free.
- 【EASY ON THE EYES】 Protect your eyes and enhance your comfort with Blue-Light Shift technology. This feature reduces harmful blue light emissions from your screen, helping to alleviate eye strain during long hours of use and promoting healthier viewing habits.
- 【WIDEN YOUR PERSPECTIVE】Our sleek minimal bezel design ensures undivided attention. The nearly bezel-free display seamlessly connects in a dual monitor arrangement, delivering an unobstructed view that lets you focus on more at once, completely distraction-free.
import { test, expect } from '@playwright/test';
test('dashboard is stable', async ({ page }) => {
await page.goto('https://example.com/dashboard');
const api = await page.waitForResponse(r =>
r.url().includes('/api/dashboard') && r.status() === 200
);
if (!api.ok()) throw new Error(`Dashboard API: ${api.status()}`);
await expect(page).toHaveScreenshot('dashboard.png');
});
Independent reader supportYour contribution helps us test, update, and keep practical guides available for everyone.Common symptoms and targeted fixes
| Symptom | Likely cause | Fix |
|---|---|---|
requestfailed with a network error |
DNS, TLS, proxy, blocked connection or aborted request. | Test the URL from the same host, inspect failure text, proxy and certificates, then retry only if the operation is safe. |
404 or 503 but no requestfailed |
The server returned an HTTP error response. | Check status, final URL, deployment health and route; handle non-2xx responses explicitly. |
waitForResponse timeout |
Wrong predicate, action did not fire, request was intercepted, or service exceeded the timeout. | Install the wait before the action, log all relevant responses, verify method/path, and inspect interception handlers. |
| Selector timeout | Wrong locator, frame, visibility state or page never reached the expected state. | Capture URL and DOM state, select the correct frame, and wait for a meaningful readiness signal. |
| Screenshot assertion mismatch | Layout, fonts, animations, data or viewport changed. | Stabilize data and fonts, disable animation where appropriate, use a fixed viewport, and inspect the diff. |
| Empty success result | Application caught and swallowed an exception. | Rethrow or return a structured failure so monitoring can observe it. |
Reduce a failure to a safe reproducer
- Keep the same browser launch arguments, URL host and operation.
- Remove unrelated clicks, waits and requests until the smallest failing sequence remains.
- Change one relevant variable at a time: timeout, selector, proxy, viewport or interception rule.
- Compare a successful run and failed run using the same redacted diagnostics.
- Restore the full workflow only after the minimal case is reliable.
Or skip the browser setup
ScreenshotNeo provides a one-request screenshot API and MCP server. It accepts consent banners before capture and removes more than 60 known consent platforms, newsletter popups and chat widgets; each cleanup step can be disabled. Bot checks, blank pages, timeouts, failed loads and cache hits are not billed, and response headers identify the page verdict and billing result. Its MCP tools—take_screenshot, get_page_info and capture_pdf—let Claude, Cursor and other MCP clients capture pages without you wiring browser events.
See the ScreenshotNeo documentation for parameters. This cURL call saves a WebP image:
curl -G "https://api.screenshotneo.com/v1/shot" -d access_key=YOUR_API_KEY --data-urlencode url=https://stripe.com -o shot.webp
Python:
import requests
r = requests.get("https://api.screenshotneo.com/v1/shot", params={"access_key": "YOUR_API_KEY", "url": "https://stripe.com"}, timeout=90)
open("shot.webp", "wb").write(r.content)
Node.js:
const q = new URLSearchParams({ access_key: 'YOUR_API_KEY', url: 'https://stripe.com' });
const res = await fetch(`https://api.screenshotneo.com/v1/shot?${q}`);
Every plan includes the capture options, including full-page lazy-image loading, CSS-selector elements, device and retina settings, PDFs, custom CSS and JavaScript, clicks, waits, blocking, headers, cookies, user agents, authorization, timezone, geolocation, transparency, resizing, TTL caching, signed links, async webhooks, bulk capture of up to 100 URLs per call, usage data and an OpenAPI specification. Pricing starts with 1,000 screenshots per month free with no card; paid plans are $5 for 3,000, $15 for 15,000, $39 for 60,000, $99 for 250,000 and $249 for 1,000,000. Yearly billing gives two months free. Sign up free to get the 1,000 monthly screenshots without a card.
Frequently Asked Questions
Should a 404 make a screenshot job fail?
Decide based on your contract. If the target must exist, treat a non-2xx status as a structured failure even though the browser received an HTTP response.
What’s actually slowing this PC down?
Pick the symptom - the matching free tool is one click away.
How much timeout should I add?
Set it from observed latency for the specific environment and operation. A larger value cannot correct a wrong selector, stalled interception handler or unavailable service.
Can I retry every timed-out screenshot?
Only when the operation is read-only or you have verified idempotency. For side effects, inspect state first because the server may have completed the action.
Quick Recap
Product prices and availability are accurate as of the date/time indicated and are subject to change. Any price and availability information displayed on Amazon at the time of purchase will apply.

