Accessibility audit
Knowing a page 'has accessibility issues' is nearly useless; knowing that a specific button has no accessible name and lives at a specific point in the DOM is what actually gets fixed. This endpoint scans a URL against WCAG success criteria and returns each violation tied to the exact element that caused it, so a developer opens the report and starts editing instead of hunting.
Run it online
Run this on our servers with your account. Free tools run in your browser; this one bills your KIT balance per the price above.
The distance between a policy and a page that works
Most organizations already have an accessibility policy on paper; far fewer have verified that any given page actually meets it. The gap isn't usually neglect — it's that manual accessibility review is slow and specialized, while a page changes every time a component is edited, a new image is added without alt text, or a form field loses its label during a redesign. web.accessibility exists to make checking a page as fast as publishing it, so accessibility can be verified on the same schedule as everything else instead of once a year during an audit.
What a scan returns
POST /web/accessibility with a URL, get a task_id back immediately, and receive a structured report by signed webhook or a signed link once the async job finishes. Each violation is tied to a WCAG success criterion, a severity, a plain-language description of the problem, and a selector pointing at the exact element on the page responsible for it — an image missing alt text, a form input with no associated label, text with contrast too low against its background — so the fix is located, not just described in the abstract.
What automated scanning can and can't catch
Automated accessibility testing has matured over the past decade into a reliable first pass for a well-defined set of checks — missing alt text, color contrast, form labeling, heading structure, ARIA misuse — the kind of issues that are objectively detectable from markup alone. It complements rather than replaces a human review with assistive technology, since some criteria, like whether alt text is actually meaningful or a keyboard flow feels natural, require judgment a script can't make; the scan is the fast, repeatable layer that catches the checkable majority so human review time goes toward what genuinely needs it.
Where it fits into shipping software
Teams that treat accessibility as a build requirement rather than an afterthought run this on new pages before launch and again after significant redesigns, since a page that passed a review once can silently regress the next time a component library gets updated. Priced per request plus per URL, scanning a batch of pages before a release costs in direct proportion to how many pages you check, which makes it realistic to cover a whole site rather than spot-checking a handful of pages and hoping the rest hold up.
What you can do with it
Pre-launch page verification
A development team scans every new page before it ships to catch missing alt text, unlabeled form fields and contrast issues while they're still cheap to fix.
Post-redesign regression check
A team re-scans key pages after a visual redesign to confirm the new component library didn't quietly reintroduce accessibility violations that had been fixed before.
Vendor and procurement due diligence
An organization scans a vendor's product pages before signing a contract to document accessibility gaps as part of procurement review.
Ongoing site-wide monitoring
A large content site schedules recurring scans across its most-trafficked pages so violations introduced by content editors get caught quickly.
FAQ
How do I test a page for accessibility with the API?
POST the page URL to /web/accessibility, keep the returned task_id, and collect the violation report by webhook or a signed link valid for 24 hours.
Is the accessibility testing API free?
No, there is no free tier or trial; it costs $0.040 per request plus $0.001 per URL, and a failed task is never charged.
Does the report show which element caused each violation?
Yes, each violation includes a selector pointing at the specific element on the page responsible for it, not just a description of the problem.
Does passing this scan mean a page is fully WCAG compliant?
It confirms the page passes the checks that are automatically detectable; some WCAG criteria require human judgment and aren't fully verifiable by any automated scan alone.
Which WCAG criteria does it check?
The set of success criteria that are reliably detectable from markup, such as alt text, color contrast, form labeling, heading structure and ARIA usage; check the endpoint reference for the current full list.
Can I scan multiple pages at once?
Yes, it's priced per request plus per URL, and you can queue a request per page for full-site coverage.
Is this endpoint live yet?
Yes, it's live and accepting requests now.
Is the scanned page data kept afterward?
No, page content and results are deleted after the retention window and are never used for training.
For developers — API access
Everything on this page is available programmatically. This section is for teams who want to wire it into their own systems; everyone else can just use the tool above.
API endpoint
Prefer to automate it? One authenticated POST creates the task; the result comes back by webhook or a signed link. The same capability also runs here on the web, and soon from our app, email and Telegram.
Call it from your stack
curl -X POST https://api.kit.forhosting.com/web/accessibility \
-H "Authorization: Bearer $KIT_KEY" \
-H "Content-Type: application/json" \
-d '{"url":"https://ejemplo.com"}'const res = await fetch("https://api.kit.forhosting.com/web/accessibility", {
method: "POST",
headers: {
"Authorization": `Bearer ${process.env.KIT_KEY}`,
"Content-Type": "application/json"
},
body: JSON.stringify({
"url": "https://ejemplo.com"
})
});
const { task_id } = await res.json();import os, requests
res = requests.post(
"https://api.kit.forhosting.com/web/accessibility",
headers={"Authorization": f"Bearer {os.environ['KIT_KEY']}"},
json={
"url": "https://ejemplo.com"
},
)
task_id = res.json()["task_id"]<?php
$res = file_get_contents("https://api.kit.forhosting.com/web/accessibility", false, stream_context_create([
"http" => [
"method" => "POST",
"header" => "Authorization: Bearer " . getenv("KIT_KEY") . "\r\nContent-Type: application/json",
"content" => '{"url":"https://ejemplo.com"}',
],
]));
$task = json_decode($res, true);body := bytes.NewBufferString(`{"url":"https://ejemplo.com"}`)
req, _ := http.NewRequest("POST", "https://api.kit.forhosting.com/web/accessibility", body)
req.Header.Set("Authorization", "Bearer "+os.Getenv("KIT_KEY"))
req.Header.Set("Content-Type", "application/json")
res, _ := http.DefaultClient.Do(req)Example request
{
"url": "https://ejemplo.com"
}Example response
{
"task_id": "tsk_a1b2c3d4e5f6a1b2c3d4e5f6",
"type": "web.accessibility",
"status": "queued",
"_links": {
"result": "/tasks/tsk_…/result"
}
}The API is asynchronous: the call returns a task_id immediately and the result arrives by webhook. Polling is capped at 1 req/s per task.
Pricing
Published price — no tokens, no invented credits. A failed task is never charged.
Limits
timeout_sec | 30 |
max_crawl_pages | 25 |
Errors
| HTTP | Code | Meaning |
|---|---|---|
401 | unauthorized | Missing or invalid API key. |
402 | insufficient_balance | Your balance doesn't cover the task price. |
404 | unknown_type | That task type doesn't exist. |
429 | rate_limited | Too many requests. Use the webhook instead of polling. |
422 | task_failed | The task failed after 3 retries. You are never charged for it. |