wave-a11y
Runs WebAIM WAVE accessibility scans via the WAVE API or the browser-extension UI - produces visual overlay of errors / alerts / structural elements directly on the page, plus categorized JSON output for CI use. Use when the team values manual-review-friendly visual feedback (the WAVE overlay) alongside automated CI scans, or when a regulatory audit requires WebAIM-branded reports.
wave-a11y
Overview
WAVE (Web Accessibility Evaluation Tool) is WebAIM's flagship a11y scanner - distinguished by its visual overlay that places icons directly on a rendered page showing errors, alerts, and structural elements. It runs via:
The WAVE convention is to categorize findings into: errors (definite WCAG failures), alerts (likely issues needing review), features (positive a11y patterns to celebrate), structural elements (landmarks, headings), HTML5 / ARIA (machine-readable semantics), contrast errors (color contrast specifically).
Source-fetch note (2026-05-04): WAVE's documentation lives across
wave.webaim.org,webaim.org/articles, and tool- specific subpages. This skill cites WebAIM as the canonical source for WAVE conventions; the API specifics may evolve - verify the current WAVE API v3+ documentation atwave.webaim.org/apibefore authoring CI integrations against specific endpoints.
When to use
If the goal is purely automated CI gating without visual review, axe-a11y and pa11y-a11y are simpler and free.
Install / access
| Method | Cost |
|---|---|
| Browser extension (Chrome / Firefox / Edge) | Free. |
| WAVE API | Free credits + paid tiers (per WebAIM). |
| Stand-Alone API (self-hosted server) | Commercial license. |
For programmatic CI integration, the WAVE API is the canonical path; pricing / signup at wave.webaim.org/api.
Manual usage (extension)
The visual feedback is the WAVE differentiator - designers can review without reading text reports.
Programmatic usage (API)
curl 'https://wave.webaim.org/api/request?key=YOUR_KEY&url=https://example.com&reporttype=4'Reporttype 4 returns the full JSON. The response includes:
{
"status": { "success": true, "httpstatuscode": 200 },
"statistics": {
"pagetitle": "Example",
"pageurl": "https://example.com/",
"totalelements": 423,
"allitemcount": 12,
"errorcount": 3,
"alertcount": 5,
"featurecount": 4,
...
},
"categories": {
"error": { "items": { ... } },
"alert": { "items": { ... } },
"feature": { ... },
"structure": { ... },
"html5": { ... },
"contrast": { "items": { ... } }
}
}Per category, items is keyed by the WAVE issue code (e.g. alt_missing, label_missing, contrast); each entry has description, count, selectors[], and per-instance xpath / selector / html.
Pipe to jq for triage:
# All error-level codes + counts
jq -r '.categories.error.items | to_entries[] | "\(.key): \(.value.count)"' wave-results.json
# Failing selectors per issue
jq -r '.categories.error.items | to_entries[] | .value.selectors[] | tostring' wave-results.jsonCI integration
The CI pattern uses the WAVE API:
# .github/workflows/wave.yml
name: wave-a11y
on:
pull_request:
paths: ['src/**']
jobs:
wave:
runs-on: ubuntu-latest
steps:
- uses: actions/checkout@v5
- name: Run WAVE scan via API
env:
WAVE_API_KEY: ${{ secrets.WAVE_API_KEY }}
run: |
# Scan each URL the project cares about
for url in https://staging.example.com/ https://staging.example.com/dashboard; do
slug=$(echo "$url" | tr '/:' '__')
curl -sS "https://wave.webaim.org/api/request?key=$WAVE_API_KEY&url=$url&reporttype=4" \
> "wave-$slug.json"
done
- name: Upload reports
if: always()
uses: actions/upload-artifact@v4
with:
name: wave-reports
path: wave-*.json
retention-days: 14
- name: Gate via violation-gate
run: python scripts/run_a11y_gate.py wave-*.jsonThe gate logic lives in a11y-violation-gate; this CI workflow's job is to capture the WAVE outputs.
Anti-patterns
| Anti-pattern | Why it fails | Fix |
|---|---|---|
| Treating "alerts" as errors | Alerts are flagged for human review, not auto-fail. | Block on errors; route alerts to the review process. |
| Storing WAVE API key in committed config | Key leak; quota theft. | Always in CI secrets. |
| Running WAVE against production | API hits load production; possible PII leakage in scan data. | Always staging or pre-prod. |
| Using WAVE alone without axe / pa11y | WAVE has different rule coverage; misses some structural / ARIA issues. | Pair with axe-a11y for full coverage. |
| Ignoring "contrast errors" because they're "not real bugs" | Contrast errors are SC 1.4.3 violations - definite WCAG failures. | Treat as errors; aggregate via gate. |