Automated accessibility scanning across the five engines - axe-core (primary), pa11y, Lighthouse a11y, WAVE, and IBM Equal Access. Authors and runs axe-core scans via the `axe.run()` JavaScript API or the @axe-core/playwright / @axe-core/cli wrappers, parses `violations[]` into per-rule severity, configures rule disable / disable-by-tag patterns, and emits CI-gateable output; references/ carry the pa11y CLI (htmlcs + axe runners), Lighthouse CI `categories:accessibility` assertions, the WAVE API / overlay, and IBM Equal Access (Section 508) with their verified CLI / API / config. Use for any automated a11y scanner setup - axe-core for JS/TS UI test suites on every PR, and the references for CLI-only, Lighthouse-pipeline, WebAIM-branded, or Section 508 scanning.
72
91%
Does it follow best practices?
Run evals on this skill
Adds up to 20 points to the overall score
Passed
No findings from the security scan
Companion reference for axe-a11y. Consult when the project needs scriptable
a11y scans without a full test framework (CI cron job, docs publication,
static-site CI), or when a Node-stack project wants a single-command scanner
instead of framework-integrated axe tests.
pa11y is "your automated accessibility testing pal" - a Node.js CLI that runs a11y tests on a page via the command line or a programmatic API (pa11y). It can use HTML CodeSniffer (htmlcs, default) or axe-core as the underlying engine. If the project already runs Playwright / Cypress with axe-core, prefer the direct axe integration in SKILL.md - pa11y adds a layer.
npm install -g pa11y # or --save-dev per-project
pa11y https://example.com(Per pa11y.)
| Flag | Effect |
|---|---|
--reporter <name> | Output format: cli (default), csv, json, html, tsv. |
--standard <name> | WCAG standard: WCAG2A, WCAG2AA (default), WCAG2AAA. |
--runner <name> | Engine: htmlcs (default) or axe; repeat to run both. |
--include-warnings | Include warning-level issues (excluded by default). |
--include-notices | Include notice-level issues. |
--ignore <rules> | Skip specific rules (comma-separated). |
--threshold <n> | Allow up to N issues before failing (exit-code gate). |
--timeout <ms> | Page-load timeout. |
--config <file> | Use a .pa11yrc config file. |
pa11y's WCAG2AA standard is 2.0/2.1; WCAG 2.2 SCs (2.4.11, etc.) need
--runner axe alongside htmlcs.
pa11y-ci (https://github.com/pa11y/pa11y-ci) batches a URL set from a
.pa11yci config and exits non-zero if any URL exceeds threshold - the
canonical CI gate signal:
{
"defaults": {
"standard": "WCAG2AA",
"runners": ["axe", "htmlcs"],
"includeWarnings": true,
"threshold": 0
},
"urls": [
"https://staging.example.com/",
"https://staging.example.com/dashboard",
"https://staging.example.com/checkout"
]
}const pa11y = require('pa11y');
const results = await pa11y('https://example.com', {
standard: 'WCAG2AA',
runners: ['axe', 'htmlcs'],
includeWarnings: true,
});
console.log(results.issues);results.issues[] holds one object per finding with code, type
(error / warning / notice), typeCode, selector, context, message, and
runner. When both engines run, the same defect appears twice under
different codes - WCAG-SC-coded from htmlcs
(WCAG2AA.Principle1.Guideline1_4.1_4_3.G18.Fail), rule-coded from axe
(color-contrast) - and a11y-violation-gate collapses the pair via its
fingerprint field.
pa11y --standard WCAG2AA \
--runner htmlcs --runner axe \
--include-warnings \
--reporter json \
--threshold 0 \
https://staging.example.com/checkout > pa11y-results.jsonThe run exits non-zero (threshold 0 exceeded) and pa11y-results.json holds
the issues[] array for the gate.
| Anti-pattern | Why it fails | Fix |
|---|---|---|
Default WCAG2AA without WCAG 2.2 specifics | The htmlcs standard is 2.0/2.1; 2.2 SCs need the axe runner. | Always include --runner axe. |
| Threshold 0 on a project with debt | Every PR fails until the entire backlog is fixed. | Use a11y-violation-gate ratchet OR raise threshold incrementally. |
| Running only htmlcs | Different rule coverage than axe; misses issues. | Run both runners; deduplicate at the gate. |
| Ignoring rules without config comments | Lost institutional knowledge. | Inline justification + quarterly review. |
load event; SPAs may need --wait-for-selector before scanning.