Back to blog
    August 23, 2026Tutorial

    What an Accessibility Audit Catches — and What Only a Screen Reader Will

    Accessibility became a shipping requirement rather than a nice-to-have some time around June 2025, when the European Accessibility Act started applying to consumer-facing digital products sold in the EU. Plenty of teams responded by running an automated audit, fixing what it flagged, and calling it done.

    That's a reasonable first move and a bad last one. Automated checks are excellent at a specific, narrow band of problems and structurally incapable of finding the rest — and the rest is what actually stops someone using your app.

    Here's the honest division of labour.

    What automation genuinely catches

    These are machine-checkable because they're properties of the tree, not of meaning. Every one of them is worth catching in CI, on every build:

    Missing labels. A control with no accessibility label reads out as "button" — or worse, as its resource id, or as nothing at all. This is the single most common finding in mobile audits and it's a one-line fix. contentDescription on Android, accessibilityLabel on iOS.

    Touch targets below the minimum. WCAG 2.2 added Target Size (Minimum) at 24×24 CSS pixels for AA. The platform guidelines are stricter and more useful as a working number: Apple's HIG says 44×44 pt, Material says 48×48 dp. Small targets are a motor-accessibility issue first, but they're a usability issue for everybody — a tap target you can't hit reliably on a train is bad for all users, not just some.

    Contrast below threshold. 4.5:1 for body text, 3:1 for large text and UI components. This one gets flagged constantly on the exact elements designers care most about: light grey placeholder text, disabled-looking-but-enabled buttons, text over hero images.

    Missing or duplicated identifiers. Two controls with the same label, or a label that's just "image", make a screen reader user unable to distinguish two different actions.

    Traversal order gaps. Elements the accessibility tree can't reach at all — usually a custom view that draws itself and never exposes anything.

    Run these automatically. They're cheap, they're deterministic, and a build should fail on regressions. On a real device the same audit also reflects the actual rendered layout, which matters for the size and contrast checks — a target that's 48dp in the layout file can be clipped to less than that by a parent on a small screen.

    What automation cannot catch, by construction

    Every item below is about meaning, and no static analysis has access to meaning.

    Labels that exist but are useless. contentDescription="button1" passes every automated check ever written. So does accessibilityLabel="image". So does a label on a "delete" icon that says "trash" while the confirmation dialog says "remove" — technically labelled, actually confusing. Automation verifies presence; only a human verifies that the label says the thing the control does.

    Reading order that's legal but wrong. The accessibility tree can be complete and traversable and still present a price before the product it belongs to, or read a card's badge before its title. Nothing is missing, so nothing is flagged. Swiping through it takes ten seconds to notice.

    Focus that goes somewhere unhelpful. Open a modal — where does focus land? After you delete an item, where does focus go? After an error, is the user told, or does focus sit on a field that now has a red outline they can't see? These are the interactions that decide whether an app is usable with a screen reader, and they're invisible to a tree snapshot.

    State that isn't announced. A toggle that looks on but doesn't expose its state. A loading spinner that never announces "loading". A form error that appears visually and is never spoken. The control is labelled; the change isn't communicated.

    Custom gestures with no alternative. Swipe-to-delete, long-press menus, pinch-to-zoom, drag-to-reorder. A screen reader intercepts the gestures the app expects, so unless there's an alternative path — a custom action, a visible button — the feature is simply unavailable.

    Dynamic Type and large text. Bump the system font to its largest setting and watch layouts collapse: truncated labels, buttons whose text disappears, rows that overlap. This is the most commonly skipped accessibility check and one of the most commonly needed — the population using large text is much larger than the population using a screen reader.

    Vendors of automated engines typically claim to catch somewhere between a third and half of real issues. Whatever the exact number, the half they miss isn't a random sample — it's concentrated precisely in the interactive, stateful behaviour that determines whether the app is usable at all.

    The manual pass that's actually worth doing

    You do not need a full audit every sprint. You need a repeatable 20-minute pass on your critical flows — sign-up, the core action, checkout, settings.

    1. Screen reader only, screen off if you can. Turn on VoiceOver (iOS) or TalkBack (Android) and complete the flow without looking. Not "check the labels" — complete the flow. The point where you get stuck is the finding, and it's usually somewhere no static check was looking.

    2. Swipe through every screen linearly. Don't tap around; swipe right repeatedly, the way an actual screen reader user navigates. You are checking two things: does the order make sense, and is anything unreachable.

    3. Largest text size. System settings, biggest Dynamic Type / font scale, walk the same flows. Look for truncation, overlap, and buttons that lost their labels.

    4. One-handed, thumb only. Not a formal accessibility criterion, but it catches the same class of target-size and reachability problems that motor impairments amplify.

    5. Check the three states nobody checks. Loading, empty, and error. Errors especially: if a validation message appears visually and isn't announced, a screen reader user submits the form over and over with no idea what's wrong.

    Write down what you find each time. The same five findings recurring across releases is a signal about your components, not your screens — fix the shared button component once instead of fixing forty instances of it.

    Wiring it into the pipeline

    A workable split, in increasing order of cost:

    CadenceCheck
    Every buildAutomated audit on key screens; fail on new violations
    Every releaseScreen reader pass on critical flows; largest-text pass
    QuarterlyFull manual audit, ideally with someone who uses assistive tech daily

    The "fail on new violations" wording matters. Failing on all violations means a team with an existing backlog turns the check off in week one. Baseline what exists, block what's added, and burn the baseline down deliberately.

    On RobotActions the automated half runs against a real device as part of a session — the audit reads the live accessibility tree, so labels, target sizes and contrast are evaluated on what actually rendered on that hardware, and you can capture a screen-reader preview of a screen to review the announced order without needing the device physically in front of you. That covers the machine-checkable band and makes the manual pass cheaper, because you're walking flows on a device that's already provisioned rather than hunting for a spare handset.

    The manual pass still has to happen. There's no version of this where it doesn't.

    The part worth saying out loud

    Every fix in the automated column is also a fix for people not using assistive technology. Bigger targets help everyone on a bumpy bus. Higher contrast helps everyone in sunlight. Text that survives a larger font size helps everyone over forty. Labels that describe what a control does help your own automated tests find elements reliably — an app with a complete accessibility tree is measurably easier to write stable tests against, because you can stop guessing at XPath and select by the same identifiers a screen reader uses.

    That last point is worth taking seriously if you're arguing for the work internally. Accessible markup and stable test automation are the same investment described two ways.

    Run an accessibility audit on a real device →

    Ready to test on real devices?

    Sign in with Google or GitHub and get real iOS and Android devices in your browser — free to try.

    👋 Hi! Need help? Chat with us!

    Chat with us

    Online

    Before we start

    Share your details so we can follow up with you.