wcag-audit loads a URL in headless Chromium, runs axe-core against WCAG 2.1 A, AA or AAA, and gives you a score, a ranked to-do list and an exit code your pipeline can act on. It is the open-source engine inside Alfa Audit.
Node.js 20 or newer. There is no postinstall hook on purpose; install Chromium once yourself.
# one-off
npx @belikenikola/wcag-audit https://example.com
# or install globally
npm install -g @belikenikola/wcag-audit
npx playwright install chromium # Chromium is needed once (~150-300 MB)
wcag-audit https://example.com --level AA --format html -o report.htmlwcag-audit <url> [options]
-l, --level <level> WCAG conformance level: A, AA, or AAA (default: AA)
-f, --format <fmt> Output format: json, html, or md (default: json)
-o, --output <path> Output file path (default: auto)
-t, --timeout <ms> Page load timeout in milliseconds (default: 30000)
-v, --verbose Verbose loggingA score and the counts
A 0-100 accessibility score weighted by impact, plus violations, instances, items needing manual review, and passes.
A prioritized to-do list
Each item has a priority (impact x effort), the remediation task, the WCAG success criteria, the number of affected nodes and an effort estimate.
Full violation detail
Rule id, description, impact, WCAG tags, the affected elements with selectors and HTML, and a link to the axe rule documentation.
Three formats
JSON for pipelines, HTML to send to a stakeholder, Markdown to paste into an issue.
The CLI exits 1 whenever it finds any violation, which is too strict for most teams. Let it write JSON, then decide your own threshold. This GitHub Actions job fails only on critical or serious impact and keeps the full report as an artifact.
name: accessibility
on: [pull_request]
jobs:
wcag:
runs-on: ubuntu-latest
steps:
- uses: actions/setup-node@v4
with: { node-version: 20 }
- run: npx playwright install --with-deps chromium
# exit 1 just means "violations found" - decide the threshold yourself below
- run: npx @belikenikola/wcag-audit "${{ vars.PREVIEW_URL }}" --format json -o report.json || true
- name: Fail on critical or serious violations
run: |
node -e '
const r = require("./report.json");
const bad = r.violations.filter(v => ["critical","serious"].includes(v.impact));
console.log("score " + r.summary.score + "/100, " + r.violations.length + " violations, " + bad.length + " critical/serious");
for (const v of bad) console.log(" - " + v.id + " (" + v.impact + "): " + v.help);
process.exit(bad.length ? 1 : 0);
'
- uses: actions/upload-artifact@v4
if: always()
with: { name: wcag-report, path: report.json }| Code | Meaning |
|---|---|
| 0 | Audit ran, no violations found |
| 1 | Audit ran, violations found (the report has them) |
| 2 | URL requires authentication; nothing audited |
| 3 | Invalid input (URL or options) |
| 4 | Unexpected error |
The package root exports the same functions the CLI is built on.
import { runAudit, buildTodoList, generateReport, shutdown } from '@belikenikola/wcag-audit';
const result = await runAudit('https://example.com', { level: 'AA', timeout: 30000 });
if (result.success) {
console.log(result.summary.score); // 0-100
const todos = buildTodoList(result.violations); // ranked by impact x effort
const html = generateReport(result, 'html'); // or 'json' | 'md'
}
if (result.requiresAuth) console.log('login wall:', result.authReason);
await shutdown();Inject your own browser launcher so you do not have to ship full Playwright. This is exactly how Alfa Audit runs it inside a Vercel function.
import { setBrowserLauncher, runAudit, shutdown } from '@belikenikola/wcag-audit';
import { chromium } from 'playwright-core';
import chromiumBin from '@sparticuz/chromium';
// Ship playwright-core + a Lambda-sized Chromium instead of full Playwright.
setBrowserLauncher(async () =>
chromium.launch({
args: chromiumBin.args,
executablePath: await chromiumBin.executablePath(),
headless: true,
})
);
const result = await runAudit('https://example.com');
await shutdown();Alfa Audit is this engine with a dashboard: add sites, schedule weekly re-audits, track the score over time, export PDF, and share a public report or badge. Free to start. The CLI stays free and open source either way.