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.
75
94%
Does it follow best practices?
Run evals on this skill
Adds up to 20 points to the overall score
View guide
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.