ScreenshotNeo

BlogHow-to

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.

By the ScreenshotNeo team1 October 20264 min read

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: true captures the full scrollable page instead of only the viewport.
  • omitBackground: true allows 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.