ScreenshotNeo

BlogHow-to

How to Automate Website Accessibility Testing

Add repeatable accessibility checks to development and CI, then review findings and test the parts automation cannot judge.

By the ScreenshotNeo team4 October 20269 min read

Automate accessibility checks by scanning the rendered pages and interface states your tests actually visit, fixing confirmed findings, and rerunning the checks in development or CI. Treat the results as a way to catch some machine-detectable issues early, not as proof that a site conforms to WCAG: tools cannot evaluate every accessibility requirement, and knowledgeable human review is still needed. W3C explains the limits of evaluation tools and its evaluation overview recommends evaluation early and throughout development.

1. Decide what the automated checks should cover

A browser-based accessibility engine can inspect the rendered interface for issues it knows how to detect. That makes it useful for repeatable checks of pages, components, and states exercised by your tests. It does not tell you whether every user can complete a task, whether content makes sense, or whether a site meets a standard in full.

Start with the interfaces that matter most to users and change often: shared components, key landing pages, forms, account flows, and critical task journeys. Include meaningful states, such as an open menu, validation errors, dialogs, or expanded content. A scan only covers what the test renders and visits.

Keep these boundaries in mind:

  • Automated findings are potential issues to inspect. Confirm that the reported element and rule apply before changing code.
  • A clean report means the tool found no issues within its rules and the tested state. It is not a conformance verdict.
  • Automated tools can be inaccurate or misleading, and some accessibility aspects require human judgment. W3C says tools can assist with evaluation but cannot determine accessibility on their own.
  • Broader evaluation can cover representative pages, groups of pages, whole sites, or authenticated content, depending on the tool and access available. State exactly what your scan covers.

2. Add a repeatable Playwright check

One practical approach is to run an accessibility engine against pages in your existing browser tests. The example below uses Playwright Test with the axe integration. W3C’s tool directory lists axe-core as a free testing engine with integrations including Playwright and Selenium; this is an example of an integration, not an endorsement. Check the current package documentation and versions when adopting it.

Install the dependencies

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

Create tests/accessibility.spec.js:

const { test, expect } = require('@playwright/test');
const { AxeBuilder } = require('@axe-core/playwright');

test('home page has no detected accessibility violations', async ({ page }) => {
  await page.goto(process.env.BASE_URL || 'http://127.0.0.1:3000');

  const results = await new AxeBuilder({ page }).analyze();
  const summary = results.violations.map((violation) => ({
    id: violation.id,
    impact: violation.impact,
    description: violation.description,
    help: violation.help,
    helpUrl: violation.helpUrl,
    nodes: violation.nodes.map((node) => ({
      target: node.target,
      summary: node.failureSummary
    }))
  }));

  expect(summary, JSON.stringify(summary, null, 2)).toEqual([]);
});

Run it after starting the application locally or point BASE_URL at a test deployment:

BASE_URL=http://127.0.0.1:3000 npx playwright test tests/accessibility.spec.js

The assertion makes detected violations fail the test and prints a useful summary. During initial adoption, you may prefer to collect and review the report before making the check blocking. Do not turn unresolved findings into a permanent ignored baseline without tracking and revisiting them.

Scan important interaction states

Navigation and interaction are ordinary browser-test steps. Scan after the page reaches the state you want to evaluate:

test('open navigation has no detected accessibility violations', async ({ page }) => {
  await page.goto(process.env.BASE_URL || 'http://127.0.0.1:3000');
  await page.getByRole('button', { name: 'Menu' }).click();

  const results = await new AxeBuilder({ page }).analyze();
  expect(results.violations, JSON.stringify(results.violations, null, 2)).toEqual([]);
});

Use accessible role and name locators where the interface supports them. If a control has no usable role or name, that may be a testability concern as well as a signal to inspect the control. Adapt the locator to your actual interface; the sample assumes a button named “Menu.” Add separate checks for materially different states rather than assuming the initial page scan covers them.

3. Put the checks in your delivery workflow

  1. Run locally during development. Scan the page or component state you changed. Fix confirmed issues while the relevant code is fresh.
  2. Add checks to browser tests. Cover representative routes and important interaction states, not just the home page.
  3. Run them in CI. Start the app in the test environment, set the test base URL, and run the same browser test command. Store reports or test output with the build when that helps the team investigate failures.
  4. Review failures. Inspect the affected element, the rule, and the surrounding interface. Fix real issues, rerun the check, and confirm that the change did not break the user flow.
  5. Schedule broader evaluation. Use a suitable site or representative-page scan when its scope and access fit your needs. Record which URLs, authenticated areas, and states were included.
  6. Include manual evaluation. Have people with accessibility knowledge assess aspects that automation cannot settle, including complete journeys and the usability of the interface in context.

W3C recommends evaluating early and throughout development because issues are easier to address while work is underway. Its evaluation tools list includes tools for different workflows and scopes; listings are not endorsements, and tool information can change.

4. Choose a tool for your workflow

There is no single tool choice that fits every team. W3C recommends considering your process, site complexity, specialist technologies, and developers’ skills. Compare options on the work they support:

Question What to check
What is its purpose? Does it automate checks, guide manual evaluation, simulate a user experience, or combine roles?
What can it scan? Can it check a component, one page, a sample, a site, or authenticated content? Which rendered states does it include?
Where does it fit? Does it work as a browser extension, command-line tool, CI integration, desktop or online service, or CMS tool?
What does it report? Can your team identify the affected element, understand the finding, and decide what to fix?
What does it cover? Review the standards, versions, rules, and applicable ACT rule implementations it supports. Do not assume that two tools cover the same requirements.
Can the team operate it? Check platform and browser support, language, required expertise, access needs, reporting workflow, and cost or licensing.

Teams may combine tools across development stages. For example, a browser or CI check can give developers repeatable feedback, while a broader evaluation workflow can cover pages and contexts outside the automated test suite. Verify current capabilities, versions, availability, and pricing directly with each tool provider: W3C notes that specific tool information changes frequently.

5. Add a broader evaluation method

Automated scans are one part of an evaluation plan. W3C’s WCAG-EM 2.0 is a published evaluation methodology for assessing conformance to WCAG across websites, apps, and other digital products. It describes an evaluation process; it is not a scanner. Use an appropriate methodology when you need a structured evaluation beyond the pages and states covered by CI.

For a broader scan, establish a representative scope and make access arrangements for any restricted areas. Review what the tool actually reached and report that scope. A result from a few public URLs cannot establish the behavior of unvisited authenticated flows or states.

6. Keep visual evidence separate from accessibility results

Screenshots can help developers compare a page before and after a change or attach visual context to a review. They are not accessibility tests: an image does not establish whether controls have accessible names, the page works by keyboard, or assistive technology can interpret its content.

ScreenshotNeo is a website screenshot API and MCP server. Use it to capture visual evidence alongside your accessibility workflow, while keeping the actual accessibility checks and human evaluation in their own steps.

7. Troubleshoot common problems

Symptom Likely cause What to do
The test reports a violation. A rule detected a potential issue in the rendered state. Inspect the rule, target element, and failure details. Confirm the issue, fix the markup or behavior, then rerun the check.
A test passes, but a user reports an accessibility problem. The issue may not be machine-detectable, or the affected page, state, or journey was not tested. Reproduce the relevant state, add coverage where suitable, and include manual evaluation. A passing scan is not proof of accessibility.
The scan misses a dialog, menu, or validation state. The test scanned before opening or triggering that state. Drive the interface into the state first, then run a separate scan for it.
The browser cannot reach the page. The app may not be running, the base URL may be wrong, or the route may require authentication. Check the app startup step and URL in the test environment. Configure a test account or session for restricted routes where appropriate.
The same check behaves differently across runs. The page may depend on asynchronous content, external services, or changing data. Wait for a meaningful page-ready condition, stabilize test data, and reduce unnecessary third-party dependencies in the test environment.
The report is hard to act on. The test output may omit element targets or rule details. Print or retain the violation ID, impact, help text, affected targets, and failure summary. Keep enough output to reproduce the page state.
A page-wide scan takes too long. The suite may be scanning too many routes or repeatedly launching browsers. Prioritize critical routes and shared components, reuse the existing browser-test setup, and run broader coverage on an appropriate schedule. Preserve meaningful coverage.

8. Performance, reliability, and cost

  • Performance: Browser scans add work to each test, so begin with high-value routes and changed components. Avoid scanning the same unchanged state repeatedly when a focused test provides adequate feedback. Balance speed against coverage.
  • Reliability: Test a stable deployment with controlled data and explicit navigation and state setup. Include authenticated coverage deliberately. Keep the tool and browser dependencies maintained, and review changes when upgrading them.
  • Cost: Tool costs and licensing vary. W3C’s tool list and selection guidance do not settle current vendor pricing; check providers’ current terms. Also account for the engineering time needed to review findings and manually evaluate experiences.
  • Coverage: More URLs do not automatically mean better evaluation. Include representative templates, high-impact journeys, and states that automated checks can meaningfully inspect. Document gaps for manual review.
  • Release decisions: Decide which confirmed findings block a release and how exceptions are recorded. Do not treat a numeric score or a clean automated report as a standalone conformance determination.

9. Or skip the browser setup

ScreenshotNeo captures visual evidence; it does not run accessibility rules or replace manual evaluation. Its API can help when you need repeatable screenshots alongside your test results. The screenshot-specific details and options are in the ScreenshotNeo 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}`);
if (!res.ok) throw new Error(`Screenshot request failed: ${res.status}`);
await import('node:fs/promises').then(({ writeFile }) => writeFile('shot.webp', Buffer.from(await res.arrayBuffer())));

ScreenshotNeo removes supported cookie and consent banners, newsletter popups, and chat widgets before the shot; each step can be turned off. Bot checks or CAPTCHAs, blank pages, timeouts, failed loads, and cache hits cost nothing, and the response includes page-verdict and billing headers. Its MCP server offers take_screenshot, get_page_info, and capture_pdf for AI agents and MCP clients. The free plan includes 1,000 screenshots a month with no card; paid plans start at $5 for 3,000 shots. Sign up for 1,000 free screenshots a month with no card.

FAQ

Can accessibility testing be fully automated?

No. Automation can catch some potential issues, but it cannot judge every accessibility aspect or determine conformance by itself. Combine it with knowledgeable human evaluation.

Does a clean scan mean my site meets WCAG?

No. It means the scan did not report issues within its rules on the content and states it examined. It does not cover unvisited pages or replace a broader evaluation.

Should accessibility checks run on every pull request?

Run focused checks in the workflow when the runtime and coverage fit your team. Add representative routes and states, and plan broader evaluation separately where needed.

Is WCAG-EM a testing tool?

No. WCAG-EM 2.0 is a methodology for evaluating WCAG conformance across digital products, not an automated scanner.

Sources