Pa11y is your automated accessibility testing pal
Pa11y is your automated accessibility testing pal. It runs HTML CodeSniffer from the command line for programmatic accessibility reporting.
On the command line:
var pa11y = ;var test = ;test;
✨ 🔜 ✨ The Pa11y team is very excited to announce plans for the successor to Pa11y Dashboard and Pa11y Webservice, codename "Sidekick". Help us define the features that you want to see by visiting the proposal. ✨
Pa11y requires Node.js 4+ to run.
On a Mac, you can install the required dependency with Homebrew:
$ brew install node
Alternatively download pre-built packages from the Node.js website.
Depending on your flavour of Linux, you should be able to use a package manager to install the required dependency. Alternatively download pre-built packages from the Node.js website.
Windows users approach with caution – we've been able to get Pa11y running (Windows 7, Node 4) but only after installing Visual Studio and the Windows SDK (as well as Git, and Python). The Windows installation instructions for node-gyp are a good place to start.
Install Pa11y globally with npm:
npm install -g pa11y
This installs the
pa11y command-line tool:
Run an accessibility test against a URL:
Run an accessibility test against a file (absolute paths only, not relative):
Run a test with CSV reporting and save to a file:
pa11y --reporter csv > report.csv
Run Pa11y with the Section508 ruleset:
pa11y --standard Section508
The command-line tool uses the following exit codes:
0: Pa11y ran successfully, and there are no errors
1: Pa11y failed run due to a technical fault
2: Pa11y ran successfully but there are errors in the page
By default, only accessibility issues with a type of
error will exit with a code of
2. This is configurable with the
--level flag which can be set to one of the following:
error: exit with a code of
2on errors only, exit with a code of
0on warnings and notices
warning: exit with a code of
2on errors and warnings, exit with a code of
notice: exit with a code of
2on errors, warnings, and notices
none: always exit with a code of
The command-line tool can be configured with a JSON file as well as arguments. By default it will look for a
pa11y.json file in the current directory, but you can change this with the
pa11y --config ./path/to/config.json
For more information on configuring Pa11y, see the configuration documentation.
The ignore flag can be used in several different ways. Separated by semi-colons:
pa11y --ignore "warning;notice"
or by using the flag multiple times:
pa11y --ignore warning --ignore notice
Pa11y can also ignore notices, warnings, and errors up to a threshold number. This might be useful if you're using CI and don't want to break your build. The following example will return exit code 0 on a page with 9 errors, and return exit code 2 on a page with 11 errors.
pa11y --threshold 10
The command-line tool can report test results in a few different ways using the
--reporter flag. The built-in reporters are:
cli: output test results in a human-readable format
csv: output test results as comma-separated values
html: output test results as an HTML document
json: output test results as a JSON array
markdown: output test results as a Markdown document
You can also write and publish your own reporters. Pa11y looks for reporters in the core library, your
node_modules folder (with a naming pattern), and the current working directory. The first reporter found will be loaded. So with this command:
pa11y --reporter rainbows
The following locations will be checked:
A Pa11y reporter should export the following methods, and these should make use of
console to send output:
; // Called when pa11y starts; // Called when a technical error is reported; // Called when a debug message is reported; // Called when an information message is reported; // Called with the results of a test run
Reporters may also optionally export a
process method. This should accept the same arguments as the
results method but return the processed results rather than outputting them:
processresultsArray url; // Called with results by a user
You may find the following reporters useful:
1.0-json: output test results in the Pa11y 1.0 JSON format
Install Pa11y with npm or add to your
npm install pa11y
var pa11y = ;
Create a tester by initialising Pa11y with some options:
var test = ;
test.run function can then be used to run your test function against a URL:
The results that get passed into your test callback come from HTML CodeSniffer, and look like this:
code: 'WCAG2AA.Principle1.Guideline1_1.1_1_1.H30.2'context: '<a href=""><img src="example.jpg" alt=""/></a>'message: 'Img element is the only content of the link, but is missing alt text. The alt text should describe the purpose of the link.'selector: 'html > body > p:nth-child(1) > a'type: 'error'typeCode: 1code: 'WCAG2AA.Principle1.Guideline1_3.1_3_1.H49.B'context: '<b>Hello World!</b>'message: 'Semantic markup should be used to mark emphasised or special text so that it can be programmatically determined.'selector: '#content > b:nth-child(4)'type: 'warning'typeCode: 2code: 'WCAG2AA.Principle2.Guideline2_4.2_4_4.H77,H78,H79,H80,H81'context: '<a href="">Hello World!</a>'message: 'Check that the link text combined with programmatically determined link context identifies the purpose of the link.'selector: 'html > body > ul > li:nth-child(2) > a'type: 'notice'typeCode: 3
If you wish to transform these results with the command-line reporters, then you can do so in your code by requiring them in. The
markdown reporters all expose a
// Assuming you've already run tests, and the results// are available in a `results` variable:var htmlReporter = ;var html = htmlReporter;
Pa11y exposes a function which allows you to validate action strings before attempting to use them.
This function accepts an action string and returns a boolean indicating whether it matches one of the actions that Pa11y supports:
pa11y; // truepa11y; // false
Pa11y has lots of options you can use to change the way PhantomJS runs, or the way your page is loaded. Options can be set either on the Pa11y instance when it's created or the individual test runs. This allows you to set some defaults which can be overridden per-test:
// Set the default Foo header to "bar"var test =;// Run a test with the Foo header set to "bar"test;// Run a test with the Foo header overriddentest;
Below is a reference of all the options that are available:
Actions to be run before Pa11y tests the page. There are quite a few different actions available in Pa11y, the Actions documentation outlines each of them.
Note: actions are currently in a beta state and the API may change while we gather feedback.
Defaults to an empty array.
The accessibility standards that are allowed to be used. This can be modified to allow for custom HTML CodeSniffer standards.
Note: unless you're doing something particularly complicated, it's much easier and less error prone to use actions rather than
beforeScript. If you specify both, the
beforeScript will be dropped with a warning.
A function to be run before Pa11y tests the page. The function accepts three parameters:
pageis the phantomjs page object, documentation for the phantom bridge can be found here
optionsis the finished options object used to configure pa11y
nextis a callback function
A CSS selector to hide elements from testing, selectors can be comma separated.
Elements matching this selector will be hidden from testing by styling them with
The path or URL to source HTML CodeSniffer from.
Defaults to a local copy of HTML CodeSniffer, found in lib/vendor/HTMLCS.js.
An array of result codes and types that you'd like to ignore. You can find the codes for each rule in the console output and the types are
Defaults to an empty array.
An object which implements the methods
info which will be used to report errors and test information.
Each of these defaults to an empty function.
A key-value map of request headers to send when testing a web page.
Defaults to an empty object.
A key-value map of settings to add to the PhantomJS page. For a full list of available settings, see the PhantomJS page settings documentation.
userAgent: 'pa11y/<version> (truffler/<version>)'
The viewport width and height in pixels. The
viewport object must have both
width: 1024height: 768
A key-value map of settings to initialise PhantomJS with. This is passed directly into the
phantom module – documentation can be found here. You can pass PhantomJS command-line parameters in the
phantom.parameters option as key-value pairs.
phantom.port is not specified, a random available port will be used.
The root element for testing a subset of the page opposed to the full document.
null, meaning the full document will be tested.
The accessibility standard to use when testing pages. This should be one of
WCAG2AAA (or match one of the standards in the
The time in milliseconds that a test should be allowed to run before calling back with a timeout error.
The time in milliseconds to wait before running HTML CodeSniffer on the page.
HTML string to verify is present in the page source HTML. Could be used to ascertain that intended page is being tested (as opposed to error page) by using
<title> tags and content (as below), or that a specific element is present.
Actions are additional interactions that you can make Pa11y perform before the tests are run. They allow you to do things like click on a button, enter a value in a form, wait for a redirect, or wait for the URL fragment to change:
Below is a reference of all the available actions and what they do on the page. Some of these take time to complete so you may need to increase the
timeout option if you have a large set of actions.
This allows you to click an element by passing in a CSS selector. This action takes the form
click element <selector>. E.g.
This allows you to set the value of a text-based input or select box by passing in a CSS selector and value. This action takes the form
set field <selector> to <value>. E.g.
This allows you to check or uncheck checkbox and radio inputs by passing in a CSS selector. This action takes the form
check field <selector> or
uncheck field <selector>. E.g.
This allows you to pause the test until a condition is met, and the page has either a given fragment, path, or URL. This will wait until Pa11y times out so it should be used after another action that would trigger the change in state. You can also wait until the page does not have a given fragment, path, or URL using the
to not be syntax. This action takes one of the forms:
wait for fragment to be <fragment>(including the preceding
wait for fragment to not be <fragment>(including the preceding
wait for path to be <path>(including the preceding
wait for path to not be <path>(including the preceding
wait for url to be <url>
wait for url to not be <url>
Run Pa11y on a URL and output the results. See the example, or run it with:
Step through some actions before Pa11y runs. This example logs into a fictional site then waits until the account page has loaded before running Pa11y. See the example.
Inject a script before Pa11y runs. This example logs into a fictional site then waits until the account page has loaded before running Pa11y. See the example.
Common questions about Pa11y are answered here.
page.headers option either in your JS code or in your config file:
page.settings option either in your JS code or in your config file to set a username and password:
actions option to specify a series of actions to execute before Pa11y runs the tests:
You can also use the
beforeScript option for this, but it can be complicated and error-prone. See the [
beforeScript example] for more information.
phantom.parameters option either in your JS code or in your config file:
These match PhantomJS command-line parameters.
proxy-type can be set to
For simple interactions, we recommend using actions. For more complex interactions, use the
beforeScript option either in your JS code or in your config file to simulate the interactions before running Pa11y.
In this example, additional content is loaded via ajax when a button is clicked.
Once the content is loaded the
aria-hidden attribute switches from
Pa11y uses PhantomJS as a headless web browser to load the DOM content and can only analyze what is provided. If parts of the DOM are been loaded after the document is first generated, you may get results that differ from the bookmarklet which runs in the browser and can test against the complete DOM.
If you use Pa11y and HTML CodeSniffer CLI you will find that you get the same results, which will both differ from the bookmarklet, a similar issue was highlighted by HTML CodeSniffer.
We are aware of an issue with regard to iframe content, PhantomJS doesn't automatically provide access to the inner content of iframes, and so Pa11y doesn't currently support testing against iframe content from a parent page context. Any page that makes use of iframes, e.g. for displaying ads, may show different results on Pa11y than those when running HTML_CodeSniffer in the browser.
If you do need to test the contents of an iframe, run Pa11y against the iframe source URL directly.
Pa11y doesn't check the hover state. Instead, you must test the contrast of the hover state for links manually.
There are many ways to contribute to Pa11y, we cover these in the contributing guide for this repo.
If you're ready to contribute some code, clone this repo locally and commit on a separate branch. Please write unit tests for your changes, and check that everything works by running the following before opening a pull-request:
Pa11y major versions are normally supported for 6 months after their last minor release. This means that patch-level changes will be added and bugs will be fixed. The table below outlines the end-of-support dates for major versions, and the last minor release for that version.
We also maintain a migration guide to help you migrate.
|❔||Major Version||Last Minor Release||Node.js Versions||Support End Date|
If you're opening issues related to these, please mention the version that the issue relates to.
Pa11y is licensed under the Lesser General Public License (LGPL-3.0).
Copyright © 2013–2017, Team Pa11y