How to Configure Playwright to Always Capture Screenshots
Configure Playwright Test to save a screenshot after every test, with modes, full-page options, fixes, and a ScreenshotNeo alternative.
Direct answer: In Playwright Test, set screenshot: 'on' inside the top-level use object in playwright.config.ts. Playwright then saves a screenshot after every test. Automatic screenshots are off by default. See the official Playwright configuration reference.
import { defineConfig } from '@playwright/test';
export default defineConfig({
use: {
screenshot: 'on',
},
});
Run the suite with npx playwright test. Artifacts are written under the test output directory, commonly test-results.
1. Choose when screenshots are captured
| Mode | Behavior | Use it when |
|---|---|---|
off |
No automatic screenshot | You only call page.screenshot() |
on |
After every test | You need an artifact for every pass and failure |
only-on-failure |
After failed tests | You want debugging evidence with less storage |
on-first-failure |
After a test’s first failure | You retry tests and need one failure artifact |
import { defineConfig } from '@playwright/test';
export default defineConfig({ use: { screenshot: 'only-on-failure' } });
Use on when every completed test needs an image. Use a failure mode when artifact volume matters more than screenshots from passing tests.
2. Configure full-page and transparent captures
The setting accepts an object with a mode. Documented fields include fullPage and omitBackground:
import { defineConfig } from '@playwright/test';
export default defineConfig({
use: {
screenshot: { mode: 'on', fullPage: true, omitBackground: true },
},
});
fullPage: truecaptures the full scrollable page instead of only the viewport.omitBackground: trueallows transparency. It does not apply to JPEG.
Long pages create larger files and may take longer to encode.
3. Complete runnable example
// playwright.config.ts
import { defineConfig } from '@playwright/test';
export default defineConfig({
testDir: './tests',
outputDir: './test-results',
use: {
baseURL: 'https://example.com',
screenshot: 'on',
viewport: { width: 1280, height: 720 },
},
});
// tests/home.spec.ts
import { test, expect } from '@playwright/test';
test('home page has a heading', async ({ page }) => {
await page.goto('/');
await expect(page.locator('h1')).toBeVisible();
});
npm install -D @playwright/test
npx playwright install
npx playwright test
npx playwright show-report
Playwright manages artifact filenames and places them in each test result folder.
4. Override the global setting
Project and test settings can override the global default:
import { defineConfig } from '@playwright/test';
export default defineConfig({
use: { screenshot: 'on' },
projects: [
{ name: 'chromium', use: { browserName: 'chromium' } },
{ name: 'mobile', use: { browserName: 'chromium', screenshot: 'only-on-failure' } },
],
});
import { test } from '@playwright/test';
test.use({ screenshot: 'only-on-failure' });
test('checkout', async ({ page }) => {
await page.goto('https://example.com/checkout');
});
More specific settings override broader ones.
5. Automatic versus explicit screenshots
screenshot: 'on' captures after the test finishes. For an intermediate state, call the page API:
test('checkout states', async ({ page }) => {
await page.goto('https://example.com/checkout');
await page.screenshot({ path: 'artifacts/form.png', fullPage: true });
await page.screenshot({ path: 'artifacts/complete.png' });
});
For visual regression, use await expect(page).toHaveScreenshot('home.png'). Automatic artifacts, explicit captures, and screenshot assertions serve different purposes. Video and trace recording are separate options.
6. Timing, retries, and parallel workers
- Capture happens after the test body completes, so wait for the UI state you need.
- Retries can create artifacts for each failed attempt.
- Parallel workers use separate result paths; do not assume one shared filename.
- Animations, fonts, clocks, ads, and remote data can make screenshots differ between runs. Use stable test data, fixed viewports, and waits for meaningful selectors.
7. Troubleshooting
| Symptom | Cause | Fix |
|---|---|---|
| No screenshots | Option missing, misspelled, or still off |
Put screenshot: 'on' under use. |
| Only failures have images | A failure mode is configured | Change the mode to 'on'. |
| Only viewport captured | fullPage is false |
Use object form with fullPage: true. |
| Transparent output is white | JPEG cannot contain transparency | Use a format with alpha and omitBackground: true. |
| Artifacts are hard to find | They are in the configured output directory | Set outputDir and open the HTML report. |
| Flaky visual differences | Fonts, motion, time, or remote data vary | Stabilize those inputs and wait for the final state. |
| Config has no effect | Wrong config file or working directory | Run npx playwright test -c playwright.config.ts. |
8. Performance, storage, and reliability
- Every-test capture adds rendering and image-encoding work. Cost grows with test count, viewport size, and page height.
- Failure-only modes reduce artifact storage and CI upload time.
- Store screenshots as CI artifacts with a retention policy; do not commit generated images.
- Use stable browser versions, fonts, locale, timezone, and data for reproducible images.
- Keep logs, traces, or videos when a screenshot alone cannot explain a blank or partial page.
9. Or skip the browser setup
If you need a clean screenshot from a URL rather than a test-runner artifact, ScreenshotNeo provides one GET request returning PNG, JPEG, WebP, or PDF. See the ScreenshotNeo API documentation.
curl -G "https://api.screenshotneo.com/v1/shot" -d access_key=YOUR_API_KEY --data-urlencode url=https://stripe.com -o shot.webp
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)
const q = new URLSearchParams({ access_key: 'YOUR_API_KEY', url: 'https://stripe.com' });
const res = await fetch(`https://api.screenshotneo.com/v1/shot?${q}`);
Cookie and consent banners, newsletter popups, and chat widgets are removed before capture. Bot checks, blank pages, failed loads, timeouts, and cache hits are not billed; response headers report the page verdict and billing status. Its MCP server provides take_screenshot, get_page_info, and capture_pdf for Claude, Cursor, and other MCP clients. The free plan includes 1,000 screenshots monthly with no card; paid plans start at $5 for 3,000.
Create a free ScreenshotNeo account.
10. FAQ
Does automatic mode capture during a test?
No. It captures after completion. Use page.screenshot() for an intermediate state.
Can automatic screenshots and visual assertions coexist?
Yes. They are independent features.
Is a trace required?
No. Traces and videos are separate recording options.
Which mode suits CI?
Use on for every result; use only-on-failure or on-first-failure for smaller artifacts.


