Accessibility testing for teams with an existing codebase
Fail the build,
not the audit.
Runs axe-core on every pull request and returns structured WCAG violations as JSON. With a committed baseline it fails the build only on violations you have not already accepted — so switching it on today does not turn tomorrow red.
Free, no signup. Or .
- critical img:nth-child(4) — image-alt in baseline
- serious .hero__subtitle — color-contrast, 3.03:1 in baseline
- serious a[href$="cart"] — link-name in baseline
- moderate #filters > div — aria-required-children in baseline
- +52 more already on the page before you arrived in baseline
Without one, every build is red from the first run.
This is the difference between a checker and a gate. Point a scanner at a site that already has 56 violations and every build fails on day one. Nobody fixes 56 issues to unblock a deploy — they delete the step, and the gate is gone by Friday. A baseline accepts what is already there, so the 57th violation is the one that fails.
Why this keeps happening
of the top one million home pages have detectable WCAG failures. Each square is one page in a thousand.
The average page carries 56.1 of them, and both numbers got worse year on year. The detection is not the hard part — axe-core is free, mature and probably already in your dependency tree.
What almost nobody has is a gate a team will leave switched on.
WebAIM Million, 2026
How it works
One line of YAML.
A GitHub Action, a CLI for every other CI system, and Playwright and Cypress adapters. Fail on serious violations, warn on the rest, post the diff as a comment on the pull request. Nobody has to log into anything.
Fails on the 57th, not the first 56.
Every violation carries a fingerprint that survives a CSS-class rename, and baselines
key on path rather than hostname so preview deployments keep matching. Accepting a
violation is an --update-baseline commit someone reviews.
The engine version ships with the result.
axe-core is pinned and returned on every scan. An engine upgrade changes findings, and a result you cannot attribute to a version is a result you cannot reproduce. Most scanners float and let you discover it in a pull request.
We tell you what is broken.
We do not sell a widget that claims to fix your site with one line of JavaScript. The FTC fined accessiBe $1M in 2025 over claims like that. We report what a machine can detect, name the part it cannot, and leave the fixing to you.
# .github/workflows/a11y.yml
- uses: skiplink/action@v1
with:
urls: https://staging.example.com
baseline: .skiplink/baseline.json
fail-on: new # or: critical | serious | moderate
token: ${{ secrets.SKIPLINK_TOKEN }}
What a machine can and cannot do
Caught automatically
- Colour contrast against the computed background
- Images with no alt attribute
- Inputs with no associated label
- Links and buttons with no accessible name
- Invalid or contradictory ARIA
- Heading levels that skip
Needs a human
- Whether alt text actually describes the image
- Whether focus order matches the visual order
- Whether an error message can be understood
- Whether a custom widget behaves as its role promises
- Whether captions are accurate
- Whether it works under a screen reader in practice
An image with alt="image" passes every automated check and helps nobody. That
is the shape of the gap, and no scanner closes it. Use automation for the floor — the
regressions that pile up between audits, caught in the pull request where they are cheap —
and a qualified reviewer for the rest. The long version.
Pricing
Usage-based. No seats, no sales calls, no annual contracts. Cancel from the dashboard without emailing anyone. Open source and non-profits get Growth free — send us the repo.
Turn it on before
the audit finds it.
Scan a page free, with no signup. If it earns its place, the same check runs on every pull request in one line of YAML — and with a baseline, it stays green until someone actually breaks something.
500 scans a month on the free tier · no card · cancel from the dashboard without emailing anyone