Caption Auditor: catching screenshot captions that fail accessibility standards

Quick one from a build session this week. I’ve had a question nagging me for a while now: are the screenshots in our learning paths actually described properly for screen-reader users? Alt text is easy to forget, easy to fumble (“image123.png”), and almost impossible to audit by hand across a whole course library. So I built a tool to help with that.

What it does

You pick a learning path from a dropdown. The Caption Auditor walks that path’s pages, pulls out the product and UI screenshots (skipping logos, icons, headshots and marketing photos), and checks each one’s alt text against WCAG 2.2, specifically 1.1.1 Non-text Content and 1.4.5 Images of Text. You get back a report: every screenshot, a pass or fail verdict with a severity, the reason it failed, and a copy-ready suggested alt text you can paste straight in to fix it.

What it looks like

A run surfaces things like:

  • Missing alt text on a storyboard screenshot (high severity)
  • Alt text that is just the filename, “screenshot-2026-04-07-at-11-18-51-am.png” (high)
  • Alt text that is too short to be useful, “functions” (medium)
  • Vague alt text like “Grid” that does not describe the content (low)
  • And the good ones passing cleanly, so you have a reference for what good looks like

Filter tabs flip between failing, passing, and all, and each suggested fix has a one-click copy button.

Learning bits

Two things worth sharing.

First, the design of the check itself held up really well. One vision-model pass per image does two things: it first classifies whether the image is actually a screenshot of software, then judges the caption only if it is. That keeps logos and stock photos out of the report.

Second, the interesting wall we hit: our education pages render their screenshots and captions client-side, so a plain crawl of the HTML sees no alt text at all. The real captions only appear after the page’s JavaScript runs. (This is what Tines 3B told me, by the way.) So a straight “fetch and read” approach reports everything as empty, which is misleading. The two better ways forward are to read alt text directly from the LMS (the source of truth, since that is where the content is published) or to render each page in a headless browser and read the live DOM. (Again, this is what 3B told me. :grinning_face_with_smiling_eyes: )

We (me and 3B) picked the LMS API route, but we’re still working on it, so this screenshot is a what it will look like once it’s done.

What’s next

  • Run it on a schedule and post a weekly “captions needing attention” summary.
  • Extend beyond learning content to any content surface we publish.

There’s still some work to do, but for now it’s a pretty neat proof of the concept.

3 Likes