ScreenshotNeo

BlogHow-to

How to Schedule Website Screenshots for Accessibility Review Evidence

Build a repeatable screenshot evidence workflow with Playwright, scheduled CI runs, consistent browser settings, and accessibility checks that go beyond images.

By the ScreenshotNeo team4 October 20269 min read

Use a browser automation script such as Playwright to capture the pages and interaction states your team reviews, then run that script on a recurring schedule in your CI system or job scheduler. Save each image with a descriptive name and record the URL, state, timestamp or run ID, browser, operating environment, and viewport. Treat screenshots as records of what rendered in that context and moment: they do not prove that a page conforms to WCAG. Pair them with automated accessibility checks, manual assessment, and inclusive user testing where appropriate. Playwright explicitly notes that automated testing cannot detect all types of WCAG violations.

1. Decide what the evidence needs to show

Start with the review question, not the screenshot command. List the pages and states that matter, then choose a capture scope for each one. Include meaningful interaction states such as an open navigation menu, a validation message, or a modal when those are part of the experience under review.

Capture scope Useful for Trade-off
Viewport A focused view of the initial or interactive state at a defined screen size. Content outside the visible viewport is not shown.
Element A particular component, such as a dialog, form, or navigation region. It omits surrounding page context unless that context is captured separately.
Full page Reviewing the overall page structure and long pages in one image. Long pages can produce tall images that are harder to inspect and compare.

Playwright supports viewport, element, and full-page screenshots, as well as explicit filenames. Choose the smallest set of captures that answers the review questions; add separate captures for important states instead of relying on one long page image to tell the whole story. See the Playwright screenshot documentation.

2. Create a repeatable Playwright capture

The following example uses Playwright Test. It visits a page, waits for a known heading, captures the viewport and full page, and writes a small JSON manifest beside the images. Replace the example URL and selectors with your review targets. Pin the Playwright version in your project lockfile so scheduled runs use a deliberate browser version.

import { test, expect } from '@playwright/test';
import { mkdir, writeFile } from 'node:fs/promises';

const baseURL = process.env.REVIEW_BASE_URL ?? 'https://example.com';
const runId = process.env.GITHUB_RUN_ID ?? new Date().toISOString().replaceAll(':', '-');
const outputDir = `artifacts/accessibility/${runId}`;

test('capture accessibility review evidence', async ({ page, browserName }) => {
  await mkdir(outputDir, { recursive: true });
  await page.setViewportSize({ width: 1440, height: 900 });

  const url = new URL('/contact', baseURL).toString();
  await page.goto(url, { waitUntil: 'domcontentloaded' });
  await expect(page.getByRole('heading', { name: 'Contact' })).toBeVisible();

  // Capture the initial viewport and the complete page.
  await page.screenshot({ path: `${outputDir}/contact-viewport.png` });
  await page.screenshot({ path: `${outputDir}/contact-full-page.png`, fullPage: true });

  // Capture a meaningful state when it is relevant to the review.
  await page.getByRole('button', { name: 'Send message' }).click();
  await expect(page.getByText('Enter your email address')).toBeVisible();
  await page.screenshot({ path: `${outputDir}/contact-email-error.png` });

  const manifest = {
    runId,
    capturedAt: new Date().toISOString(),
    browser: browserName,
    viewport: { width: 1440, height: 900 },
    captures: [
      { file: 'contact-viewport.png', url, state: 'initial viewport' },
      { file: 'contact-full-page.png', url, state: 'full page' },
      { file: 'contact-email-error.png', url, state: 'empty form validation error' }
    ]
  };
  await writeFile(`${outputDir}/manifest.json`, JSON.stringify(manifest, null, 2));
});

Install and run it from the project root:

npm install --save-dev @playwright/test
npx playwright install chromium
npx playwright test

The heading and validation text are examples. Use stable role-based locators where possible, wait for the content that makes the capture meaningful, and fail the run if an expected state does not appear. A screenshot taken after a failed navigation or before the page is ready can create misleading evidence.

Capture a component or a full page

For an element screenshot, locate the component and pass a path to its screenshot method:

const dialog = page.getByRole('dialog', { name: 'Cookie preferences' });
await expect(dialog).toBeVisible();
await dialog.screenshot({ path: `${outputDir}/cookie-preferences-dialog.png` });

For a full-page capture, set fullPage: true on page.screenshot. For a viewport capture, leave it unset. Use explicit filenames that identify the page and state; the extension selects the image format supported by the browser tooling.

3. Add accessibility checks alongside the images

Images help reviewers see rendered appearance and state, but they do not expose every accessibility issue. Add automated checks to the same run where useful, and keep manual assessment in the workflow. For important flows, include feedback from people with relevant access needs. Playwright recommends combining automated checks with other assessment methods because automation has limits. Read Playwright’s accessibility testing guidance.

Keep the outputs linked by run ID: screenshot files, the capture manifest, automated scan output, and any manual review notes. This makes it easier to understand which page state and environment a finding refers to. The manifest format above is a practical recommendation, not a formal evidence standard.

4. Schedule the capture in CI or a job scheduler

Run the test at an interval your team can review, and consider triggering it after releases or substantial content changes. There is no universally correct cadence or retention period in the cited browser guidance; choose both according to the rate of change and your review process. Scheduler syntax differs by CI provider, so the job below is intentionally provider-neutral.

  1. Check out the site or test repository and install the pinned dependencies.
  2. Install the browser required by the test runner.
  3. Set the target base URL and any required test credentials as protected environment variables.
  4. Run the capture test on the recurring schedule and, if useful, after deploys.
  5. Upload the output directory as a job artifact or store it in your approved evidence repository.
  6. Keep the run ID, capture manifest, browser version, and any accessibility scan results with the images.

For scheduled evidence, define what should happen when the target site is unavailable. A failed run should be clearly marked as failed rather than silently treated as a valid screenshot set. Avoid putting secrets in the manifest or artifact names.

5. Keep comparisons meaningful

Visual comparisons are sensitive to the environment. Playwright documents that operating system, browser version, settings, hardware, power source, and headless mode can affect rendering. Keep the browser and execution environment consistent where possible, and record enough context to explain differences. Playwright’s screenshot comparison guidance also describes waiting for consecutive screenshots to match before comparison to reduce transient rendering differences.

  • Use a stable browser version and a consistent CI image or host.
  • Set the viewport explicitly and keep device scale settings consistent.
  • Wait for a meaningful page condition instead of relying only on a fixed delay.
  • Where animation or dynamic content interferes with review, control the page state or use the test runner’s supported screenshot options deliberately.
  • Compare like with like: the same URL, state, viewport, browser, and relevant user context.

A visual diff can flag appearance changes for investigation. It is not an accessibility conformance result, and a matching screenshot does not establish that assistive technology users can operate the page.

6. Decide what evidence to retain

Give each run a unique identifier and preserve the capture manifest with the images. Agree on retention based on your team’s review and recordkeeping needs; the referenced sources do not set a universal retention duration. If artifacts may contain personal information or sensitive page content, restrict access and retention accordingly.

A useful evidence record includes the target URL, page state, capture timestamp or run ID, browser and operating environment, viewport, screenshot scope, and links to related scan results or review notes. This is a workflow recommendation inferred from the capture and testing context, not a claim that a specific formal standard requires this exact manifest.

7. Troubleshooting

Symptom Likely cause Fix
Capture is blank or shows the wrong page Navigation failed, a redirect changed the target, or the test captured before expected content appeared. Check the final URL and navigation errors; wait for a page-specific locator before saving the image.
Screenshot is inconsistent across runs Browser or host differences, changing content, animation, or a page state that was not fully ready. Pin the browser environment, set the viewport, wait for stable expected content, and control relevant dynamic state.
Interaction-state image is missing The action did not reach the expected state, or the locator is ambiguous or stale. Use a specific role/name locator, assert the resulting state is visible, and only then capture.
Full-page image is difficult to review The page is very long or contains content irrelevant to the question. Capture the relevant element or viewport as well, and separate important states into descriptive files.
Scheduled run has no artifacts The runner failed before upload, the output path differs from the upload path, or the scheduler environment lacks required configuration. Inspect the job log, confirm the artifact path, and make artifact upload run even when the test fails so diagnostics remain available.
Visual diff reports noise Rendering conditions or content changed between runs. Compare runs in a consistent environment and investigate whether the difference is meaningful before updating any baseline.

8. Performance, reliability, and cost

Capture only the pages and states that answer review questions. Full-page screenshots and additional interaction states take more browser time and storage than a single viewport capture. Reuse the test setup, avoid unnecessary waits, and wait on specific content or state rather than adding large fixed delays. A scheduled browser run depends on the target site, network, CI capacity, and test stability; report failures as failures and retain diagnostics so transient outages do not look like successful evidence.

Playwright is browser automation you run in your own environment, so account for CI execution and artifact storage under your existing platform’s terms. The cited sources do not establish a universal cost per capture. ScreenshotNeo offers a hosted screenshot API with a free tier and paid plans; its pricing and billing rules are described below using the product’s stated terms.

Or skip the browser setup

ScreenshotNeo is a website screenshot API and MCP server. One GET request can return a PNG, JPEG, WebP, or PDF; consult the ScreenshotNeo API documentation for request options. For a simple scheduled page capture, call the endpoint and save its response:

curl -G "https://api.screenshotneo.com/v1/shot" -d access_key=YOUR_API_KEY --data-urlencode url=https://example.com -o shot.webp
import requests

r = requests.get(
    "https://api.screenshotneo.com/v1/shot",
    params={"access_key": "YOUR_API_KEY", "url": "https://example.com"},
    timeout=90,
)
open("shot.webp", "wb").write(r.content)
const q = new URLSearchParams({ access_key: 'YOUR_API_KEY', url: 'https://example.com' });
const res = await fetch(`https://api.screenshotneo.com/v1/shot?${q}`);
if (!res.ok) throw new Error(`Screenshot request failed: ${res.status}`);
const fs = await import('node:fs/promises');
await fs.writeFile('shot.webp', Buffer.from(await res.arrayBuffer()));

ScreenshotNeo removes cookie banners, newsletter popups, and chat widgets before capture; each cleanup step can be turned off. Bot checks, blank pages, failed loads, timeouts, and cache hits are not billed, and response headers report the page verdict and billing status. Its MCP server provides screenshot tools for AI agents. The free plan includes 1,000 screenshots a month with no card; paid plans start at $5 for 3,000. The same API can capture one target per call; use your scheduler to repeat requests and preserve your own run context. Screenshots still document rendered appearance, so pair them with accessibility checks and human review.

Create a free ScreenshotNeo account for 1,000 screenshots a month with no card.

FAQ

Do screenshots prove WCAG conformance?

No. They show rendered appearance in a particular context. Accessibility checks, manual assessment, and user testing are needed to evaluate more than appearance.

How often should the capture run?

Set an interval your team can review and add runs after meaningful releases or content changes. The sources do not prescribe a universal schedule.

Should every page use a full-page screenshot?

No. Choose viewport, element, or full-page scope according to the review question, and capture separate interaction states when they matter.

Can screenshots from different environments be compared?

They can be compared, but rendering differences may reflect the browser or host rather than the page. Consistent conditions make visual differences easier to interpret.