A comprehensive Python library for checking HTML content against WCAG 2.2 accessibility guidelines.
- Full WCAG 2.2 Coverage: Checks against all 4 principles (Perceivable, Operable, Understandable, Robust) and 86+ success criteria
- Multiple Conformance Levels: Target Level A, AA, or AAA compliance
- Flexible Input: Check HTML strings or files
- Detailed Reports: Generate reports in Text, JSON, HTML, or Markdown format
- Actionable Feedback: Each issue includes recommendations and technique references
pip install wcag-checkerOr install from source:
git clone https://github.com/yourusername/wcag-checker
cd wcag-checker
pip install -e .from wcag_checker import WCAGChecker, ConformanceLevel
# Create a checker
checker = WCAGChecker(level=ConformanceLevel.AA)
# Check HTML content
html = """
<!DOCTYPE html>
<html>
<body>
<img src="logo.png">
<a href="page.html">Click here</a>
</body>
</html>
"""
result = checker.check(html)
# View summary
print(result.summary())
# Iterate through issues
for issue in result.issues:
print(f"[{issue.level.value}] {issue.criterion.id}: {issue.message}")The main class for checking HTML content.
from wcag_checker import WCAGChecker, ConformanceLevel
checker = WCAGChecker(
level=ConformanceLevel.AA, # Target conformance level (A, AA, or AAA)
include_notices=True, # Include informational notices
enabled_criteria=None, # Only run specific criteria (set of IDs)
disabled_criteria=None, # Skip specific criteria (set of IDs)
)
# Check HTML string
result = checker.check(html_string)
# Check HTML file
result = checker.check_file("path/to/file.html")Contains the results of an accessibility check.
result = checker.check(html)
# Properties
result.issues # List of Issue objects
result.checks_run # Number of checks executed
result.is_compliant # True if no errors found
result.level # Target conformance level
# Methods
result.summary() # Get text summary
result.filter_by_level(IssueLevel.ERROR) # Filter by severity
result.filter_by_criterion("1.1.1") # Filter by WCAG criterion
result.filter_by_principle("perceivable") # Filter by principleRepresents an accessibility issue found during checking.
for issue in result.issues:
issue.criterion # WCAGCriterion object
issue.level # IssueLevel (ERROR, WARNING, NOTICE)
issue.message # Description of the issue
issue.element # The problematic HTML element
issue.selector # CSS selector for the element
issue.line # Line number in source
issue.context # Surrounding HTML for context
issue.recommendation # How to fix the issue
issue.techniques # WCAG technique referencesGenerate accessible reports in multiple formats.
from wcag_checker import Report, ReportFormat
result = checker.check(html)
report = Report(result)
# Generate different formats
text_report = report.to_text()
json_report = report.to_json()
html_report = report.to_html()
md_report = report.to_markdown()
# Save to file
report.save("report.html", ReportFormat.HTML)
report.save("report.json", ReportFormat.JSON)- Level A: Minimum level of conformance (most critical issues)
- Level AA: Recommended for most websites (A + additional requirements)
- Level AAA: Highest level of conformance (AA + additional requirements)
from wcag_checker import ConformanceLevel
# Check for Level A only
checker = WCAGChecker(level=ConformanceLevel.A)
# Check for Level AA (includes A)
checker = WCAGChecker(level=ConformanceLevel.AA)
# Check for Level AAA (includes A and AA)
checker = WCAGChecker(level=ConformanceLevel.AAA)- ERROR: Must be fixed for conformance
- WARNING: Should be reviewed, likely needs fixing
- NOTICE: Informational, may need manual verification
from wcag_checker import IssueLevel
# Get only errors
errors = result.filter_by_level(IssueLevel.ERROR)
# Exclude notices during checking
checker = WCAGChecker(include_notices=False)- 1.1.1 Non-text Content (images, SVGs, objects)
- 1.2.1 Audio/Video alternatives
- 1.2.2 Captions for video
- 1.2.3 Audio descriptions
- 1.3.1 Info and Relationships (headings, tables, lists, forms)
- 1.3.5 Identify Input Purpose (autocomplete)
- 1.4.1 Use of Color
- 1.4.2 Audio Control
- 2.1.1 Keyboard Accessible
- 2.1.4 Character Key Shortcuts
- 2.2.1 Timing Adjustable (meta refresh)
- 2.2.2 Pause, Stop, Hide (blink, marquee)
- 2.3.1 Three Flashes (animated GIFs)
- 2.4.1 Bypass Blocks (skip links, landmarks)
- 2.4.2 Page Titled
- 2.4.4 Link Purpose
- 2.4.6 Headings and Labels
- 2.4.7 Focus Visible
- 2.5.3 Label in Name
- 2.5.7 Dragging Movements (WCAG 2.2)
- 2.5.8 Target Size (WCAG 2.2)
- 3.1.1 Language of Page
- 3.1.2 Language of Parts
- 3.2.1 On Focus
- 3.2.2 On Input
- 3.2.6 Consistent Help (WCAG 2.2)
- 3.3.1 Error Identification
- 3.3.2 Labels or Instructions
- 3.3.7 Redundant Entry (WCAG 2.2)
- 4.1.1 Parsing (duplicate IDs, invalid nesting)
- 4.1.2 Name, Role, Value (buttons, iframes, ARIA)
- 4.1.3 Status Messages (live regions)
# Check a single file
python -m wcag_checker check page.html
# Check with specific level
python -m wcag_checker check page.html --level AAA
# Generate HTML report
python -m wcag_checker check page.html --format html --output report.htmlYou can create custom checks by extending the BaseCheck class:
from wcag_checker.checks.base import BaseCheck, register_check
from wcag_checker.criteria import SC_1_1_1
@register_check
class MyCustomCheck(BaseCheck):
criterion = SC_1_1_1
description = "My custom accessibility check"
def check(self):
issues = []
# Your checking logic here
for element in self.soup.find_all('my-element'):
if not element.get('accessible-attr'):
issues.append(Issue(
criterion=self.criterion,
level=IssueLevel.ERROR,
message="Missing accessible attribute",
element=str(element),
selector=self.get_element_selector(element),
))
return issuesMIT License - see LICENSE file for details.