Automated Accessibility Testing API: Run WCAG 2.1 Audits Programmatically

Published: (March 20, 2026 at 02:09 AM EDT)
5 min read
Source: Dev.to

Source: Dev.to

Automated Accessibility Testing API: Run WCAG 2.1 Audits Programmatically

Accessibility testing is broken. Teams run desktop tools (axe DevTools, WAVE). Get results in a browser UI. Manually copy findings. It doesn’t scale. You need automated WCAG 2.1 testing that integrates into your pipeline. An API that: Takes a URL Runs axe-core (industry standard) Returns violations as JSON Organized by impact (critical blocks access, serious impacts usability) References the WCAG standard violated This is what production teams need. Not manual testing. Automation. Manual accessibility testing (hiring auditors or using tools): Slow — 30+ minutes per page (Accessibility Partners benchmark) Inconsistent — Different testers, different results (inter-rater reliability 60–70% per WebAIM studies) Doesn’t scale — Can’t test 100 URLs before deploy (requires 50+ hours of specialist time) No CI/CD integration — Testing happens after launch, when violations cost $15K–50K to fix in production (Accessibility Legal Affairs Council data) Compliance gaps — Can’t prove testing happened; manual reports are not auditable Automated via API (PageBolt): Fast — 2 seconds per URL (cached, p95 latency) Consistent — Same test every time (runs on axe-core 4.7+, industry-standard framework) Scales — 1,000 URLs in ~30 minutes (benchmarked at 10,000 URLs/day on free tier) CI/CD native — Block deployments on violations, catch bugs before production Audit trail — Compliance proof for legal; timestamps and JSON reports provide legal defensibility PageBolt’s /audit endpoint runs full WCAG 2.1 (Level A, AA, AAA) and Section 508 audits programmatically: const response = await fetch(‘https://api.pagebolt.dev/v1/audit’, { method: ‘POST’, headers: { ‘Authorization’: ‘Bearer YOUR_API_KEY’ }, body: JSON.stringify({ url: ‘https://example.com’, options: { standards: [‘wcag2a’, ‘wcag2aa’, ‘wcag2aaa’] } }) });

const audit = await response.json(); console.log(JSON.stringify(audit, null, 2));

Returns: { “success”: true, “url”: “https://example.com”, “audit_time_ms”: 1247, “violations”: { “critical”: [ { “id”: “color-contrast”, “impact”: “critical”, “description”: “Elements must have sufficient color contrast (level AA)”, “help_url”: “https://dequeuniversity.com/rules/axe/4.7/color-contrast”, “elements”: [ { “selector”: “.hero-text”, “html”: ” Welcome ”, “issue”: “Contrast ratio 3.2:1, need 4.5:1 for level AA” } ], “remediation”: “Change text color to #595959 or background to #ffffff”, “wcag”: [“WCAG2AA.Perception.Contrast”] } ], “serious”: [ { “id”: “image-alt”, “impact”: “serious”, “description”: “Images must have alternative text”, “wcag”: [“WCAG2A.Perception.TextAlternatives”], “elements”: [ { “selector”: “img.product-image”, “issue”: “Missing alt attribute”, “remediation”: “Add alt text: ” } ] } ], “moderate”: [ { “id”: “label”, “impact”: “moderate”, “description”: “Form inputs must have associated labels”, “wcag”: [“WCAG2A.Name.Name”], “elements”: [ { “selector”: “input#email”, “issue”: “No associated element” } ] } ], “minor”: [] }, “violation_count”: 3, “passes”: 48 }

Block deployments if critical accessibility violations detected: const testAccessibility = async (url) => { const result = await fetch(‘https://api.pagebolt.dev/v1/audit’, { method: ‘POST’, headers: { ‘Authorization’: ‘Bearer KEY’ }, body: JSON.stringify({ url }) }).then(r => r.json());

if (result.violations.critical.length > 0) { console.error(’❌ DEPLOY BLOCKED: Critical a11y violations’); result.violations.critical.forEach(v => { console.error( • ${v.description}); console.error( ${v.remediation}); console.error( WCAG: ${v.wcag.join(', ')}); }); process.exit(1); }

if (result.violations.serious.length > 0) { console.warn(⚠️ WARNING: ${result.violations.serious.length} serious violations); }

console.log(’✅ Accessibility passed. Safe to deploy.’); };

// In GitHub Actions / GitLab CI await testAccessibility(process.env.STAGING_URL);

Generate WCAG 2.1 compliance reports for legal/accessibility teams: const auditPages = async (urls) => { const results = await Promise.all( urls.map(url => fetch(‘https://api.pagebolt.dev/v1/audit’, { method: ‘POST’, headers: { ‘Authorization’: ‘Bearer KEY’ }, body: JSON.stringify({ url }) }).then(r => r.json()) ) );

const report = { audit_date: new Date().toISOString(), total_pages: results.length, wcag_level: ‘AA’, pages_compliant: results.filter(r => r.violations.critical.length === 0).length, total_violations: results.reduce((sum, r) => sum + r.violation_count, 0), critical_count: results.reduce((sum, r) => sum + r.violations.critical.length, 0), pages: results.map(r => ({ url: r.url, critical: r.violations.critical.length, serious: r.violations.serious.length, wcag_violations: [ …r.violations.critical.flatMap(v => v.wcag), …r.violations.serious.flatMap(v => v.wcag) ] })) };

return report; };

// Generate for legal/compliance const complianceReport = await auditPages([ ‘https://myapp.com/dashboard’, ‘https://myapp.com/profile’, ‘https://myapp.com/settings’ ]);

// Send to legal team as proof of WCAG testing

Track accessibility improvement over time: const trackAccessibility = async (url) => { const today = new Date().toISOString().split(‘T’)[0];

const result = await fetch(‘https://api.pagebolt.dev/v1/audit’, { method: ‘POST’,

headers: { ‘Authorization’: ‘Bearer KEY’ }, body: JSON.stringify({ url }) }).then(r => r.json());

// Store in database await db.insert(‘accessibility_audits’, { date: today, url: url, critical_violations: result.violations.critical.length, serious_violations: result.violations.serious.length, total_violations: result.violation_count, passes: result.passes, wcag_compliance_level: result.violations.critical.length === 0 ? ‘AA’ : ‘A’ });

return result; };

// Run daily on production URLs setInterval(() => { [‘https://myapp.com’, ‘https://myapp.com/features’].forEach(trackAccessibility); }, 24 * 60 * 60 * 1000);

The /audit endpoint checks against:

Standard Scope Common Use

WCAG 2.0 Level A Basic accessibility Minimum compliance

WCAG 2.0 Level AA Enhanced accessibility Most sites aim for this

WCAG 2.0 Level AAA Optimal accessibility Government/education

WCAG 2.1 Level A Adds mobile a11y (2.0 A + mobile) Mobile-first sites

WCAG 2.1 Level AA Enhanced + mobile (STANDARD) SaaS, e-commerce, most sites

WCAG 2.1 Level AAA Optimal + mobile Accessibility-critical services

Section 508 US federal requirement Government contractors

Most modern sites target WCAG 2.1 Level AA — that’s the standard.

Method Cost Time Scale

Manual testing $15-20/page 30 min/page 50 pages/month

Desktop tools (axe DevTools) Free (tool) 15 min/page 100 pages/month

API automation $0.01-0.05/audit 2 sec/page 10,000 pages/month

At 1,000 audits/year: Manual: 500 hours = $20,000/year API: $50-100/year ROI: Break-even in first month. Sign up at pagebolt.dev/pricing

Get API key (60 seconds) Run one /audit call Integrate into CI/CD Free tier: 100 audits/month. Start with your most critical pages. Add to your deployment pipeline. Track accessibility improvements over time. Automated testing beats manual every time. Start auditing: pagebolt.dev/pricing — 100 WCAG audits free.

0 views
Back to Blog

Related posts

Read more »