# Accessibility Checker — WCAG 2.2 Audit with axe-core (`reverend_sal/accessibility-audit`) Actor

Audit any list of web pages for WCAG 2.0/2.1/2.2 A & AA accessibility issues with axe-core in real Chrome. Get every violation with impact, WCAG criteria, failing elements (CSS selector + HTML) and fix guidance. Export to CSV/Excel or call via API.

- **URL**: https://apify.com/reverend_sal/accessibility-audit.md
- **Developed by:** [North Eng](https://apify.com/reverend_sal) (community)
- **Categories:** Developer tools, Automation
- **Stats:** 2 total users, 1 monthly users, 100.0% runs succeeded, 0 bookmarks
- **User rating**: No ratings yet

## Pricing

from $4.00 / 1,000 page auditeds

This Actor is paid per event. You are not charged for the Apify platform usage, but only a fixed price for specific events.

Learn more: https://docs.apify.com/actors/running/actors-in-store.md#pay-per-event

## What's an Apify Actor?

An Actor is a serverless cloud program that runs on the Apify platform. It has two run modes.
In Batch mode, an Actor accepts a well-defined JSON input, performs an action which can take anything from a few seconds to a few hours,
and optionally produces a well-defined JSON output, datasets with results, or files in key-value store.
In Standby mode, an Actor provides a web server which can be used as a website, API, or an MCP server.

Apify vocabulary and the platform model are defined once, in the agent quickstart at https://apify.com/agents.md.

## How to integrate an Actor?

If asked about integration, you help developers integrate Actors into their projects.
You adapt to their stack and deliver integrations that are safe, well-documented, and production-ready.

Do not guess an integration path. Every one of them is in the agent quickstart at https://apify.com/agents.md: the Apify MCP server, Agent Skills with the Apify CLI, the JavaScript and Python clients, the REST API, and the account-free path for an agent with no human to sign in. It also carries the rule on stating cost before the first paid run.

For examples already wired to this Actor's own input schema, see the [API](#api) section below.

Each client library has reference documentation the quickstart does not restate: [JavaScript/TypeScript](https://docs.apify.com/api/client/js/docs.md) (`npm install apify-client`) and [Python](https://docs.apify.com/api/client/python/docs.md) (`pip install apify-client`).

# README

## Accessibility Checker — WCAG 2.2 AA audit with axe-core

Audit any list of web pages for **WCAG 2.0, 2.1 and 2.2 (A / AA / AAA)** accessibility problems. Each page is loaded in real Chrome and tested with **axe-core 4.14** — the same open-source engine behind Deque axe DevTools, Lighthouse's accessibility score and Microsoft Accessibility Insights.

For every page you get the violated rules, their **impact** (critical / serious / moderate / minor), the **WCAG success criteria**, the **failing elements** (CSS selector + HTML snippet), a plain-English failure summary and a link to fix guidance.

### Who it's for

- **Developers and QA** — audit staging before a release; call it from CI via the Apify API.
- **Agencies and freelancers** — produce a client accessibility report in one run; export to Excel.
- **Compliance prep** — ADA, Section 508, EN 301 549 and the European Accessibility Act all reference WCAG. Start with an automated baseline.
- **SEO and content teams** — find missing alt text, empty links and unlabeled form fields across many pages.

> Automated testing finds a large share of common WCAG issues but **not all of them** — no tool can. Items in `needsReview` need a human check, and a full conformance claim needs manual testing with assistive technology.

### How to use

1. Paste your page URLs (or upload a list).
2. Pick a standard — **WCAG 2.2 AA** is the default and the usual legal target.
3. Click **Start**. Look at the **Overview** view for per-page counts and the **Violations** view for one row per problem rule. Export as CSV, Excel, JSON or HTML.

### Input

| Field | Default | Notes |
|---|---|---|
| `urls` | — | Pages to audit |
| `standard` | `wcag22aa` | `wcag2a`, `wcag2aa`, `wcag21aa`, `wcag22aa`, `wcag2aaa` |
| `includeBestPractices` | false | Adds axe best-practice rules (landmarks, heading order…) |
| `viewport` | `desktop` | `desktop` (1366×900) or `mobile` (390×844) |
| `waitUntil` | `load` | `load`, `domcontentloaded` or `networkidle` |
| `extraWaitSecs` | 1 | Extra time for client-side apps to render |
| `disableRules` | \[] | axe rule ids to skip, e.g. `color-contrast` |
| `saveScreenshots` | false | Saves a screenshot per page to the key-value store |
| `maxConcurrency` | 3 | Parallel pages |

### Output

One item per page. Real result for the W3C "inaccessible demo" page (Oct 22 2026, trimmed to the first violation):

```json
{
  "url": "https://www.w3.org/WAI/demos/bad/before/home.html",
  "httpStatus": 200,
  "title": "Welcome to CityLights! [Inaccessible Home Page]",
  "standard": "wcag22aa",
  "axeVersion": "4.14.0",
  "violationCount": 6,
  "affectedElements": 46,
  "impactCounts": { "critical": 2, "serious": 4, "moderate": 0, "minor": 0 },
  "passedRules": 14,
  "needsReviewRules": 1,
  "violations": [
    {
      "id": "image-alt",
      "impact": "critical",
      "help": "Images must have alternative text",
      "helpUrl": "https://dequeuniversity.com/rules/axe/4.14/image-alt?application=axeAPI",
      "wcag": ["wcag2a", "wcag111", "section508", "section508.22.a", "EN-301-549"],
      "elementCount": 33,
      "elements": [
        {
          "target": "img[src$=\"border_left_top.gif\"]",
          "html": "<img src=\"./img/border_left_top.gif\" width=\"10px\" height=\"10px\">",
          "failureSummary": "Fix any of the following:\n  Element does not have an alt attribute ..."
        }
      ]
    }
  ],
  "needsReview": [
    { "id": "color-contrast", "impact": "serious", "help": "Elements must meet minimum color contrast ratio thresholds", "elementCount": 2 }
  ]
}
```

The same run on W3C's *fixed* version of that page found 1 violation (`target-size`), which shows the difference between the two pages.

Pages that fail to load (DNS error, timeout) are listed with an `error` field and are **not charged**.

### Pricing

| Event | Price |
|---|---|
| Page audited | **$0.004** ($4 per 1,000 pages) |
| Actor start | Apify default ($0.00005) |

You are charged only for pages that loaded and were fully audited. Auditing 250 pages costs about $1.

### FAQ

**Can it check sites on my private network?**
No. Private addresses are refused: URLs (and every redirect, sub-resource and WebSocket) that resolve to localhost, private-network, link-local or cloud-metadata addresses (IPv4 and IPv6, e.g. 169.254.169.254) are not fetched (they are reported with `errorCode: "BLOCKED_URL"` and not charged).

**Is this the same as Lighthouse's accessibility score?** Lighthouse runs a subset of axe-core rules and turns them into a 0–100 score. This Actor runs the full axe rule set for the WCAG level you choose and lists every failing element.

**Can it audit pages behind a login?** Not in this version.

**Single-page apps?** Yes — pages render in Chrome. Use `waitUntil: networkidle` or raise `extraWaitSecs` if content loads late.

**Does it fix issues?** No. It tells you exactly what and where; each rule links to Deque's fix guide.

### Support

Use the **Issues** tab. Built and maintained by Hustler, an AI agent run by its human owner; issues are triaged by the agent and reviewed by the owner. axe-core is © Deque Systems, MPL-2.0.

# Actor input Schema

## `urls` (type: `array`):

Pages to audit. Each URL is loaded in Chrome and audited independently.

## `standard` (type: `string`):

Which WCAG rule set axe-core should run. Each level includes the levels below it.

## `includeBestPractices` (type: `boolean`):

Also run axe-core best-practice rules (e.g. landmarks, heading order). Not WCAG failures, but useful.

## `viewport` (type: `string`):

Browser window size used for the audit. Mobile also emulates a touch device.

## `waitUntil` (type: `string`):

When to consider the page loaded before auditing.

## `extraWaitSecs` (type: `integer`):

Give client-side apps time to render before the audit.

## `disableRules` (type: `array`):

axe-core rule ids to skip, e.g. "color-contrast".

## `saveScreenshots` (type: `boolean`):

Store a viewport screenshot of each page in the key-value store (link in results).

## `maxConcurrency` (type: `integer`):

How many pages are audited at the same time. Higher is faster but needs more memory.

## `timeoutSecs` (type: `integer`):

Pages that do not load within this time are reported as errors (not charged).

## Actor input object example

```json
{
  "urls": [
    {
      "url": "https://www.w3.org/WAI/demos/bad/before/home.html"
    }
  ],
  "standard": "wcag22aa",
  "includeBestPractices": false,
  "viewport": "desktop",
  "waitUntil": "load",
  "extraWaitSecs": 1,
  "disableRules": [],
  "saveScreenshots": false,
  "maxConcurrency": 3,
  "timeoutSecs": 45
}
```

# Actor output Schema

## `overview` (type: `string`):

One row per page with violation counts by impact.

## `violations` (type: `string`):

Violated rules with WCAG criteria, elements and fix links.

## `screenshots` (type: `string`):

Full-page screenshots (when enabled).

# API

You can run this Actor programmatically using our API. Below are code examples in JavaScript, Python, and CLI, as well as the OpenAPI specification and MCP server setup.

## JavaScript example

```javascript
import { ApifyClient } from 'apify-client';

// Initialize the ApifyClient with your Apify API token
// Replace the '<YOUR_API_TOKEN>' with your token
const client = new ApifyClient({
    token: '<YOUR_API_TOKEN>',
});

// Prepare Actor input
const input = {
    "urls": [
        {
            "url": "https://www.w3.org/WAI/demos/bad/before/home.html"
        }
    ]
};

// Run the Actor and wait for it to finish
const run = await client.actor("reverend_sal/accessibility-audit").call(input);

// Fetch and print Actor results from the run's dataset (if any)
console.log('Results from dataset');
console.log(`💾 Check your data here: https://console.apify.com/storage/datasets/${run.defaultDatasetId}`);
const { items } = await client.dataset(run.defaultDatasetId).listItems();
items.forEach((item) => {
    console.dir(item);
});

// 📚 Want to learn more 📖? Go to → https://docs.apify.com/api/client/js/docs

```

## Python example

```python
from apify_client import ApifyClient

# Initialize the ApifyClient with your Apify API token
# Replace '<YOUR_API_TOKEN>' with your token.
client = ApifyClient("<YOUR_API_TOKEN>")

# Prepare the Actor input
run_input = { "urls": [{ "url": "https://www.w3.org/WAI/demos/bad/before/home.html" }] }

# Run the Actor and wait for it to finish
run = client.actor("reverend_sal/accessibility-audit").call(run_input=run_input)

# Fetch and print Actor results from the run's dataset (if there are any)
print(f"💾 Check your data here: https://console.apify.com/storage/datasets/{run.default_dataset_id}")
for item in client.dataset(run.default_dataset_id).iterate_items():
    print(item)

# 📚 Want to learn more 📖? Go to → https://docs.apify.com/api/client/python/docs/quick-start

```

## CLI example

```bash
echo '{
  "urls": [
    {
      "url": "https://www.w3.org/WAI/demos/bad/before/home.html"
    }
  ]
}' |
apify call reverend_sal/accessibility-audit --silent --output-dataset

```

## MCP server setup

```json
{
    "mcpServers": {
        "apify": {
            "type": "http",
            "url": "https://mcp.apify.com/?tools=fetch-actor-details,reverend_sal/accessibility-audit"
        }
    }
}
```

The hosted server signs you in with OAuth on first connect, so no API token belongs in this config. Clients without OAuth support can send an `Authorization: Bearer <APIFY_API_TOKEN>` header instead, using a token from API & Integrations in Apify Console (https://console.apify.com/settings/integrations).

## OpenAPI specification

Download the OpenAPI definition: https://api.apify.com/v2/actors/2UyvikOPNHlN3Jnax/builds/R7afkfCW23od2I2II/openapi.json
