# SiteVerdict — Accessibility Statement & VPAT/ACR Generator (`siteverdict/siteverdict-accessibility-statement-generator`) Actor

Audit your site for WCAG 2.2 (axe-core + keyboard, reflow, motion checks) and get a draft UK public-sector or EAA accessibility statement plus a VPAT-style conformance report (ACR) in HTML, Markdown and Word. Honest drafts: failures listed, nothing claimed that automation can't prove.

- **URL**: https://apify.com/siteverdict/siteverdict-accessibility-statement-generator.md
- **Developed by:** [Aman Thakran](https://apify.com/siteverdict) (community)
- **Categories:** Developer tools, Business
- **Security:** Limited permissions
- **Stats:** 2 total users, 1 monthly users, 100.0% runs succeeded, 0 bookmarks
- **User rating**: No ratings yet

## Pricing

Pay per event

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

## SiteVerdict — Accessibility Statement & VPAT/ACR Generator

**Turn an automated WCAG 2.2 audit into a draft accessibility statement and a VPAT®-style Accessibility Conformance Report (ACR) in minutes. You get HTML, Markdown and Word files, every known failure is listed in plain English, and nothing is claimed that automation cannot prove.**

> **Every document is a DRAFT.** Automated testing finds roughly 30–50% of accessibility barriers. Many WCAG criteria cannot be tested automatically at all. Items marked `[REVIEW]` must be completed or confirmed by a person, ideally after manual and assistive-technology testing. **Not legal advice.**

### What it does

1. **Audits your pages** in a real Chromium browser with the SiteVerdict Accessibility Auditor engine:

   - axe-core 4.14 WCAG 2.2 A/AA rules;
   - a keyboard focus walk (invisible or obscured focus, keyboard traps, skip link);
   - reflow at 320 px (400% zoom);
   - target size and animation/reduced-motion checks;
   - desktop (1366 px) and, only when `mobile` is selected in **Devices** (selected by default), a simulated mobile viewport (390 px). Only the viewports you select are tested and named in the statement; real phones, tablets and native apps are not tested.

   You can also **import** an existing SiteVerdict Accessibility Auditor dataset (`auditDatasetId`), which costs nothing extra for pages.
2. **Merges your manual findings** (`manualFindings`): keyboard, screen-reader and zoom test results per WCAG criterion. They override the automated result for that criterion.
3. **Drafts the accessibility statement**:
   - **UK public sector:** the Public Sector Bodies (Websites and Mobile Applications) (No. 2) Accessibility Regulations 2018, following the structure of the GOV.UK sample statement. Sections:
     - how accessible the site is;
     - feedback and contact;
     - the enforcement procedure (EHRC/EASS, or ECNI for Northern Ireland);
     - compliance status;
     - non-compliance items, each with its WCAG criterion and a fix date;
     - disproportionate burden;
     - out-of-scope content (PDFs before 23 Sept 2018, video before 23 Sept 2020, live video, maps, third-party and archived content);
     - your improvement plan;
     - how the statement was prepared.
   - **European Accessibility Act:** Annex V / Article 13 service information. Sections:
     - a service description;
     - how the service meets the requirements, with EN 301 549 V3.2.1 clause references;
     - known limitations and exemptions;
     - contact;
     - the market surveillance authority.
   - **Voluntary:** a private-sector WCAG 2.2 AA statement.
4. **Drafts an ACR** in the ITI VPAT 2.5 (WCAG edition) layout:
   - product information and the evaluation methods used;
   - **Table 1 (Level A)** and **Table 2 (Level AA)**, plus optional **Table 3 (AAA)**, covering all WCAG 2.2 criteria;
   - one of these conformance levels for each criterion: *Supports / Partially Supports / Does Not Support / Not Applicable / Not Evaluated*.
5. **Optional AI plain-English rewrite**, using your own Anthropic or OpenAI key. It turns "Form elements must have labels (10 instances)" into "Some form fields have no labels, so screen-reader users may not know what to enter", and drafts a "What we're doing" paragraph. Only issue titles, descriptions and WCAG numbers are sent; no page content is sent.

#### Honest by design

| Situation | Draft says |
|---|---|
| A criterion fails on every audited page | **Does Not Support** |
| A criterion fails on some pages | **Partially Supports** |
| No automated failure | **Not Evaluated**, plus a suggestion ("Supports (if manual testing confirms)" or "Requires manual evaluation"). We never write "Supports" on automation alone. |
| Your manual finding says passes / fails / N/A | That result is used |
| UK compliance status | "fully compliant" **only** if every A/AA criterion is confirmed by your manual findings. Otherwise "partially" or "not compliant", marked `[REVIEW]`. |

### Who it is for

1. **UK public sector bodies** (councils, NHS, universities, schools, charities with public funding). They must publish an up-to-date accessibility statement, and many statements are years out of date.
2. **EU-facing businesses** that must publish EAA accessibility information for e-commerce, banking, transport, e-books or telecoms services from 28 June 2025.
3. **Agencies and SaaS vendors** answering procurement questionnaires. They need a VPAT/ACR draft to hand to the accessibility auditor, not a blank template.

### Example

```json
{
  "jurisdiction": "uk-psbar",
  "startUrls": [{ "url": "https://www.example.gov.uk/" }],
  "crawl": true,
  "maxPages": 10,
  "organisationName": "Example Borough Council",
  "contactEmail": "accessibility@example.gov.uk",
  "enforcementRegion": "england-scotland-wales",
  "outOfScope": ["pdfs-before-2018", "maps"],
  "manualFindings": [
    { "sc": "2.4.3", "status": "fails", "description": "In the bin-collection form, focus jumps to the footer after the postcode search.", "fixBy": "March 2027" }
  ]
}
```

**Before:** an axe report full of selectors, and a blank GOV.UK template.

**After** (excerpt from `STATEMENT.md`; sample mode, bundled demo audit):

> ### Compliance status
>
> This website is partially compliant with the Web Content Accessibility Guidelines version 2.2 AA standard, due to the non-compliances listed below.
>
> ### Non-compliance with the accessibility regulations
>
> - Form elements must have labels (10 instances on 1 page tested). This fails WCAG 2.2 success criterion 4.1.2 (Name, Role, Value). We plan to fix this by \[REVIEW: planned fix date].
> - Elements must meet minimum color contrast ratio thresholds (4 instances on 1 page tested). This fails WCAG 2.2 success criterion 1.4.3 (Contrast (Minimum)). …

ACR excerpt:

| Criteria | Conformance Level | Remarks and Explanations |
|---|---|---|
| 1.1.1 Non-text Content (Level A) | Partially Supports | Automated testing found failures on 1 of 2 page(s): Images must have alternative text (2). |
| 1.4.3 Contrast (Minimum) (Level AA) | Partially Supports | … |
| 2.4.6 Headings and Labels (Level AA) | Not Evaluated | Not testable automatically; manual evaluation required. Suggested: Requires manual evaluation. |

Try it free with `"sampleMode": true`. It uses two bundled real audit results, with no browser and no charge. If you run with no start URL, no audit dataset and no manual findings (for example an empty API call), the Actor runs this sample automatically instead of failing: every row has `isSampleData: true`, the status message starts with **SAMPLE DATA**, every generated document carries a "SAMPLE DATA - not a real accessibility statement" banner, and nothing is charged.

### Output

- **Key-value store:**
  - `STATEMENT.html`
  - `STATEMENT.md`
  - `STATEMENT.doc`: Word-compatible HTML. It opens directly in Microsoft Word, LibreOffice and Google Docs; use *File → Save As → .docx* to get a native Word file.
  - `ACR.html`, `ACR.md`, `ACR.csv` (the criteria table)
  - `SUMMARY`: agent-ready JSON with the status, counts and document links
- **Dataset**, with three views:
  - **Statement summary** (one row);
  - **WCAG 2.2 criteria**: one row per criterion, the ACR table;
  - **Pages**: one row per page audited.

### Pricing (pay per event)

| Event | When | Proposed price |
|---|---|---|
| `page-audited` | each page fully audited in the browser (not for imported datasets, blocked, failed or robots-disallowed pages) | $0.02 |
| `statement-generated` | each statement + ACR document pack | $0.50 |
| `ai-rewrite` | each successful AI plain-English rewrite (your own key pays the model) | $0.05 |

Examples:

- 10 pages + pack ≈ **$0.70**
- 50 pages + pack + AI ≈ **$1.55**
- Importing an existing audit dataset ≈ **$0.50**

Sample mode is free, and the run stops at your maximum total charge.

### FAQ

**Can I publish the statement as is?**
No. Complete every `[REVIEW]` placeholder: fix dates, testing method, contact details, and any disproportionate burden claims (which need a documented assessment). Confirm the result with manual testing. GOV.UK expects statements to be based on a proper evaluation.

**Why is nothing marked "Supports"?**
Automated tools can prove a failure but not a pass for most criteria. Add your manual results in `manualFindings` and those criteria become *Supports*, *Partially Supports* and so on.

**Is this an official VPAT?**
No. VPAT® is a registered service mark of ITI. This is an independent draft in the same WCAG-edition layout, to give your evaluator a head start.

**Which pages should I test?**
Choose a representative sample: home page, contact, search, a form or transaction, a content page per template, and documents. You can also enable `crawl`.

**Does it bypass logins or bot protection?**
No. Pages behind a login or a bot challenge are reported as blocked or failed and are not charged.

### Limits

- Automated checks cover only part of WCAG. Captions, meaningful sequence, error suggestions, consistent help and many other criteria need human judgement.
- Pages are audited one at a time in a single browser: about 15–40 s per page on desktop + mobile. The cap is 50 pages per run.
- PDFs and other documents are not audited.
- The EAA template does not decide whether your service is in scope, or which national law and authority apply.
- AI text is a draft, marked `[REVIEW]`.

### Sources & compliance

All sources were checked on 11 Oct 2026.

- **GOV.UK sources:**
  - Sample accessibility statement: https://www.gov.uk/government/publications/sample-accessibility-statement
  - Make your public sector website or app accessible: https://www.gov.uk/guidance/accessibility-requirements-for-public-sector-websites-and-apps
  - Regulations: https://www.legislation.gov.uk/uksi/2018/952/contents/made
  - GOV.UK guidance is Crown copyright under the Open Government Licence v3.0. The statement wording is adapted from the sample statement.
- **European Accessibility Act:** Directive (EU) 2019/882, https://eur-lex.europa.eu/eli/dir/2019/882/oj (Article 13, Annex V).
- **EN 301 549 V3.2.1** (ETSI): https://www.etsi.org/deliver/etsi_en/301500_301599/301549/03.02.01_60/en_301549v030201p.pdf
- **WCAG 2.2:** W3C Recommendation, https://www.w3.org/TR/WCAG22/. Criterion names are used under the W3C Document License.
- **VPAT®:** registered service mark of the Information Technology Industry Council (ITI), https://www.itic.org/policy/accessibility/vpat. No endorsement implied.
- **Engine:** axe-core 4.14.0 by Deque Systems (MPL-2.0, used unmodified), https://github.com/dequelabs/axe-core. See `LICENSES.md`.
- **Crawling and security:**
  - The Actor fetches only the public pages you list, and same-site links if you enable crawling.
  - robots.txt is respected.
  - It uses an honest User-Agent: `SiteVerdict/accessibility-statement-generator (+hello@webrevenuescan.com)`, appended to the Chromium UA.
  - It never bypasses CAPTCHAs, logins or bot protection.
  - Private, internal and cloud-metadata addresses are refused. Every browser request goes through an SSRF guard.
- **Personal data:** none collected. The contact email you enter should be an organisational address.
- **UK GDPR / PECR:** no marketing and no tracking.
- **Not legal advice.**

Made by SiteVerdict, Aman Thakran / BharatFare Travel and Technologies Ltd (UK). Contact: hello@webrevenuescan.com.

# Changelog

This Actor's version history is a separate document: https://apify.com/siteverdict/siteverdict-accessibility-statement-generator/changelog.md

# Actor input Schema

## `jurisdiction` (type: `string`):

Which statement template to draft. The ACR (WCAG 2.2 conformance table) is produced for every type.

## `startUrls` (type: `array`):

Public pages of the website (max 20). robots.txt is respected; private/internal addresses are refused.

## `crawl` (type: `boolean`):

Follow internal links from the first page to build a sample (up to Max pages). Choose a representative sample: home page, key journeys, forms, templates.

## `maxPages` (type: `integer`):

Each audited page is one billable event.

## `auditDatasetId` (type: `string`):

Dataset ID from a SiteVerdict Accessibility Auditor run. When set, no pages are audited (and none are charged); the statement is built from those results.

## `manualFindings` (type: `array`):

Results of your manual / assistive-technology testing. They override automation per criterion: <code>{"sc": "2.4.3", "status": "fails|partially|passes|not-applicable|not-tested", "description": "Focus jumps to the footer after the search form", "pages": \["https://…"], "plannedFix": "…", "fixBy": "March 2027"}</code>.

## `organisationName` (type: `string`):

Who runs the website.

## `websiteName` (type: `string`):

Defaults to the host name.

## `websiteUrl` (type: `string`):

Defaults to the first audited page's origin.

## `statementScope` (type: `string`):

e.g. "the example.gov.uk website, excluding the planning portal subdomain".

## `contactEmail` (type: `string`):

Published organisational contact, e.g. accessibility@… (not a personal address).

## `contactPhone` (type: `string`):

Optional.

## `responseDays` (type: `integer`):

How quickly you reply to accessibility requests.

## `enforcementRegion` (type: `string`):

Used in the UK public-sector enforcement section.

## `testedBy` (type: `string`):

e.g. "our digital team using SiteVerdict automated checks and manual testing".

## `disproportionateBurden` (type: `array`):

Only if you have a documented assessment. One per line.

## `outOfScope` (type: `array`):

Adds the matching exemption text (UK public sector).

## `improvementPlan` (type: `string`):

Your roadmap text. Leave empty for a \[REVIEW] placeholder (or let the AI step draft one).

## `productName` (type: `string`):

Defaults to the website name.

## `productVersion` (type: `string`):

e.g. "October 2026 release".

## `productDescription` (type: `string`):

Used in the ACR and the EAA service description.

## `marketSurveillanceAuthority` (type: `string`):

Name of the authority in your Member State (EAA mode).

## `includeAAA` (type: `boolean`):

Adds Table 3 (Level AAA).

## `statementDate` (type: `string`):

Defaults to today.

## `devices` (type: `array`):

Viewports to test (live audits).

## `navigationTimeoutSecs` (type: `integer`):

Per page.

## `aiProvider` (type: `string`):

Rewrites each failure into plain English for the public statement and drafts the improvement plan, using YOUR OWN key. Only issue titles, descriptions and WCAG numbers are sent — never page content.

## `aiApiKey` (type: `string`):

Stored encrypted, never logged or output.

## `aiModel` (type: `string`):

Default: claude-sonnet-5-5 (Anthropic) or gpt-4.1-mini (OpenAI).

## `sampleMode` (type: `boolean`):

Generates all documents from two bundled real audit results (an inaccessible demo page and a GOV.UK page). No browser, no charges. If no start URL, audit dataset or manual findings are given, the run uses sample mode automatically, every row is marked isSampleData: true and the documents carry a SAMPLE DATA banner.

## Actor input object example

```json
{
  "jurisdiction": "uk-psbar",
  "startUrls": [
    {
      "url": "https://www.w3.org/WAI/demos/bad/before/home.html"
    }
  ],
  "crawl": false,
  "maxPages": 10,
  "manualFindings": [],
  "organisationName": "Example Council",
  "responseDays": 5,
  "enforcementRegion": "england-scotland-wales",
  "includeAAA": false,
  "devices": [
    "desktop",
    "mobile"
  ],
  "navigationTimeoutSecs": 45,
  "aiProvider": "none",
  "sampleMode": false
}
```

# Actor output Schema

## `results` (type: `string`):

No description

## `summary` (type: `string`):

No description

## `files` (type: `string`):

No description

# 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 = {
    "startUrls": [
        {
            "url": "https://www.w3.org/WAI/demos/bad/before/home.html"
        }
    ],
    "manualFindings": [],
    "organisationName": "Example Council"
};

// Run the Actor and wait for it to finish
const run = await client.actor("siteverdict/siteverdict-accessibility-statement-generator").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 = {
    "startUrls": [{ "url": "https://www.w3.org/WAI/demos/bad/before/home.html" }],
    "manualFindings": [],
    "organisationName": "Example Council",
}

# Run the Actor and wait for it to finish
run = client.actor("siteverdict/siteverdict-accessibility-statement-generator").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 '{
  "startUrls": [
    {
      "url": "https://www.w3.org/WAI/demos/bad/before/home.html"
    }
  ],
  "manualFindings": [],
  "organisationName": "Example Council"
}' |
apify call siteverdict/siteverdict-accessibility-statement-generator --silent --output-dataset

```

## MCP server setup

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

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/mi1SoJVYuUClQm7vU/builds/Q3C1xzWPf8t1MWtTr/openapi.json
