Automated accessibility testing uses tools like axe-core, Lighthouse, or Pa11y to check a rendered page against machine-verifiable WCAG rules — missing alt text, unlabeled inputs, low contrast, invalid ARIA — and report the offending element. It runs in CI or on a schedule, and per industry research catches roughly half of accessibility issues. The rest needs a human.
Around 16% of the world's population lives with a significant disability. Meanwhile WebAIM's annual survey of the top million homepages keeps finding the same thing: the overwhelming majority have detectable WCAG failures, and the typical homepage has dozens. The gap between "we care about accessibility" and "our signup form has labels" has never been wider — or more expensive.
Expensive, because the legal landscape moved. The European Accessibility Act (EAA) has applied since June 28, 2025: e-commerce and many digital services sold into the EU must be accessible, with member states attaching real fines. In the US, ADA lawsuits over inaccessible websites continue at thousands per year, and they disproportionately target small and mid-size businesses — the ones without an accessibility team.
This post is about the automation layer: what a scanner can genuinely catch, what it can't, and why "it's automated, so it's partial" is an argument for running it on every deploy rather than skipping it.
The Web Content Accessibility Guidelines (WCAG) 2.x organize requirements under four principles — content must be perceivable, operable, understandable, and robust. Conformance comes in levels; Level AA is the standard contracts, laws (including the EAA's underlying EN 301 549), and procurement checklists mean when they say "accessible."
In practice, AA translates into things like: every image conveys its information in text, every form field has a name, the page has a sane heading structure, keyboard users can reach and operate everything, nothing relies on color alone, and assistive technologies can parse the markup. None of this is exotic — most of it is HTML used the way HTML was designed.
Three conformance levels stack. Level A is the floor — the failures that make content outright unusable (no keyboard access, no alt text, autoplaying audio you can't stop). Nobody targets A on purpose; you pass it on the way to AA.
Level AA is the target that matters. It's what EN 301 549 (the European standard the EAA leans on) points at, what US ADA settlements and consent decrees routinely name, what Section 508 procurement requires, and what your enterprise customer's security questionnaire or VPAT will ask you to attest to. If a contract, law, or RFP says "accessible" without qualifying it, assume WCAG 2.1 (or 2.2) Level AA.
Level AAA adds stricter criteria — 7:1 contrast, sign-language interpretation for prerecorded audio, no more than three-word-per-line justification quirks. The W3C explicitly says AAA is not achievable for all content, so it isn't a sane site-wide goal. Cherry-pick AAA criteria where they're cheap (7:1 contrast on body text costs nothing at design time) and target AA everywhere.
When you configure a tool, this maps directly to a tag filter: axe-core's wcag2a, wcag2aa, wcag21aa tags, or Pa11y's WCAG2AA standard. Pick AA and stop arguing about it.
Deque's research — the most-cited number in this space — found that automated testing can detect issues accounting for roughly 57% of accessibility problems. Call it "about half," and note that the half automation owns is the half that's objective, repeatable, and cheap to fix. That's the automation surface, and it covers the failures that are both most common and most embarrassing:
lang attribute — screen readers guess the pronunciation language without it<h1>s, skipped heading levels (h2 → h4) — headings are how many screen reader users navigate a long page, so a broken outline breaks their primary wayfinding<main> landmark, duplicate ids, invalid ARIA rolesaria-hidden on focusable elements — keyboard focus lands on something screen readers are told doesn't exist<th>/scope)autocomplete on identity fields — WCAG 1.3.5; also what lets password managers and users with motor or cognitive disabilities fill forms reliably<fieldset>/<legend> — options with no audible question<label for> pointing at nothing, image buttons without alt texttabindex — hijacks focus order in ways that are nearly impossible to maintainuser-scalable=no) — overrides low-vision users' primary coping tool<marquee>/<blink>Every one of these is detectable in raw HTML, deterministic, and fixable in minutes once named. That's the profile of a perfect CI/scanner check.
The split is not arbitrary. Automation owns the checks with a deterministic answer in the DOM; humans own everything that requires judgment about meaning, sequence, or experience.
| Automation catches reliably | Automation cannot judge |
|---|---|
Missing or empty alt attributes | Whether the alt text actually describes the image |
| Contrast below 4.5:1 (in-browser tools, from computed styles) | Whether focus is visible against your real background |
Invalid ARIA roles/attributes, aria-hidden on focusable nodes | Whether your custom combobox behaves like a combobox |
| Inputs with no accessible name | Whether the label wording means anything to a user |
Missing lang, duplicate id, broken heading order | Whether heading order matches the visual reading order |
Positive tabindex, missing skip link | Whether tab order through a flow is sensible |
Autoplaying audio, untitled <iframe>s | Whether captions are accurate, or the page is cognitively navigable |
Two nuances worth internalizing. First, contrast is only automatable where the tool can read computed styles — a headless-browser runner like axe-core resolves the cascade and gets real numbers; static HTML analysis sees only the inline-style subset. Second, automation cannot produce a conformance claim. A VPAT, an EN 301 549 statement, or an "accessible per WCAG 2.1 AA" line in a contract requires manual testing: keyboard-only traversal, a screen reader pass (NVDA or VoiceOver), zoom to 400%, and a look at the flows that matter. "Zero axe violations" is evidence, not conformance.
Anyone selling "fully automated WCAG compliance" — particularly one-line JavaScript "overlay" widgets — is selling the impossible; overlay vendors' customers keep getting sued, and disability advocates have documented overlays making sites less usable. Treat scans as the floor: they catch the objective majority-by-volume failures on every deploy, and they free human review (one afternoon with a keyboard and a screen reader: tab through signup, checkout, and your core flow) to focus on the judgment calls automation can't make.
The right mental model: automated checks are accessibility signals, not certification. That's also why scanning beats auditing-once: an audit is a snapshot, while your templates change weekly. The unlabeled input ships back in with the next form refactor; the scanner catches it the same day.
Five tools cover almost every real setup. They overlap heavily — most of them are axe-core wearing a different coat — so pick by where it runs, not by rule count.
axe-core is Deque's open-source rules engine and the thing under the hood of most of the others. It runs inside a real browser against the rendered DOM and computed styles, so it sees your React output and resolves actual contrast ratios instead of guessing from markup. Rules are tagged (wcag2a, wcag2aa, wcag21aa, best-practice) so you can filter to exactly the level you're claiming. Deque tunes it for near-zero false positives, which is precisely why its coverage stops where judgment starts — it won't flag anything it can't prove.
Lighthouse ships in Chrome DevTools, npx lighthouse, PageSpeed Insights, and Lighthouse CI. Its Accessibility category is a curated subset of axe-core rules rolled into a weighted 0–100 score. That makes it a good smoke test and a good trend line, and a bad compliance signal: a 100 means "no failures found in this subset," which Google's own docs say out loud. Use it if you already run Lighthouse for performance budgets; don't build the program on the score.
Pa11y (and pa11y-ci) is a Node CLI that drives headless Chrome and runs either HTML_CodeSniffer or axe-core as its engine. Its edge is CI ergonomics rather than rules: a config file with a URL list or a sitemap, JSON/CI reporters, per-URL ignore rules, and an error threshold so a backlog doesn't red-light every build. Best fit when you want to sweep dozens of static URLs on a schedule without writing a test suite.
WAVE is WebAIM's browser extension and web service. It renders findings as icons overlaid on the page itself, which makes it the fastest way to show a designer or content editor what's wrong without a JSON dump. The extension evaluates whatever is in your browser, including pages behind auth, and needs no setup. It's a manual triage tool, not a CI tool — the automation path is the paid API.
@axe-core/playwright is the axe integration for Playwright (equivalents exist for Cypress and Puppeteer). It runs axe against a page you already drove — logged in, cart populated, modal open, step three of checkout. That's the only way to test states a URL crawler structurally cannot reach, and it's the integration most product teams should own. Everything else is a supplement to this.
Automating web accessibility is worth doing only if it runs without anyone remembering to run it. The pattern that works: test the deployed preview URL, not localhost, so you're checking the same build your users get, CDN and all.
Here's a complete GitHub Actions workflow that fires when a preview deploy succeeds and runs axe against it:
name: Accessibility
on:
deployment_status
jobs:
axe:
# only run once the preview deploy is actually live
if: github.event.deployment_status.state == 'success'
runs-on: ubuntu-latest
env:
PREVIEW_URL: ${{ github.event.deployment_status.environment_url }}
steps:
- uses: actions/checkout@v4
- uses: actions/setup-node@v4
with:
node-version: 20
cache: npm
- run: npm ci
- run: npx playwright install --with-deps chromium
- run: npx playwright test tests/a11y.spec.ts
- uses: actions/upload-artifact@v4
if: always()
with:
name: a11y-report
path: playwright-report/
And the test it runs. Note the withTags filter — that's where the AA decision from earlier becomes a config line:
// tests/a11y.spec.ts
import { test, expect } from '@playwright/test';
import AxeBuilder from '@axe-core/playwright';
const PATHS = ['/', '/pricing', '/signup', '/contact'];
for (const path of PATHS) {
test(`no WCAG AA violations on ${path}`, async ({ page }) => {
await page.goto(new URL(path, process.env.PREVIEW_URL).toString());
const { violations } = await new AxeBuilder({ page })
.withTags(['wcag2a', 'wcag2aa', 'wcag21a', 'wcag21aa'])
.analyze();
const summary = violations.map(
(v) => `${v.id} (${v.impact}) x${v.nodes.length}: ${v.help}`
);
expect(summary, summary.join('\n')).toEqual([]);
});
}
The summary trick matters more than it looks: a raw axe failure prints an unreadable object graph, while this puts the rule id, impact, and node count straight into the CI log so whoever broke it can fix it without opening an artifact.
If you'd rather not own a test suite, pa11y-ci gets you most of the way with a config file:
{
"defaults": {
"standard": "WCAG2AA",
"runners": ["axe"],
"timeout": 30000,
"threshold": 0,
"chromeLaunchConfig": { "args": ["--no-sandbox"] }
},
"urls": [
"https://preview-abc123.vercel.app/",
"https://preview-abc123.vercel.app/pricing",
"https://preview-abc123.vercel.app/signup"
]
}
# explicit URL list
npx pa11y-ci --config .pa11yci.json
# or crawl everything you've told Google about
npx pa11y-ci --sitemap https://example.com/sitemap.xml --sitemap-exclude "/blog/"
Three things that decide whether this survives contact with a real team:
threshold (pa11y-ci) or snapshot the current violation ids and fail only on additions, then burn the list down on purpose.Accessibility failures live in templates, but not only in the homepage template. Forms hide on contact and signup pages, tables on pricing pages, iframes on docs pages. A scan that samples interior pages — not just / — catches the template classes a homepage-only check structurally can't see.
The accessibility check is the eighth pillar in a CheckVibe scan, alongside security, SEO, and performance:
Accessibility issues also feed the compliance check's EAA-relevant signals, since "is the site accessible" is now a legal-exposure question, not just a quality one.
Run a free scan — if your forms are labeled and your headings are sane, you'll know in a minute. If they aren't, you'll know exactly where.
No. Deque's research puts automated detection at roughly 57% of accessibility issues — the objective ones: missing labels, alt attributes, lang, broken heading structure, invalid ARIA. Judgment calls (alt-text quality, focus order, screen-reader flow comprehensibility, cognitive load) need a human with a keyboard and a screen reader. Automation's job is catching that objective half continuously, so human review stays rare, focused, and affordable.
WCAG is the W3C's accessibility standard; 2.1/2.2 are versions and A/AA/AAA are conformance levels. Level AA is the benchmark referenced by most laws and contracts — including the EU's EN 301 549 standard underlying the European Accessibility Act — covering things like text alternatives, labels, keyboard operability, contrast, and consistent navigation.
Level AA, on WCAG 2.1 or 2.2. It's what EN 301 549 references for the European Accessibility Act, what US ADA settlements and Section 508 procurement name, and what enterprise VPATs ask you to attest to. Level A is too low to satisfy anyone; AAA contains criteria the W3C says cannot be met for all content. Configure axe with the wcag21aa tag or Pa11y with WCAG2AA and stop debating it.
On every pull request, against the deployed preview URL rather than localhost — plus a scheduled run against production, weekly is plenty. CI catches regressions in code you changed; the scheduled run catches what your CMS, your marketing team, and third-party embeds changed without a deploy. Manual keyboard and screen-reader passes cost far more, so do those quarterly and after any redesign of a core flow.
If you sell e-commerce or covered digital services to consumers in the EU, very likely yes — it has applied since June 28, 2025, regardless of where your company is based. Microenterprises (under 10 staff and under €2M turnover) have a service exemption, but their B2B customers increasingly demand conformance anyway. Member states enforce with fines; the practical baseline is WCAG 2.1 AA.
Year after year, WebAIM's million-site survey finds the same five: low-contrast text, images without alt text, form inputs without labels, empty links, and missing document language. Four of the five are trivially machine-detectable and typically one-line fixes — which is what makes shipping them in 2026 so unnecessary.
No. One-line overlay widgets cannot fix markup-level failures (they read the same broken DOM), they frequently interfere with users' own assistive technology, and companies using them continue to receive ADA demand letters — some lawsuits now cite the overlay itself. Fix the markup; it's less work than it sounds.
Paste your URL and get a security report in 30 seconds — 100+ automated checks with AI-ready fix prompts.
Related articles
The questions enterprise buyers actually send small vendors, how to answer honestly when the answer is no, and what to prepare before the first one.
What a SOC 2 auditor actually asks a five-person engineering team for, which controls you can evidence automatically, and which ones need a human.
How to set remediation deadlines by severity, when the clock should start, and why measuring from triage instead of detection inflates every number.