Skip to content

Technology

Most automated accessibility testing is rule-based. We extend it with gradient-boosted models to detect what a static rule structurally cannot.

How a scan becomes a finding

Rule-based checks and gradient-boosted classifiers operate on the same scan data, within a single pass.

UI classification

Identifies what a piece of UI is, so the rule engine applies the right checks.

Rule engine

Fast, precise checks - but blind to anything past a single page snapshot.

Feature extraction

Rule output and DOM diffs become structured features.

3 classifiers

Score flows, components, and matches that rules can't judge.

Findings

Every result mapped to a real success criterion and level.

Rules alone vs. rules plus gradient boosting

The classifiers do not replace the rule engine; they operate beyond its structural limits.

DimensionRule-based only+ Gradient boosting
ScopeA single page, at a single point in time.A multi-step flow, tracked across transitions.
New failure patternNeeds a new rule to be hand-written.Generalizes from similar labeled examples.
NoiseFlags every syntactic pattern match.Suppresses matches that are not genuine issues in context.
Improves howOnly through a manual rule-set edit.As more reviewed scans accumulate.
ExplainabilityRule ID and matched element.Rule ID, matched element, and the features that drove the call.

Three classifiers, one scan

Each targets a distinct failure mode the rule engine cannot detect.

False-positive filtering

A classifier trained on the context around a rule match - not just the match itself - suppresses low-value flags before they reach the findings list. The most data-rich and straightforward of the three.

rule IDparent elementcomputed contrasthistorical FP rate

Flow-level evaluation

Each step transition in a flow is reduced to a feature row and classified on its own, trained on transitions labeled through structured manual review.

focus before/afterDOM tree distancenode diffaria-live change

Component-level evaluation

Looking across every instance of a component lets a model learn structural correlations between working and broken implementations, instead of one rule per variation.

ARIA roles/attrsnesting depthevent handlerspass/fail history

False-positive filtering

A duplicate ID that isn't actually duplicate

The rule engine flags two elements sharing the id submit-btn as a duplicate. What it misses: each lives in a separate Shadow DOM root, where IDs are scoped and don't actually collide. The classifier weighs shadow-root boundaries into the match before it's surfaced.

rule_idduplicate-id
matched_idsubmit-btn
occurrences_on_page2
same_shadow_rootfalse
shadow_root_count2
reviewer_labelfalse positive - IDs scoped to separate shadow roots

Flow-level evaluation

Step 2 to step 3, and nothing announces the change

Moving from shipping to payment swaps the page content client-side - no full reload, so no rule ever re-evaluates it. Focus stays on the old step, and nothing announces the new one loaded. Catching this means comparing state before and after the transition.

step_from2 - Shipping
step_to3 - Payment
focus_after_transitionunchanged (stayed on step 2)
new_heading_announcedfalse
dom_nodes_replaced38
reviewer_labelstep change not announced - screen reader users can't tell the flow advanced

Component-level evaluation

A component that passes every rule and still doesn't work

A custom combobox passes every rule: valid role, aria-expanded, aria-controls, even a keydown handler. What none of them catch: that handler never updates aria-activedescendant, so keyboard users can't tell which option is selected. Only comparing its structure against known-working implementations surfaces the gap.

component_idSearchCombobox
instances_scanned18
individual_rules_passed18 / 18
keydown_handler_presenttrue
aria_activedescendant_presentfalse
structural_pattern_match0.31 (low)
reviewer_labelhighlighted option not exposed - fails despite passing every rule

Where the training data comes from

Labels come from structured manual review, not a separate labeling project - every time a reviewer marks a criterion passed, failed, or not applicable, that outcome becomes training data. The dataset grows with normal product use.

Explainable by default

Every model-derived finding ships with the features that drove it, not just a score. Reviewers can confirm or dismiss a finding, and that decision feeds back into the training set.

Why gradient boosting, not deep learning

The signals are structured and tabular. Gradient boosting trains effectively on the labeled data we actually have, runs fast enough for a continuous scan, and stays inspectable - a deliberate trade-off, not a claim that deep learning couldn't do this too.

Where this is still evolving

Per-transition features work well for short flows, less so for long, highly variable ones. Component-level detection is the most data-hungry of the three, and leans on rule-derived signals where labeled history is thin.

This does not replace WCAG as the governing standard. Every finding, rule- or model-derived, maps to a specific success criterion; the models extend coverage and precision but do not define what "accessible" means on their own.

Read the full technical note

Submit your business interest

Accessibility Inspector is currently a research preview. Leave your email and we'll let you know the moment it opens up.

One email when it's ready - no spam.