WCAG Scanner is a powerful accessibility testing tool that helps developers identify and fix accessibility issues on their websites according to Web Content Accessibility Guidelines (WCAG). It performs automated checks against WCAG 2.1 standards and provides actionable recommendations to improve web accessibility.
- WCAG 2.1 Compliance Scanning: Checks against A, AA, and AAA conformance levels
- Fast and Full Presets: Default fast scans plus optional heavier rules like
backgroundImages - React Dev Overlay: Live in-browser inspector with element highlighting, pinning, and impact filtering
- AI Fix Suggestions: Paste your Gemini API key in the overlay settings to get instant fix suggestions per violation
- Programmatic API: Scan HTML strings or local files from Node.js
- Express Middleware: Auto-scan responses in your Express app
- Multiple Report Formats: JSON, HTML, and console output
# npm
npm install wcag-scanner
# yarn
yarn add wcag-scanner
# pnpm
pnpm add wcag-scannerReact users: React and React DOM are peer dependencies already in your project β no extra install needed.
The easiest way to use wcag-scanner in a React app. Add one line to your entry file and a live accessibility inspector appears in the corner of your browser during development.
// main.ts / main.jsx / index.tsx β works with any file type
import { initWcagOverlay } from 'wcag-scanner/react';
initWcagOverlay(); // auto-disabled in productionOptions:
initWcagOverlay({
level: 'AA', // 'A' | 'AA' | 'AAA' β default: 'AA'
preset: 'fast', // 'fast' | 'full' β default: 'fast'
position: 'bottom-right', // 'bottom-right' | 'bottom-left'
debounce: 750, // ms to wait after DOM change before rescanning
rules: ['images', 'backgroundImages', 'contrast'], // explicit rules override preset
});preset: 'full' includes the heavier optional checks such as backgroundImages. Use rules when you want an exact rule list.
Preset Contents
| Preset | Rules included |
|---|---|
fast |
images, contrast, forms, aria, structure, keyboard |
full |
images, contrast, forms, aria, structure, keyboard, backgroundImages |
You can also import these programmatically:
import { RULE_PRESETS, resolveRuleNames } from 'wcag-scanner';
console.log(RULE_PRESETS.fast);
console.log(resolveRuleNames({ preset: 'full' }));Features:
- Hover over a violation to highlight the element on the page
- Click to pin the highlight; click again to unpin
- Expand any violation card for the HTML snippet, element path, WCAG criteria, and fix hint
- Filter by impact level (critical / serious / moderate / minor)
- Drag the panel anywhere on screen
- Keyboard shortcut
Alt+Shift+Wto toggle open/close - β Settings β paste a free Google Gemini API key to get AI-powered fix suggestions per violation
The overlay never runs in production (
NODE_ENV=production) and is never included in your production bundle.
Scan HTML strings or local files from Node.js scripts, CI pipelines, or build tools.
import { scanHtml, scanFile, formatReport, saveReport } from 'wcag-scanner';
// Scan an HTML string
const results = await scanHtml('<img src="logo.png">', { level: 'AA', preset: 'fast' });
console.log(`${results.violations.length} violations found`);
// Scan a local HTML file
const results = await scanFile('./public/index.html', { level: 'AA', preset: 'full' });
// Run an exact subset of rules
const targeted = await scanHtml('<div style="background-image:url(hero.jpg)"></div>', {
rules: ['images', 'backgroundImages'],
});
// Or resolve a built-in preset yourself
// import { RULE_PRESETS } from 'wcag-scanner';
// const results = await scanHtml(html, { rules: RULE_PRESETS.full });
// Generate and save a report
const html = formatReport(results, 'html'); // 'html' | 'json' | 'console'
saveReport(html, 'accessibility-report.html');Automatically scan every HTML response in your Express app and inject a violation badge.
import express from 'express';
import { middleware } from 'wcag-scanner';
const app = express();
app.use(middleware.express.createMiddleware({
enabled: true,
level: 'AA',
preset: 'fast',
headerName: 'X-WCAG-Violations', // violation count added to response headers
inlineReport: true, // inject a small widget into the HTML response
onViolation: (results, req) => {
console.log(`${results.violations.length} issues on ${req.path}`);
},
}));
// Switch to preset: 'full' if you also want heavier checks like backgroundImages.
app.get('/', (req, res) => {
res.send(`<!DOCTYPE html><html><body><h1>Hello</h1></body></html>`);
});
app.listen(3000);Current local synthetic benchmark baseline from the repo profiling scripts:
| Rule | Command | Approx. duration |
|---|---|---|
images |
npm run profile:images |
128ms |
forms |
npm run profile:forms |
484ms |
aria |
npm run profile:aria |
398ms |
contrast |
npm run profile:contrast |
1836ms |
Notes:
- These are synthetic local benchmarks, not production browser traces.
contrastis currently the main runtime hotspot.backgroundImagesis intentionally excluded from the defaultfastpreset because it is a heavier optional check.
