Accessibility Testing with Lighthouse
Lighthouse is Google's tool for auditing web application quality: performance, accessibility, SEO, best practices. The accessibility score (0–100) is based on axe-core and covers WCAG 2.1 AA. It runs via CLI, Chrome DevTools, or Node.js API.
Lighthouse CLI
npm install -g lighthouse
# Basic audit
lighthouse https://example.com --only-categories=accessibility --output=json --output-path=report.json
# Headless audit
lighthouse https://example.com \
--chrome-flags="--headless --no-sandbox" \
--only-categories=accessibility \
--output=html,json \
--output-path=./reports/lighthouse
Node.js API for Batch Audit
// scripts/lighthouse-audit.js
const lighthouse = require('lighthouse');
const chromeLauncher = require('chrome-launcher');
const fs = require('fs');
const PAGES = [
{ url: 'http://localhost:3000', name: 'Homepage' },
{ url: 'http://localhost:3000/catalog', name: 'Catalog' },
{ url: 'http://localhost:3000/product/1', name: 'Product Card' },
{ url: 'http://localhost:3000/checkout', name: 'Checkout' },
];
async function runAudit() {
const chrome = await chromeLauncher.launch({
chromeFlags: ['--headless', '--no-sandbox', '--disable-gpu'],
});
const results = [];
try {
for (const page of PAGES) {
const runnerResult = await lighthouse(page.url, {
port: chrome.port,
onlyCategories: ['accessibility'],
formFactor: 'desktop',
throttling: { cpuSlowdownMultiplier: 1 },
screenEmulation: { disabled: true },
});
const score = runnerResult.lhr.categories.accessibility.score * 100;
const audits = runnerResult.lhr.audits;
// Collect only failing checks
const failures = Object.values(audits)
.filter(a => a.score !== null && a.score < 1 && a.score >= 0)
.map(a => ({ id: a.id, title: a.title, score: a.score }));
results.push({ ...page, score, failures });
console.log(`${page.name}: ${score}/100`);
}
} finally {
await chrome.kill();
}
// Generate summary
const minScore = Math.min(...results.map(r => r.score));
console.log(`\nMinimum score: ${minScore}/100`);
fs.writeFileSync('lighthouse-summary.json', JSON.stringify(results, null, 2));
// Exit if score below threshold
if (minScore < 90) {
console.error('Accessibility below threshold 90!');
process.exit(1);
}
}
runAudit().catch(console.error);
Key Accessibility Checks in Lighthouse
| Audit ID | Description | Impact on Score |
|---|---|---|
color-contrast |
Text contrast (4.5:1 for AA) | High |
image-alt |
Alt attribute on images | High |
button-name |
Buttons with accessible name | High |
label |
Form fields linked with label | High |
heading-order |
Correct heading hierarchy | Medium |
link-name |
Links with meaningful text | Medium |
html-has-lang |
Lang attribute on html element | Low |
aria-* |
ARIA attribute correctness | Varies |
GitHub Actions Integration
# .github/workflows/lighthouse.yml
name: Lighthouse Accessibility
on: [pull_request]
jobs:
lighthouse:
runs-on: ubuntu-latest
steps:
- uses: actions/checkout@v4
- name: Run Lighthouse CI
uses: treosh/lighthouse-ci-action@v10
with:
urls: |
http://localhost:3000
http://localhost:3000/catalog
budgetPath: ./lighthouse-budget.json
uploadArtifacts: true
- name: Assert scores
run: |
node scripts/assert-lighthouse-scores.js
// lighthouse-budget.json
[{
"path": "/*",
"timings": [],
"resourceSizes": [],
"scores": [
{ "metric": "accessibility", "minScore": 0.9 }
]
}]
Timeline
Setting up Lighthouse audit with budgets and CI integration: 1–2 business days.







