Accessibility Testing with WAVE
WAVE (Web Accessibility Evaluation Tool) from WebAIM is a visual tool for checking accessibility. It overlays icons directly on the page, showing where errors are located. It can be used via browser extension, web interface at wave.webaim.org, or REST API for automation.
WAVE API for Automation
# Basic request
curl "https://wave.webaim.org/api/request?key=YOUR_KEY&url=https://example.com&reporttype=4&format=json"
// scripts/wave-audit.js
const axios = require('axios');
const fs = require('fs');
const WAVE_API_KEY = process.env.WAVE_API_KEY;
const BASE_URL = 'https://wave.webaim.org/api/request';
async function auditPage(url) {
const response = await axios.get(BASE_URL, {
params: {
key: WAVE_API_KEY,
url: url,
reporttype: 4, // 1=summary, 2=summary+items, 3=+structure, 4=+screenshots
format: 'json',
},
});
return response.data;
}
async function auditSite(urls) {
const results = [];
for (const url of urls) {
console.log(`WAVE: ${url}`);
const data = await auditPage(url);
results.push({
url,
errors: data.categories.error.count,
alerts: data.categories.alert.count,
features: data.categories.feature.count,
structure: data.categories.structure.count,
aria: data.categories.aria.count,
contrast_errors: data.categories.contrast.count,
// Details by type
error_items: Object.values(data.categories.error.items || {}),
});
// WAVE API: 500 requests/month free tier, pause between requests
await new Promise(r => setTimeout(r, 1000));
}
// Generate HTML report
generateHtmlReport(results);
return results;
}
function generateHtmlReport(results) {
const total_errors = results.reduce((s, r) => s + r.errors, 0);
const html = `
<!DOCTYPE html>
<html lang="en">
<head><meta charset="UTF-8"><title>WAVE Accessibility Report</title></head>
<body>
<h1>WAVE Accessibility Report</h1>
<p>Date: ${new Date().toLocaleDateString('en-US')} | Total Errors: ${total_errors}</p>
<table border="1" cellpadding="8">
<tr><th>URL</th><th>Errors</th><th>Alerts</th><th>Contrast</th><th>ARIA</th></tr>
${results.map(r => `
<tr style="background: ${r.errors > 0 ? '#fee2e2' : '#f0fdf4'}">
<td>${r.url}</td>
<td><b>${r.errors}</b></td>
<td>${r.alerts}</td>
<td>${r.contrast_errors}</td>
<td>${r.aria}</td>
</tr>
`).join('')}
</table>
</body>
</html>`;
fs.writeFileSync('wave-report.html', html);
}
Problem Categories in WAVE Reports
| Category | Icon | Description |
|---|---|---|
| Errors | Red circle | WCAG violations, block access |
| Alerts | Yellow triangle | Potential issues to review |
| Features | Green circle | Positive accessibility elements |
| Structural Elements | Blue icons | Headings, landmarks, lists |
| ARIA | Purple | ARIA role/label/descriptions |
| Contrast Errors | Orange | Insufficient color contrast |
Browser Extension
WAVE Extension for Chrome/Firefox doesn't require an API key and is good for manual checking of authenticated pages — the extension works in the current browser session with user cookies.
// Cannot automate extension directly,
// but can combine: Pa11y/axe for CI, WAVE Extension for manual audit
Workflow Integration
# .github/workflows/accessibility.yml
- name: WAVE API Audit
env:
WAVE_API_KEY: ${{ secrets.WAVE_API_KEY }}
run: |
node scripts/wave-audit.js
# Publish report as artifact
- uses: actions/upload-artifact@v3
with:
name: wave-report
path: wave-report.html
Timeline
Setting up WAVE API audit with HTML report and CI integration: 1–2 business days.







