Accessibility Checker API
Audit a URL or HTML for WCAG 2.2 A / AA issues with axe-core: missing alt text, labels, link and button names, ARIA errors, headings and more.
Send html (page source) or a public url. The page is parsed into a DOM without a browser and checked with the axe-core rule engine (Deque, MPL-2.0) for the chosen WCAG level (a, aa default, aaa) plus best practices: image alt text, form labels, link and button names, document title and language, heading order, landmarks, lists, tables, ARIA roles and attribute values, duplicate ARIA ids, autocomplete values, zoom blocking in the viewport meta tag, iframes titles and more.
Each violation has the rule id, impact (critical, serious, moderate, minor), WCAG success criteria (e.g. 1.1.1), a help link, and up to max_nodes offending elements with their CSS selector, HTML snippet and what to fix. score (0-100) summarises the result; needs_review lists checks axe could not decide.
Rules that need a rendered page (colour contrast, target size, inline spacing, scrollable regions, focus order) are not run and are listed in not_checked; content added by JavaScript is not seen. Automated checks find only part of the WCAG issues, so also test manually. HTML is limited to 3 MB.
Parameters
| Name | In | Type | Required | Default | |
|---|---|---|---|---|---|
url | body|query | string | no | Public page to fetch (HTML up to 3 MB). Use html instead for pages behind a login. | |
html | body | string | no | Page source to check (or send it as a text/html body). | |
level | body|query | string | no | aa | WCAG level: a, aa or aaa. |
best_practices | body|query | boolean | no | true | Include axe best-practice rules (heading order, landmarks, empty headings…). |
max_nodes | body|query | number | no | 10 | Offending elements returned per rule (1-100). |
include_passes | body|query | boolean | no | false | Also list the rules that passed. |
experimental | body|query | boolean | no | false | Include axe experimental rules. |
Example
curl -X POST "https://apibox.io.vn/v1/a11y-check" \
-H "Authorization: Bearer YOUR_API_KEY" \
-H "Content-Type: application/json" \
-d '{"html":"<!doctype html><html><head><title>Shop</title></head><body><img src=\"logo.png\"><a href=\"/cart\"></a><form><input type=\"email\" placeholder=\"Email\"><button></button></form></body></html>"}'const res = await fetch('https://apibox.io.vn/v1/a11y-check', {
method: 'POST',
headers: {
Authorization: 'Bearer YOUR_API_KEY',
'Content-Type': 'application/json',
},
body: JSON.stringify({
"html": "<!doctype html><html><head><title>Shop</title></head><body><img src=\"logo.png\"><a href=\"/cart\"></a><form><input type=\"email\" placeholder=\"Email\"><button></button></form></body></html>"
}),
});
const data = await res.json();
console.log(data);import requests
res = requests.post(
"https://apibox.io.vn/v1/a11y-check",
headers={"Authorization": "Bearer YOUR_API_KEY"},
json={"html": "<!doctype html><html><head><title>Shop</title></head><body><img src=\"logo.png\"><a href=\"/cart\"></a><form><input type=\"email\" placeholder=\"Email\"><button></button></form></body></html>"},
timeout=30,
)
print(res.json())<?php
$ch = curl_init('https://apibox.io.vn/v1/a11y-check');
curl_setopt_array($ch, [
CURLOPT_RETURNTRANSFER => true,
CURLOPT_CUSTOMREQUEST => 'POST',
CURLOPT_HTTPHEADER => ['Authorization: Bearer YOUR_API_KEY', 'Content-Type: application/json'],
CURLOPT_POSTFIELDS => '{"html":"<!doctype html><html><head><title>Shop</title></head><body><img src=\\"logo.png\\"><a href=\\"/cart\\"></a><form><input type=\\"email\\" placeholder=\\"Email\\"><button></button></form></body></html>"}',
]);
$response = curl_exec($ch);
print_r(json_decode($response, true));Response
{
"source": "html",
"url": null,
"level": "AA",
"score": 75,
"issues": 8,
"by_impact": {
"critical": 2,
"serious": 2,
"moderate": 4,
"minor": 0
},
"rules": {
"checked": 83,
"failed": 7,
"needs_review": 1,
"not_checked": 8
},
"violations": [
{
"rule": "button-name",
"impact": "critical",
"level": "A",
"wcag": [
"4.1.2"
],
"best_practice": false,
"help": "Buttons must have discernible text",
"description": "Ensure buttons have discernible text",
"help_url": "https://dequeuniversity.com/rules/axe/4.14/button-name?application=axeAPI",
"count": 1,
"nodes": [
{
"target": "button",
"html": "<button></button>",
"failure": "Element does not have inner text that is visible to screen readers | aria-label attribute does not exist or is empty | …"
}
]
},
{
"rule": "image-alt",
"impact": "critical",
"level": "A",
"wcag": [
"1.1.1"
],
"best_practice": false,
"help": "Images must have alternative text",
"description": "Ensure <img> elements have alternative text or a role of none or presentation",
"help_url": "https://dequeuniversity.com/rules/axe/4.14/image-alt?application=axeAPI",
"count": 1,
"nodes": [
{
"target": "img",
"html": "<img src=\"logo.png\">",
"failure": "Element does not have an alt attribute | …"
}
]
},
"…"
],
"needs_review": [
{
"rule": "bypass",
"impact": "serious",
"help": "Page must have means to bypass repeated blocks",
"wcag": [
"2.4.1"
],
"…": "…"
}
],
"not_checked": [
{
"rule": "avoid-inline-spacing",
"wcag": [
"1.4.12"
],
"reason": "needs the CSS object model"
},
{
"rule": "color-contrast",
"wcag": [
"1.4.3"
],
"reason": "needs rendered colours and layout"
},
"…"
],
"engine": "axe-core 4.14.0 (static DOM, no layout)",
"ms": 34,
"note": "Static check without a browser: colour contrast, target size, focus order and anything that depends on CSS layout or scripts are not tested. …"
}
Use cases
- Check pages before launch for the European Accessibility Act or public-sector rules
- Add an accessibility gate to CI for static sites and templates
- Find images without alt text and unlabeled form fields across a site
- Produce a WCAG issue list for a client audit
FAQ
Is this the same as running axe in a browser?
It runs the same axe-core rules on a static DOM. Rules that need layout or computed colours (colour contrast, target size) cannot run and are listed in not_checked; content rendered by JavaScript is not included.
Which WCAG version is checked?
WCAG 2.0, 2.1 and 2.2 rules up to the level you choose (A, AA by default, or AAA), plus axe best-practice rules unless best_practices=false.
How is the score calculated?
It starts at 100 and subtracts a weight for each failing rule by impact (critical 10, serious 6, moderate 3, minor 1) relative to the number of rules checked. Use it to track progress, not as a compliance certificate.
Related APIs
URL Metadata
Fetch any URL and get its title, description, Open Graph and Twitter Card tags, favicon, canonical, feeds and JSON-LD as JSON.
H:HTTP Headers
See the HTTP status and every response header of a URL, with a summary of security headers like HSTS, CSP and X-Frame-Options.
301Redirect Checker
Follow every 301, 302, 307 and 308 redirect of a URL and get the full chain with status codes, the final URL and the number of hops.