All posts
Product

Announcing accessio-scan: Open-Source Accessibility Scanner with axe-core + Playwright

A free, MIT-licensed CLI that runs a full WCAG audit against any URL in one command. No account, no signup, no telemetry unless you opt in.

AT
Accessio Team
6 minutes read

Announcing accessio-scan: Open-Source Accessibility Scanner with axe-core + Playwright

Today we are releasing accessio-scan, a free, MIT-licensed CLI that audits any URL for WCAG violations in one command:

npx accessio-scan https://your-site.com

That is the whole thing. No account, no signup, no config file. The scanner downloads headless Chromium on first run, navigates to the URL, injects axe-core 4.11, and reports every violation it finds, grouped by impact. One command, one report, one exit code you can wire into CI.

This post walks through why we are open-sourcing it, what ships in v0.1.0, and what comes next.

Why open source

The accessibility tooling market has a trust problem. Every vendor claims WCAG 2.2 compliance. Most ship a JavaScript overlay that patches the DOM at runtime without touching the underlying HTML, which is why NVDA, VoiceOver, and a manual auditor still flag the same issues the overlay claims to have fixed. The only way to cut through the marketing is to let developers run the audit themselves, on their own infrastructure, with a tool whose source is public.

So we wrote one. And we released it under MIT so anyone can fork it, inspect it, wrap it, ship it inside their own CI pipeline, or point it at a competitor's marketing site to see for themselves.

What ships in v0.1.0

Three output formats for three workflows.

npx accessio-scan https://example.com                    # console, coloured by impact
npx accessio-scan https://example.com --format json      # pipe into jq for custom rollups
npx accessio-scan https://example.com --format sarif     # GitHub Code Scanning, inline PR annotations

CI-ready exit codes. 0 for a clean scan, 1 if violations are found, 2 on scanner error. That makes the CLI a drop-in gate:

- run: npx accessio-scan https://staging.example.com

No bash scripting, no JSON parsing, no manual threshold setting. The build fails if axe finds any violation. Tighten by impact using a post-process step; we will ship that as a flag in v0.2.

GitHub Code Scanning out of the box. Emit a SARIF 2.1.0 report, upload it with github/codeql-action/upload-sarif, and every accessibility violation becomes an inline annotation on the pull request diff. Reviewers see them in the same place they see type errors and lint warnings. This is the integration we wish every vendor had shipped five years ago.

Privacy by design

accessio-scan has an optional --telemetry flag. When enabled, it sends a minimal report to service.accessio.ai:

FieldValue
hostHashSHA-256 of the scanned hostname. One-way.
ruleIdaxe-core rule identifier (e.g. color-contrast).
impactcritical, serious, moderate, minor.
countNumber of elements violating this rule on this scan.
tagsWCAG level and SC tags from the rule metadata.

Never sent. URLs, query strings, page HTML, CSS selectors, HTTP headers, cookies, authentication, or any user input. The privacy tests in test/telemetry.test.ts assert the wire payload contains none of those. Any pull request that adds a field to the telemetry schema must also add an assertion that the field cannot leak PII.

The server hashes the client IP with a daily-rotating salt before storing it, so abuse detection works for a day but historic rows cannot be retroactively de-anonymised even if the salt ever leaks. The full schema is in the accessio-service repo.

Telemetry is opt-in, off by default, silently fails if the endpoint is unreachable, and exists for one reason: the aggregated data will power the annual State of Web Accessibility report. We want the numbers in that report to come from real scans, not a survey with 400 respondents who self-selected by caring about the topic.

Security

We ran a security review on the codebase before cutting the v0.1.0 tag. Two HIGH findings got fixed in the initial release:

  1. The Chromium sandbox is enabled by default. Earlier iterations had --no-sandbox baked in; now you have to set ACCESSIO_SCAN_UNSAFE_DISABLE_SANDBOX=1 explicitly and get a loud stderr warning every run. The flag exists for root-in-Docker CI setups that cannot get namespace privileges; never set it on a developer machine.
  2. The --telemetry-endpoint override rejects anything that is not http:// or https://. Earlier it would happily accept file:// or data://, which made it an SSRF primitive for anyone who controlled someone else's CI config.

Pre-merge follow-ups also closed overwrite protection on --output, a length cap on --wait-for selectors, and a Dependabot config for runtime and workflow dependencies. All of this is visible in the public commit history.

Install

Run ad-hoc with no install:

npx accessio-scan https://your-site.com

Or install globally:

npm install -g accessio-scan
accessio-scan https://your-site.com

Requires Node.js 20 or later. First run downloads headless Chromium via Playwright (~300 MB). If Chromium is already installed on CI, skip the download with PLAYWRIGHT_SKIP_BROWSER_DOWNLOAD=1.

What comes next

  • Crawling. v0.2 follows internal links or a sitemap, not just the entry URL.
  • Auth. Cookie and header injection so scans can reach logged-in pages.
  • GitHub Action. A zero-config wrapper so repos can add an accessibility gate without writing the npx command.
  • Firefox and WebKit. axe-core rules are identical across engines, but shipping multi-engine scan as a single command surfaces engine-specific rendering bugs.

Links

If the scanner is useful, a star on the repo helps more than you might think. If it finds a bug on your site, open an issue; we read every one.

Announcing accessio-scan: Open-Source Accessibility Scanner with axe-core + Playwright | AccessioAI