Back to guides

GUIDE / accessibility

Automated Accessibility Testing with axe-core

Learn automated accessibility testing with axe-core: CI integration, Playwright scans, what automation catches, and limits you still must test by hand.

By The Testing AcademyPublished July 9, 2026Updated July 9, 202619 min read

Most teams already have more accessibility bugs than they can manually find before release. Automated accessibility testing with axe-core is one of the most practical regression nets: free, widely integrated, rule-based, and strong at catching many WCAG-related defects before users or auditors do.

This guide explains what axe accessibility testing catches, how to integrate axe-core in Playwright or Cypress, how to build axe-core CI pipeline integration, and where the limitations of automated a11y scanners still force manual work. You will leave with a workable Playwright axe accessibility scan tutorial, severity guidance, and a release checklist that balances speed with honesty.

Why Automated Accessibility Testing Matters

Accessibility failures are product failures. A button without a name, a form without labels, or a modal that steals focus can block people from signing up, buying, booking, or getting support. Those bugs are often cheap to find with automation and expensive to discover later through support tickets, legal risk, or public complaints.

Automated accessibility testing matters for three operational reasons:

  1. Speed. Scanners check dozens of rules on a page in seconds.
  2. Consistency. Every pull request can run the same baseline.
  3. Regression control. Once you fix a missing label pattern, automation can stop it from returning.

Automation does not replace judgment. It multiplies the checks a small QA team can apply every day. The goal is not "axe says zero issues, ship." The goal is "axe catches the easy class of defects early, so humans spend time on hard problems."

If you need a broader process that includes keyboard, screen reader, and visual checks, start with the accessibility testing checklist for WCAG. This article goes deep on the automation layer of that process.

What Is axe-core?

axe-core is an open source accessibility rules engine maintained by Deque. Browser extensions, CI libraries, design tools, and test runners use it under the hood. When people say "run axe," they usually mean:

  • Load a page or component.
  • Inject or call the axe-core engine.
  • Collect rule results mapped to WCAG and best practice tags.
  • Report violations with selectors, impact, help text, and related success criteria.

axe is not a full accessibility audit. It is a static and semi-runtime checker of markup, styles, and some computed states. That scope is exactly why it fits continuous integration so well.

Common ways teams run axe

SurfaceTooling patternBest for
Manual spot checkBrowser extensionDesign review, bug triage
Unit or component testsjsdom or component harness + axeShared UI library rules
End-to-end testsPlaywright, Cypress, Selenium wrappersCritical journeys after render
CI route suiteHeadless browser + axe on URL listRelease regression net
Storybook or design systemsStory-level axe addonComponent quality gates

Pick the surface that matches your risk. Most product teams get the best return from critical-route end-to-end scans plus a design-system component gate.

For broader scanner and workflow selection, compare this setup with other accessibility testing tools before standardizing the team's baseline.

What Does Axe Accessibility Testing Catch?

axe is strong where a machine can evaluate a rule with high confidence.

High-value catches

  • Missing accessible names on buttons, links, and icons.
  • Form controls without associated labels.
  • Empty headings or invalid heading markup patterns.
  • Document without a language attribute.
  • Some ARIA role, property, and state mismatches.
  • Duplicate IDs that break label associations.
  • Certain color contrast failures on text.
  • Images without alternative text attributes.
  • Landmarks and page structure problems that can be inferred from markup.
  • Frames without titles in many cases.

These issues show up constantly in real products, especially when teams move fast with icon buttons, custom selects, and generated markup.

What axe usually does not catch well

  • Whether alt text is meaningful versus garbage.
  • Whether visible label text matches accessible name in a helpful way for all cases.
  • Logical focus order that is technically tabbable but confusing.
  • Keyboard traps in complex custom widgets.
  • Screen reader announcement quality for live regions.
  • Whether error messages are understandable.
  • Whether instructions depend on sensory characteristics alone.
  • Whether animation or timing causes barriers beyond simple rules.
  • Whether a flow is completable by a real assistive technology user.

That list is why you still need keyboard navigation testing and screen reader testing. Automation is a net, not a substitute for human verification.

How Automated Accessibility Testing Fits the Test Pyramid

Think of accessibility the same way you think of functional quality:

LayerAccessibility focusExample
ComponentNames, roles, contrast on primitivesButton, Input, Modal in Storybook
IntegrationForm associations, error wiringSignup form with validation messages
JourneyState after navigation and interactionCheckout steps after cart updates
Exploratory / ATReal assistive tech pathsNVDA or VoiceOver on release candidates

axe works best at the first three layers. The fourth layer remains manual or specialist-assisted.

A healthy release policy might look like this:

  • Component library: no critical or serious axe violations on stories.
  • Pull requests: axe on changed critical routes.
  • Nightly: broader route inventory.
  • Pre-release: keyboard and screen reader smoke on top journeys.
  • Quarterly: deeper audit sample with specialists if needed.

Playwright Axe Accessibility Scan Tutorial

This section shows a practical Playwright path. Exact package names can vary by ecosystem version, so treat the structure as the durable part and verify package docs for your stack.

Step 1: Add axe to the project

Install your Playwright axe integration and keep axe-core current. Teams often use a wrapper that:

  1. Injects axe-core into the page.
  2. Runs axe.run with configured options.
  3. Returns violations in a test-friendly shape.

Keep the dependency next to your e2e tooling so CI installs it with the rest of the test suite.

Step 2: Create a reusable scan helper

Centralize configuration. Do not copy rule options into every test.

// tests/a11y/axeHelper.ts
import AxeBuilder from "@axe-core/playwright";
import type { Page } from "@playwright/test";

export async function scanPage(page: Page, contextName: string) {
  const results = await new AxeBuilder({ page })
    .withTags(["wcag2a", "wcag2aa", "wcag21a", "wcag21aa", "wcag22aa"])
    .analyze();

  const seriousOrWorse = results.violations.filter((v) =>
    ["serious", "critical"].includes(v.impact ?? "")
  );

  if (seriousOrWorse.length > 0) {
    const summary = seriousOrWorse
      .map((v) => `${v.id} (${v.impact}): ${v.nodes.length} node(s)`)
      .join("\n");
    throw new Error(`Axe violations in ${contextName}:\n${summary}`);
  }

  return results;
}

Why this shape helps:

  • Tags keep the suite aligned to a WCAG target.
  • Filtering by impact avoids failing the world on every minor issue on day one.
  • Context names make CI logs readable.
  • Returning full results lets you attach artifacts later.

Step 3: Scan stable pages after render

// tests/a11y/public-pages.a11y.spec.ts
import { test } from "@playwright/test";
import { scanPage } from "./axeHelper";

const routes = [
  { path: "/", name: "home" },
  { path: "/pricing", name: "pricing" },
  { path: "/sign-up", name: "sign-up" },
  { path: "/login", name: "login" },
];

for (const route of routes) {
  test(`axe: ${route.name}`, async ({ page }) => {
    await page.goto(route.path);
    await page.waitForLoadState("networkidle");
    await scanPage(page, route.name);
  });
}

Step 4: Scan after interaction, not only on load

Many defects only appear after state changes:

  • Open modal.
  • Expand accordion.
  • Submit invalid form.
  • Open user menu.
  • Load search results.
test("axe: login validation state", async ({ page }) => {
  await page.goto("/login");
  await page.getByRole("button", { name: "Sign in" }).click();
  await page.getByText("Email is required").waitFor();
  await scanPage(page, "login-validation");
});

test("axe: settings modal", async ({ page }) => {
  await page.goto("/app/settings");
  await page.getByRole("button", { name: "Edit profile" }).click();
  await page.getByRole("dialog").waitFor();
  await scanPage(page, "settings-modal");
});

If you only scan the happy empty state, you will miss the states users hit when things go wrong.

Step 5: Scope exclusions carefully

Sometimes third-party widgets or known debt should not block every PR. Prefer narrow exclusions:

const results = await new AxeBuilder({ page })
  .exclude("#third-party-chat-root")
  .disableRules(["color-contrast"]) // only with a ticketed reason
  .analyze();

Rules for exclusions:

  • Exclude the smallest selector possible.
  • Link every exclusion to a ticket and owner.
  • Revisit exclusions monthly.
  • Never disable a rule forever "because design likes it."

Step 6: Report useful failure output

A raw dump of every node can overwhelm developers. Summarize by rule, show one example selector, and attach a full JSON artifact in CI. Developers fix faster when they can answer:

  • What rule failed?
  • Where on the page?
  • What impact?
  • Which WCAG criterion?

Cypress and Other Runner Patterns

The Playwright pattern translates cleanly to Cypress:

  1. Visit the route.
  2. Wait for the app to settle.
  3. Inject axe.
  4. Run checks.
  5. Assert no serious or critical violations.

Component-level tools can run axe against isolated stories. That catches design-system regressions before product screens assemble them into larger failures.

For Selenium or WebDriver stacks, the same principle holds: inject axe-core, run against the current document, collect violations, fail on agreed severities.

Whatever runner you use, keep one shared policy:

  • Target WCAG tags.
  • Define fail thresholds.
  • Scan multiple states.
  • Publish artifacts.
  • Require owners for suppressions.

Axe-core CI Pipeline Integration

CI is where automated accessibility testing earns its keep. A local scan that nobody runs is a hobby. A pipeline scan that blocks regressions is a quality control.

Suggested pipeline stages

StageWhenScopeFailure policy
PR smokeEvery pull requestTop 5-15 routes plus changed templatesFail on new critical/serious
Merge suiteOn mainBroader authenticated and public routesFail on critical/serious
NightlyScheduledFull inventory, multiple viewportsFail or warn by agreement
Release candidateBefore prodSame as merge plus manual AT smokeFail on open blockers

Practical CI tips

Authenticate once, scan many. If most product value sits behind login, build a stable auth setup for the a11y suite. Flaky login will poison trust in accessibility results.

Use deterministic data. Empty states and seed data should be stable. Random demos that disappear between runs create noisy diffs.

Pin environments. Scan staging or preview deployments with known feature flags. Scanning production from CI can be useful for monitoring, but release gates should use controlled builds.

Track trends. Count violations by rule and route over time. A flat "42 issues" number is weak. "login gained 3 label issues this week" is actionable.

Separate legacy debt from new debt. If an old admin area has known issues, quarantine it. Do not let historical debt teach the team to ignore the suite.

Fail closed for new code. The highest ROI policy is: new serious issues on critical journeys block merge. That creates a culture of prevention without demanding a perfect historical estate on day one.

Example policy language for the team

Pull requests that change user-facing UI must pass axe scans on affected critical routes. Critical and serious violations fail the build. Moderate and minor issues should be reviewed. Rule exclusions require a ticket ID and accessibility owner approval.

Put that in the testing strategy or contribution guide so debates do not restart every sprint.

Configuring Rules Without Creating False Safety

axe has many rules. Not every team should enable every experimental check on day one. Start with WCAG A and AA tags that match your target, usually WCAG 2.2 AA for modern products.

Useful configuration questions:

  • Are we targeting WCAG 2.1 AA or 2.2 AA?
  • Do we include best-practice rules that are not strict WCAG failures?
  • Do we run color-contrast in CI, or only in design review, or both?
  • Do we scan iframe content and shadow DOM where supported?
  • Do we need locale-specific pages in the suite?

A common mature setup:

  1. WCAG A/AA tags enabled.
  2. Critical and serious fail CI.
  3. Moderate reported as warnings with dashboards.
  4. Best-practice rules enabled on design-system stories first.
  5. Manual confirmation for contrast edge cases that tools struggle with.

For contrast-specific technique, pair this article with color contrast testing.

Designing an Axe Route Inventory

Do not only scan the marketing home page. Build a route inventory from risk.

High priority

  • Authentication: login, signup, password reset.
  • Checkout or purchase flows.
  • Search and critical booking or create flows.
  • Account settings that change personal data.
  • Error and empty states on those flows.
  • Modal and drawer patterns used globally.

Medium priority

  • Content-heavy help pages.
  • Dashboards with charts and tables.
  • Admin tools used daily by internal staff.
  • Email template previews if rendered in product.

Lower priority for automation first pass

  • Rarely used legacy screens scheduled for retirement.
  • Purely static legal pages with simple markup (still worth occasional scans).

Map each route to:

  • Owner team.
  • Auth requirements.
  • Key interactive states.
  • Manual AT coverage status.

Interpreting Axe Results Like a Tester

axe output is not a bug report. It is a lead. Your job is to convert leads into verified defects.

Triage workflow

  1. Reproduce visually. Open the page and inspect the highlighted node.
  2. Confirm user impact. Who is blocked, and in which assistive context?
  3. Check for false confidence. Is the rule right but the suggested fix incomplete?
  4. File a quality bug. Include selector, rule id, WCAG mapping, screenshot, and impact.
  5. Add regression coverage. Keep the axe scan, and add a focused unit or component test if the issue is systemic.

Severity guidance for product teams

Impact signalExampleTypical handling
Blocks a core taskUnlabeled submit on checkoutRelease blocker
Blocks a secondary taskIcon-only control with no name in settingsHigh, fix this sprint
Degrades experienceContrast fail on helper textMedium, schedule intentionally
Edge template debtOld unused admin pageTracked backlog with owner

Do not file 80 micro-tickets with no prioritization. Cluster by component pattern when the root cause is shared.

Automated Accessibility Testing in Design Systems

If you own a component library, axe at the story level may give more leverage than only product-route scans.

Benefits:

  • One broken IconButton story can prevent dozens of product defects.
  • Designers and frontend engineers get feedback before feature work.
  • Accessibility becomes a component acceptance criterion.

Suggested story checks:

  • Default state.
  • Disabled state.
  • Error state.
  • Loading state.
  • With icon only.
  • With long labels.
  • Dark and light themes if both ship.

Product suites still matter because composition creates new issues: duplicate landmarks, nested interactive controls, and page-level heading chaos that components alone cannot see.

Limitations of Automated A11y Scanners

Be honest with stakeholders. Overclaiming creates legal and ethical risk.

Automated scanners generally:

  • Cover only a subset of WCAG success criteria automatically.
  • Miss many operable and understandable failures.
  • Struggle with custom widgets that look fine in the accessibility tree at a glance but fail in real use.
  • Can pass pages that are still unusable with a keyboard or screen reader.

A useful stakeholder sentence:

Our axe suite prevents many known classes of accessibility regressions and gives fast feedback in CI. It does not certify WCAG conformance by itself. We still perform keyboard and screen reader testing on critical journeys.

That sentence protects trust better than a vanity zero-violation badge.

Manual Work That Must Stay Around Axe

After automation is green, still verify:

  • Tab order across the journey.
  • Focus visibility.
  • Skip links and bypass mechanisms.
  • Modal focus traps that are intentional and escapable.
  • Form error announcements.
  • Live updates and toasts.
  • Name, role, and state for custom controls.
  • Meaningful alternatives for images and media.
  • Consistent navigation and headings.

Automation can support some of these with custom assertions, but most need human execution. Build a short manual smoke that always runs before major releases, then deepen coverage with the dedicated guides linked above.

Common Mistakes

1. Scanning only the initial page load

Interactive products change. Validation errors, open dialogs, and loaded tables are where many issues hide. Scan states, not only URLs.

2. Treating zero violations as WCAG compliance

A clean axe report is good news, not a certificate. Conformance claims need broader evidence.

3. Disabling noisy rules forever

If color-contrast is noisy, fix design tokens or improve the suite. Permanent disables train the organization to ignore accessibility.

4. Failing the build on everything on day one

If a legacy app has hundreds of issues, an all-or-nothing gate can cause teams to turn the suite off. Start with critical routes and severities, then tighten.

5. No ownership for findings

Orphaned dashboards do not fix bugs. Every serious issue needs a team, a ticket, and a target release.

6. Ignoring authenticated product surfaces

Public pages matter, but the paid product is often where users spend time. Auth setup is part of accessibility infrastructure.

7. Copy-pasting exclusions without review

Exclusions multiply silently. Keep a living exception list with dates and owners.

8. Not pairing axe with design-system quality

If product teams keep re-fixing the same button anti-pattern, move the control left into the shared library.

Worked Example: Turning Axe Failures into Fixes

Imagine a signup page scan returns:

  1. button-name on a close icon in a promo banner.
  2. label on the company size select.
  3. color-contrast on muted helper text under password.
  4. aria-allowed-attr on a custom checkbox.

Tester actions

  • Confirm the close icon is focusable and has no accessible name.
  • Confirm the select is visible but not programmatically labeled.
  • Measure helper text contrast and decide if design must change tokens.
  • Inspect the custom checkbox markup with the accessibility tree.

High quality bug report ingredients

  • Route and environment.
  • Rule id and impact.
  • DOM snippet or selector.
  • Screenshot.
  • Who is affected.
  • Suggested direction, not a demand for one exact implementation.
  • WCAG reference if your team uses that mapping.

Regression strategy

  • Keep the page-level axe scan.
  • Add a component test for IconButton requiring an accessible name.
  • Add a form story that fails without labels.
  • Review password helper text in the design token contrast checklist.

This is how automation becomes a system, not a one-off report.

Accessibility Gates for Releases

Use a simple release card:

CheckOwnerStatus
Axe critical/serious clean on critical routesQA or frontend
New exclusions reviewedAccessibility owner
Keyboard smoke on top journeysQA
Screen reader smoke on top journeysQA
Open blocker defects triagedProduct + eng

If your team practices competitive or skill-based QA drills, run accessibility scenarios in product practice environments such as QABattle battles to build tester judgment around real UI risk, then bring that judgment back to your pipeline design.

How to Roll Out Axe Without Stalling Delivery

A practical 30-day rollout:

Week 1: Install browser extension culture. Train the team on reading violations. Pick five critical routes.

Week 2: Add Playwright or Cypress scans for those routes in CI as soft warnings.

Week 3: Turn serious and critical into hard failures on those routes. Create a debt board for existing issues.

Week 4: Add interaction-state scans, component-level checks for the design system, and a weekly triage ritual.

After 30 days, expand route coverage and tighten tags. Do not wait for perfect historical cleanliness before protecting new work.

Measuring Whether Automated Accessibility Testing Is Working

Track outcomes, not vanity metrics:

  • Number of serious axe violations escaping to main.
  • Time to remediate critical accessibility bugs.
  • Percentage of critical journeys under CI scan.
  • Number of active rule exclusions.
  • Manual AT defects found after green axe (this should trend in a healthy direction as process matures, then stabilize as harder issues remain).
  • Repeat component-pattern defects.

If manual testing keeps finding the same machine-detectable issues, your automation scope or gate is too weak. If automation is green and manual testing only finds judgment-heavy issues, your split of labor is healthy.

Practice and Next Steps

To deepen the surrounding skills:

If you want structured practice against app-like arenas and battle-style QA challenges, sign up for QABattle and use accessibility scenarios to train your eye before the next production release.

Automated Accessibility Testing Checklist

Copy this into your team wiki:

  1. Define WCAG target and severity fail policy.
  2. Choose runner integration (Playwright, Cypress, or component harness).
  3. Build a shared scan helper with tags and impact filters.
  4. Inventory critical routes and interactive states.
  5. Add PR-level CI scans for critical journeys.
  6. Publish violation artifacts and readable summaries.
  7. Require tickets and owners for exclusions.
  8. Cluster defects by component pattern.
  9. Keep keyboard and screen reader smoke outside the scanner.
  10. Review metrics monthly and expand coverage deliberately.

Final Takeaways

Automated accessibility testing with axe-core is one of the highest leverage quality investments a web team can make, provided nobody confuses it with a full accessibility program. Use axe to catch machine-detectable defects early, fail CI on serious regressions, and free human testers for keyboard, screen reader, and meaning-level evaluation.

Ship the pipeline. Scan real states. Own the findings. Keep the manual craft. That combination is how teams move from good intentions to durable accessibility quality.

FAQ

Questions testers ask

What does axe accessibility testing catch?

axe catches many rule-based issues such as missing form labels, empty buttons, some color contrast failures, invalid ARIA usage, missing document language, and certain landmark or heading problems. It is strong at machine-checkable WCAG rules and weaker at meaning, focus order sense, and complete keyboard or screen reader journeys.

How do you integrate axe-core in Playwright or Cypress?

Install an axe integration package for your runner, inject or call axe after the page reaches a stable state, then assert that serious and critical violations are empty. Scan key routes after navigation, after opening modals, and after dynamic content loads. Run the same checks in CI so regressions fail the pipeline.

Can automated tools replace manual accessibility testing?

No. Automated scanners typically find only a fraction of real accessibility barriers. They miss many keyboard traps, poor focus order, unhelpful alt text, confusing announcements, and broken screen reader flows. Use automation as a fast first pass and gate, then complete keyboard, visual, and assistive technology testing.

Where should axe run in a CI pipeline?

Run axe on critical pages and components in pull request checks, and again on a broader route set in nightly or release jobs. Prefer failing the build on new serious or critical rules while tracking moderate issues. Scan after the app is fully rendered, not only on the empty shell.

What are the limitations of automated a11y scanners?

Scanners cannot reliably judge whether labels make sense, whether instructions are clear, whether focus order matches reading order, or whether a complex widget is operable with assistive technology. They also miss many timing, motion, and cognitive issues. Treat zero automated violations as a baseline, not a certificate of accessibility.

How do you keep axe results useful over time?

Scope rules deliberately, exclude only justified known issues with tickets, re-scan after interaction states, track trends by route, and require owners for open findings. Pair each repeated false positive with a documented exception and a manual verification path so the suite never becomes a ignore list.