Crashes, No Sound, or Screen Glitches?
Random freezes, missing sound and display glitches usually trace back to one bad driver. Find and replace yours safely.Free scan · under a minuteWindows Errors? Fix Them Before They Spread
Repair common Windows errors and clear accumulated junk for a smoother, more stable PC - no reinstall needed.Free scan · no reinstallUse page.screenshot() when you need an image at a precise step, and configure Playwright Test’s use options when every test (or every failure/retry) should produce artifacts. Record videos either with the test runner’s video mode or with recordVideo on a manually created browser context. Screenshots and videos are disabled by default in Playwright Test.
This guide covers runnable TypeScript examples, artifact paths, video lifecycle, visual-regression baselines, sizing, failure modes, and an API alternative when you do not want to maintain a browser environment.
Capture a screenshot at an exact point
In any Playwright test, call await page.screenshot() after the page has reached the state you want to preserve. The call waits for the screenshot operation to finish before the test continues.
import { test, expect } from '@playwright/test';
test('checkout confirmation', async ({ page }) => {
await page.goto('https://example.com/checkout');
await page.getByRole('button', { name: 'Place order' }).click();
await expect(page.getByRole('heading', { name: 'Thank you' })).toBeVisible();
await page.screenshot({ path: 'artifacts/confirmation.png', fullPage: true });
});
path can be relative to the process working directory. For parallel tests, prefer Playwright Test’s per-test output directory so files cannot overwrite one another:
What’s actually slowing this PC down?
Pick the symptom - the matching free tool is one click away.
#1 Best Overall
import { test } from '@playwright/test';
test('unique artifact path', async ({ page }, testInfo) => {
await page.goto('https://example.com');
const file = testInfo.outputPath('homepage.png');
await page.screenshot({ path: file, fullPage: true });
});
testInfo.outputPath() creates a path under that test’s output folder (normally inside test-results), which is safer for retries and workers.
Useful screenshot options
- Full page:
fullPage: truecaptures the full scrollable document instead of only the viewport. - Element only:
locator.screenshot({ path: 'card.png' })captures a specific element after it is located. - Format: use a
.png,.jpeg, or other supported extension; JPEG supportsquality. - Masking: pass
mask: [locator]to cover dynamic regions in supported Playwright versions. - Animation control:
animations: 'disabled'can make captures more stable.
Wait for the state that matters rather than relying on a fixed sleep. Assertions such as await expect(locator).toBeVisible() provide a condition that explains why the capture occurred.
Configure automatic screenshots in Playwright Test
Set the screenshot option in playwright.config.ts. The official configuration documents screenshots as off by default and supports modes that limit captures to useful debugging runs.
import { defineConfig } from '@playwright/test';
export default defineConfig({
use: {
screenshot: 'only-on-failure'
}
});
Choose the mode that matches your artifact policy:
| Mode | What it does | When to use it |
|---|---|---|
'off' |
No automatic screenshot | Lowest artifact volume; default behavior |
'on' |
Captures every test run | Auditing, demonstrations, or complete visual history |
'only-on-failure' |
Keeps a screenshot for failed tests | General failure debugging |
'on-first-failure' |
Captures on the first failure attempt | Projects where retries should not create duplicate images |
Automatic screenshots are written with the other test artifacts, usually beneath test-results. Your reporter and CI system may package or expose that directory differently, so inspect the reporter output when locating files in a pipeline.
Free tools Windows power users keep installed
One-click scans. No signup required.
Rank #2
Record videos with Playwright Test
Configure video in the same use block. Recording and retention are separate concerns: a mode can record retries while retaining only the runs that help diagnose failures.
import { defineConfig } from '@playwright/test';
export default defineConfig({
use: {
video: 'on-first-retry'
}
});
| Video mode | Behavior | Typical reason |
|---|---|---|
'off' |
No recording | Default or lowest storage use |
'on' |
Record every run | Complete session history |
'retain-on-failure' |
Record runs and retain recordings for failures | Debug failures without keeping successful-run videos |
'on-first-retry' |
Record the first retry | Capture intermittent failures with less storage |
'on-all-retries' |
Record every retry | Compare behavior across repeated attempts |
'retain-on-first-failure' |
Retain the first failing recording | Keep one representative failure artifact |
'retain-on-failure-and-retries' |
Retain failure and retry recordings | Investigate flaky behavior in depth |
The exact set of modes is defined by the current TestOptions API. Video files normally appear in the test output directory alongside traces and screenshots.
Record a video manually with a browser context
When you are using Playwright Library rather than Playwright Test, create a context with recordVideo. The video is finalized only after the page or context closes; do not read its path immediately after navigation.
import { chromium } from 'playwright';
const browser = await chromium.launch();
const context = await browser.newContext({
recordVideo: { dir: 'videos/' },
viewport: { width: 1280, height: 720 }
});
const page = await context.newPage();
await page.goto('https://example.com');
await page.getByRole('link', { name: 'More information' }).click();
await context.close(); // finalizes the recording
await browser.close();
The official video guide documents retrieving a page’s video() object and its path after closure. Closing the context in a finally block is important when a test throws:
Rank #3
const context = await browser.newContext({ recordVideo: { dir: 'videos/' } });
try {
const page = await context.newPage();
await page.goto('https://example.com');
// test actions
} finally {
await context.close();
}
Control video dimensions and annotations
Set an explicit viewport when reproducible dimensions matter. The video guide states that, unless configured otherwise, Playwright scales the viewport to fit within 800×800; when no viewport is set, the documented default video size is 800×450. A large viewport can therefore be downscaled in the recording.
const context = await browser.newContext({
viewport: { width: 1440, height: 900 },
recordVideo: {
dir: 'videos/',
size: { width: 1280, height: 800 }
}
});
Playwright also supports action annotations and an overlay containing test information. The documented default annotation duration is 500 milliseconds. These options and defaults can change between Playwright releases, so verify them in the version of the video documentation that your project uses.
Use screenshots as visual-regression baselines
expect(page).toHaveScreenshot() turns a screenshot into an assertion. On the first run, Playwright creates a reference image; subsequent runs compare the current rendering with that baseline.
import { test, expect } from '@playwright/test';
test('homepage remains visually stable', async ({ page }) => {
await page.goto('https://example.com');
await expect(page).toHaveScreenshot('homepage.png', {
fullPage: true
});
});
PNG is the default snapshot format. Use a filename ending in .webp when you want WebP, which Playwright documents as a lossless alternative. Store baselines in version control and review intentional visual changes as code changes.
Rendering can vary with the host operating system, browser version, browser settings, hardware, power source, and headless mode. Generate and compare baselines in the same environment (for example, the same CI image) to reduce false differences. Avoid putting clocks, random IDs, live advertisements, or other changing content in a baseline; mask or stub those regions instead. See the visual comparisons guide for the current comparison behavior.
Choose the right capture strategy
| Goal | Recommended approach | Trade-off |
|---|---|---|
| One diagnostic image | Explicit page.screenshot() |
You must choose the correct state and path |
| Every test has an image | screenshot: 'on' |
More files and storage |
| Failure evidence | screenshot: 'only-on-failure' |
Successful runs have no automatic image |
| Videos for flaky tests | video: 'on-first-retry' or a retain-on-failure mode |
Only selected attempts are available |
| Full session history | video: 'on' |
Highest CPU, disk, and upload cost |
| Pixel-level regression | toHaveScreenshot() |
Requires stable environments and baseline review |
| Standalone script | recordVideo on newContext() |
You must close the context to finalize video |
Troubleshoot missing or unexpected artifacts
No screenshot appears
- Confirm the test reached the screenshot call; an earlier exception prevents it.
- Check that the configured mode is not
'off'and that a failure-only mode actually saw a failure. - Print or inspect
testInfo.outputPath()and the reporter’s artifact links instead of assuming the current directory. - For a manual screenshot, ensure the destination directory exists or use a path under
testInfo.outputPath().
Video file is missing or zero bytes
- Close the browser context before reading
page.video().path()or uploading the file. - Ensure the context, not just an individual page, was closed in error paths.
- Check that your selected
videomode records the run you are examining; retry-only modes do not record the initial attempt.
Visual test fails only on CI
- Use the same browser version, operating-system image, viewport, color scheme, and headless setting for baseline generation and comparison.
- Wait for fonts, images, and application data before the assertion.
- Mask dynamic content or make it deterministic.
- Review the generated diff and update the baseline only when the design change is intentional.
Full-page capture is clipped or differs between runs
Wait for lazy content to load and ensure the page has reached a stable layout before calling fullPage: true. Fixed headers, animations, and late font swaps can change the final bitmap; disable animations or assert on the relevant content first.
Or skip the browser setup
If you need a clean website image rather than a browser test artifact, ScreenshotNeo provides a GET-based screenshot API and MCP server. It accepts consent banners like a visitor and removes more than 60 known consent platforms, newsletter popups, and chat widgets before capture; each step can be disabled. Bot checks or CAPTCHAs, blank pages, timeouts, failed loads, and cache hits are not billed, and response headers report the page verdict and billing status.
One request returns PNG, JPEG, WebP, or a PDF. The service supports full-page shots with lazy images, CSS-selector element capture, device presets and custom viewports, retina scale, dark mode, custom CSS and JavaScript, clicks, waits, blocked requests, headers, cookies, user agents, authorization, timezone, geolocation, transparent backgrounds, resizing, chosen cache TTLs, signed image links, asynchronous webhooks, bulk capture of up to 100 URLs per call, usage reporting, and an OpenAPI specification. An MCP server exposes take_screenshot, get_page_info, and capture_pdf to Claude, Cursor, and other MCP clients.
Quick wins for a faster PC:
Fix the driver behind crashes, sound loss and screen glitchesFind Drivers →Repair Windows errors before they cause bigger problemsFix Now →Scan for outdated or missing drivers - takes under a minuteDriver Scan →cURL
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)
r.raise_for_status()
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}`);
if (!res.ok) throw new Error(`${res.status} ${res.statusText}`);
const data = Buffer.from(await res.arrayBuffer());
require('fs').writeFileSync('shot.webp', data);
See the ScreenshotNeo documentation for parameters and response headers. The Free plan includes 1,000 shots per month with no card; paid plans start at $5 for 3,000 shots, and every feature is available on every plan. Create a free ScreenshotNeo account.
Operational and cost considerations
- Images consume less storage and processing time than videos; enable video only for runs where motion explains a failure.
- Failure-only and retry modes reduce CI artifact uploads while preserving evidence for broken or flaky tests.
- Use deterministic test data, stable browser versions, and explicit viewports for reproducible screenshots.
- Keep secrets out of screenshots and videos: redact sensitive fields or use test accounts.
- Set retention policies in your CI artifact store; Playwright’s capture mode controls creation and retention within the test run, not your external storage lifecycle.
Frequently Asked Questions
Where does Playwright save automatic screenshots?
They are normally placed in the test output directory, commonly under test-results. Use your reporter’s artifact links or testInfo.outputPath() to obtain the exact path.
Can I capture only one element instead of the whole page?
Yes. Locate it and call await locator.screenshot({ path: 'element.png' }); this captures the element’s rendered box.
Why must a video context be closed?
Playwright finalizes and writes the recording when the page or browser context closes. Read or upload the video after await context.close().
Do these 3 things before closing this tab:
1Scan for outdated or missing drivers - takes under a minute2Repair Windows errors before they cause bigger problems3Fix the driver behind crashes, sound loss and screen glitchesAre screenshots and videos enabled by default?
No. Playwright Test leaves both off until you set the corresponding use options or call a capture API yourself.
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.

