About CWAC
Learn about CWAC, how to set up a scan, and review the results
What is CWAC?
CWAC stands for Centralised Web Accessibility Checker. It's pronounced "quack".
CWAC is software designed to scan websites for potential web accessibility issues. It was built by and is maintained by the Government Chief Digital Officer (GCDO). The source code is open source under a GPL-3.0 licence and is also available on GitHub.
Work is underway to make this tool more usable and accessible. Please help us understand how you use this tool, and how it could be improved by sending us an email.
Getting started
There are 4 simple steps to follow:
Step 1. Set URL lists
Go to the “Set URL lists” page where you can create a list of all the website URLs you want to scan. This list can be saved so you can use it to run scans in the future. This list can also be edited and deleted.
- Start by selecting the “Add new URL list” button
- Name the list
- Add your URLs to the “Content” text field in CSV format. The first line is for headers, and must include the "url" header. You can add as many URLs as you like.
- Save your URL list
Example URL list content
url
https://www.corrections.govt.nz/
https://aroturuki.govt.nz/
Handy hints
- The text is not case-sensitive
- CWAC will start by visiting each listed URL, and then crawl the page for more links to visit up to the limit set in the configuration setting
- URL pages are not picked at random, they're scanned from the links of the pages that CWAC has already visited
- If you want CWAC to scan specific pages, then add these in as a line item
Step 2: Configure CWAC
There is a default configuration as part of CWAC named “default”, but you can choose to add a new configuration if you like. If you are new to CWAC and getting used to the setup, you can just use the default configuration. This means you can skip this section.
However, if you want to adjust aspects of the scan such as time-out settings for scans, and the detail of how CWAC will “crawl” across the URLs, go to the “Configure CWAC” page. You can also define which types of audits can be run e.g. axe-core, language or focus indicator. If you do want to add or edit the configurations, read the Editing configurations section below for more details.
Step 3: Start a scan
Go to the “Start a scan” page. On this page you can select the scan configuration and URL lists/groups you would like to use. You can also schedule a scan for a future time and date.
- Start by selecting which URL lists you would like to scan
- Select a configuration for the scan.
- Select a time and date that you want the scan to run. This is an optional step.
- Select “Start a scan” button
Once the scan is started, the screen will display the scanning progress. You do not need to wait and watch this scan. You have automatically been added to the “Watch” list and you will receive an email once the scan is complete.
Handy hints
- There is a limit to the number of URLs you can scan — it is currently set to 1000
- You can choose to “Unwatch” a scan, but this will mean you won’t receive an email notification when the scan is completed.
Step 4: View scans
When you are ready to view the scans, go to the “View scans” section. This section displays scheduled, in progress and completed scans. All the scan results are in a ‘collapsed’ state by default.
- Find your scan under the “Completed scans” heading — the latest scans are at the top of the list
- Select the scan results to expand the content
- Download the individual scan files, or
- Select the “View results” button to view the scan results
- Select which results you would like to view from the drop down selector
- Download all the files to your computer if needed
Each type of scan is available to download, by selecting each file option. Alternatively you can view the scan results within a CWAC page by selecting the “View results” link. The results page allows you to select which type of scan result you would like to view from the drop down selector. You can also download all the files in a bundled zip file to your local computer.
Handy hints
- All scans are listed by showing the latest scan at the top of each heading section.
- Find your scan under the “Completed scans” section, and select it to view all the scan details.
- You can use the “Expand all” and “Collapse all” buttons to show and hide all the scan details. You can also show and hide an individual scan.
- You can download individual scans results or a zip file of all the scan results
Editing configurations
You can set up different types of configurations for how a scan runs inside CWAC. CWAC is configured via a JSON file. Some properties are managed by the platform and not editable by you. You can safely edit the remaining configuration settings without the risk of causing an error.
If you create a new configuration, it will automatically populate with the default content to get you started. The following settings are editable and change how CWAC performs the scan.
There are 5 types of settings:
- General
- Crawl behaviour
- Timing
- Audit settings
- Audit plugins
General
max_links_per_domain
- Type:
integer- Default:
50
The maximum number of pages CWAC will crawl per domain. Increase this for more thorough coverage; decrease it to keep scans fast or to limit load on target servers.
Example
"max_links_per_domain": 50
Crawl behaviour
follow_robots_txt
- Type:
boolean- Default:
true
Whether CWAC respects robots.txt directives. Set to false only when you have
explicit permission from the site owner to crawl disallowed paths.
Example
"follow_robots_txt": true
only_allow_https
- Type:
boolean- Default:
true
When true, CWAC will only crawl HTTPS URLs and skip any HTTP links it
encounters. Recommended to keep enabled; disable only if you need to audit
HTTP-only sites.
Example
"only_allow_https": true
shuffle_base_urls
- Type:
boolean- Default:
true
Randomises the order in which base URLs are visited. Useful when scanning many sites to distribute load over time rather than hammering one domain at a time.
Example
"shuffle_base_urls": true
filter_to_organisations
- Type:
array of strings- Default:
[]
Restricts crawling to a named subset of organisations. Leave empty to crawl all configured URLs. Useful when running a full configuration but only wanting results for specific organisations.
Example
"filter_to_organisations": ["Ministry of Example", "Example City Council"]
filter_to_urls
- Type:
array of strings- Default:
[]
Restricts crawling to specific URLs. Leave empty to crawl all configured URLs. Useful for targeted re-scans or debugging specific pages.
Example
"filter_to_urls": ["https://www.example.govt.nz/", "https://www.example.govt.nz/contact-us"]
record_unexpected_response_codes
- Type:
boolean- Default:
true
When true, HTTP responses with unexpected status codes (such as 404 or 500)
are recorded in the audit output. Useful for identifying broken pages alongside
accessibility issues.
Example
"record_unexpected_response_codes": true
Timing
script_timeout
- Type:
number(seconds)- Default:
15
How long to wait for JavaScript to finish executing on a page. Increase for pages with heavy client-side rendering; decrease to fail faster on unresponsive pages.
Example
"script_timeout": 15
page_load_timeout
- Type:
number(seconds)- Default:
10
How long to wait for a page to finish loading before timing out. Increase if target sites are slow; decrease to keep scans moving on unresponsive pages.
Example
"page_load_timeout": 10
delay_between_page_loads
- Type:
number(seconds)- Default:
0.2
Pause between loading consecutive pages. Increase this to be more polite to target servers, especially on shared or production infrastructure.
Example
"delay_between_page_loads": 0.2
delay_between_viewports
- Type:
number(seconds)- Default:
0.1
Pause between testing different viewport sizes on the same page. Increase if you see inconsistent results between viewports.
Example
"delay_between_viewports": 0.1
delay_after_page_load
- Type:
number(seconds)- Default:
0.1
Additional pause after a page loads before auditing begins. Increase for pages that render content after the load event fires.
Example
"delay_after_page_load": 0.1
Audit settings
perform_header_check
- Type:
boolean- Default:
true
When true, CWAC checks HTTP response headers (such as Content-Language) as
part of the audit. Disable if header checks are not relevant to your audit
scope.
Example
"perform_header_check": true
force_open_details_elements
- Type:
boolean- Default:
true
When true, CWAC forces details elements open before auditing, ensuring
hidden content inside them is also checked. Recommended to keep enabled.
Example
"force_open_details_elements": true
viewport_sizes
- Type:
object
Defines the named viewport dimensions used during audits. Each key is a viewport
name and its value has width and height in pixels.
{
"small": { "width": 320, "height": 450 },
"medium": { "width": 1280, "height": 800 }
}
Adjust or extend these to match the breakpoints most relevant to your users.
Example
"viewport_sizes": { "large": { "width": 1440, "height": 900 } }
Audit plugins
Each plugin lives under audit_plugins and controls a specific type of check.
All plugins share a enabled boolean to turn them on or off.
axe_core_audit
Runs axe-core accessibility rules against each page.
| Property | Type | Default | Description |
|---|---|---|---|
enabled |
boolean |
true |
Enable or disable this plugin. |
best-practice |
boolean |
false |
When true, includes axe-core's best-practice rules in addition to WCAG violations. Enable for more thorough (but noisier) results. |
Example
"axe_core_audit": {
"enabled": true,
"best-practice": false
}
language_audit
Checks page language attributes and, optionally, analyses the reading level and sentiment of page content.
| Property | Type | Default | Description |
|---|---|---|---|
enabled |
boolean |
true |
Enable or disable this plugin. |
run_sentiment_analysis |
boolean |
false |
When true, performs sentiment analysis on page text. Enable if you want insight into tone and readability beyond structural accessibility. |
Example
"language_audit": {
"enabled": true,
"run_sentiment_analysis": false
}
reflow_audit
Tests whether page content reflows correctly at small viewport widths, as required by WCAG 1.4.10 Reflow.
| Property | Type | Default | Description |
|---|---|---|---|
enabled |
boolean |
true |
Enable or disable this plugin. |
viewport_to_test |
string |
"small" |
Which named viewport (from viewport_sizes) to use for reflow testing. |
screenshot_failures |
boolean |
false |
When true, captures a screenshot of pages that fail the reflow check. Useful for debugging but increases storage use. |
Example
"reflow_audit": {
"enabled": true,
"viewport_to_test": "small",
"screenshot_failures": false
}
focus_indicator_audit
Checks whether keyboard focus indicators are visible as users tab through a page.
| Property | Type | Default | Description |
|---|---|---|---|
enabled |
boolean |
false |
Enable or disable this plugin. Disabled by default as it requires tuning. |
root_element_css_selector |
string |
"main" |
CSS selector for the element to audit. Scopes tab testing to a specific region of the page. |
pre_tab_key_presses |
integer |
0 |
Number of Tab key presses to send before auditing begins. Use to skip past navigation or cookie banners. |
max_tab_key_presses |
integer |
5 |
Maximum number of Tab key presses to test. Increase for pages with many interactive elements. |
Example
"focus_indicator_audit": {
"enabled": false,
"root_element_css_selector": "main",
"pre_tab_key_presses": 0,
"max_tab_key_presses": 5
}
screenshot_audit
Captures screenshots of each audited page.
| Property | Type | Default | Description |
|---|---|---|---|
enabled |
boolean |
false |
Enable or disable this plugin. Disabled by default due to storage overhead. Enable when you want a visual record of pages at the time of auditing. |
Example
"screenshot_audit": {
"enabled": false
}
element_audit
Audits specific elements matched by a CSS selector across all pages.
| Property | Type | Default | Description |
|---|---|---|---|
enabled |
boolean |
false |
Enable or disable this plugin. |
target_element_css_selector |
string |
"input:not([type='search'])" |
CSS selector for the elements to audit. Change this to target the specific element type relevant to your audit. |
Example
"element_audit": {
"enabled": false,
"target_element_css_selector": "input:not([type='search'])"
}