US Government Title II ADA Accessibility Audit
Pricing
from $45.00 / 1,000 page auditeds
US Government Title II ADA Accessibility Audit
WCAG 2.1 AA audit for US state/local government sites, with a Title II (28 CFR Part 35) legal report: deadline, all five scoping exceptions, and the affirmative defense. Real selectors, screenshots, executive summary. Automated scan, not legal advice. No charge on failures.
Pricing
from $45.00 / 1,000 page auditeds
Rating
0.0
(0)
Developer
Barak Eliov
Maintained by CommunityActor stats
0
Bookmarked
2
Total users
1
Monthly active users
a month ago
Last modified
Categories
Security
Limited permissionsShare
Audits US state/local government websites against WCAG 2.1 AA in a real Chromium browser, using the axe-core engine (MIT, Deque Systems), and produces a Title II legal-citation PDF report: the DOJ's population-based compliance deadline, all five scoping exceptions (28 CFR 35.201), and the non-strict-liability affirmative defense (28 CFR 35.204). Automated scan only, not legal advice.
This is v1 (the scope approved in SPEC.md). See "What's not in v1 yet" below.
What this Actor does
- Audits every URL you supply at WCAG 2.1 Level A and AA - the exact minimum 28 CFR 35.200(b)(1)-(2) requires for public entities covered by Title II of the Americans with Disabilities Act.
- Produces a Title II legal-citation PDF with:
- A one-page executive summary (readable in under 60 seconds by a city council member or procurement officer): the applicable compliance deadline, a compliance-posture percentage (pages with zero critical/serious findings), and the top risk items - framed explicitly as a summary of automated-scan results, never a certification.
- The applicable compliance deadline, sourced to the DOJ's April 2026 Interim Final Rule (document 2026-07663), with an explicit note that its comment period closed June 22, 2026 and it is not yet finalized.
- All five scoping exceptions (28 CFR 35.201(a)-(e)) - archived content, preexisting conventional electronic documents, third-party-posted content, individualized password-protected documents, and preexisting social media posts.
- The affirmative defense (28 CFR 35.204): a public entity may claim fundamental alteration or undue financial/administrative burden, with the burden of proof on the entity - stated without implying strict/absolute liability.
- Every violation mapped to its WCAG success criterion, screenshots, and a batch rollup.
- Issues recurring across multiple sites in the same batch - see "Cross-site recurring issues" below.
- Never charges for a failed or blocked audit.
What makes this different from the global WCAG-audit Actors on Apify
No other Apify Actor - including this Actor's own generic English sibling
(elab/website-accessibility-wcag-audit-api) and the one federal-only "government" adjacent Actor
(malonestar/gsa-site-scanning-auditor, which covers only ~29,600 federal .gov sites via a shallower,
non-axe-core engine) - cites the DOJ Title II legal text, its population-based deadlines, its five scoping
exceptions, or its affirmative defense. Confirmed by reading all three closest incumbents' live
READMEs/schemas (see SPEC.md section 2).
Executive summary (read this first)
The legal PDF opens with a one-page executive summary - deliberately framed as a summary of automated-scan results, never a pass/fail certification: the applicable deadline statement, a compliance-posture percentage, the top risk items, and (for multi-site batches) the cross-site recurring issues below. The full legal citation and per-page findings follow it.
Cross-site recurring issues (for COGs and state municipal leagues)
When a batch covers 2 or more distinct hostnames (e.g. a council of governments or a state municipal
league auditing many member-city sites in one run), the summary row's recurringAcrossSites field and the
legal report's executive summary both list axe-core rules confirmed as violations on multiple sites -
useful because many municipal sites share the same vendor CMS/template, so one fix often applies to every
affected site. This is a mechanical count of recurring rule IDs across hostnames, computed from already-
confirmed violations - not a legal determination and not a per-finding scoping-exception
classification (see "What this Actor will never auto-decide" below). Empty for single-site batches.
What this Actor will never auto-decide
Whether any of the five scoping exceptions (28 CFR 35.201) or the affirmative defense (28 CFR 35.204) applies to a specific page or document requires human legal judgment. This Actor never attempts to auto-classify a finding against a scoping exception or the affirmative defense - those are stated as general legal content in the report, not as a per-row flag. Consult a lawyer and/or a certified accessibility auditor before relying on this report for compliance purposes.
Important legal disclaimer (read before relying on the report)
This report is an automated scan (axe-core on a real browser). It is not a certified legal audit, not a legal opinion, not an official conformance certificate, and not a DOJ determination of Title II compliance. It does not guarantee any legal outcome or full compliance with 28 CFR Part 35 Subpart H.
Standing legal-monitoring note
The April 26, 2027 / April 26, 2028 compliance dates are correct only as amended by the DOJ's April
2026 Interim Final Rule (document 2026-07663). That rule's public comment period closed June 22, 2026 and
it is not yet finalized - if DOJ issues a final rule that changes any date or exception, this Actor's
legal content (src/legalContentUs.ts) must be updated before the next report is trusted. The original
2024 final rule's earlier dates no longer apply and never appear anywhere in this Actor's output.
Input example
{"urls": ["https://www.example-city.gov"],"wcagLevel": "wcag21aa","entityPopulationTier": "50000_or_more","entityName": "City of Example","generateLegalReport": true}
Input defaults
Every input field has a default. .actor/input_schema.json is the authoritative source; this table is
generated from it and the defaults below match that file exactly.
| Field | Type | Default | Meaning |
|---|---|---|---|
urls | array | ["https://www.usa.gov"] | Public page URLs to audit, one audit per URL (up to 100 per run). No crawling. |
wcagLevel | string | "wcag21aa" | WCAG level to check. wcag21aa is the minimum 28 CFR 35.200(b)(1)-(2) requires. |
entityPopulationTier | string | "unknown" | Population tier of the audited entity, used only to state the correct deadline. Never inferred from a URL. |
entityName | string | "" | Optional, purely cosmetic entity name for the legal report's cover page. |
viewport | string | "desktop" | Screen preset: desktop, tablet, mobile, or custom. |
viewportWidth | integer | 1280 | Custom viewport width in px (used only when viewport is custom). |
viewportHeight | integer | 800 | Custom viewport height in px (used only when viewport is custom). |
includeScreenshots | boolean | true | Element screenshot per violation plus one full-page screenshot per URL. |
includeIncomplete | boolean | true | Also return axe-core checks that need human review (status = incomplete). |
includePasses | boolean | false | Also return the count of rules that passed. |
outputMode | string | "both" | Row shapes: perPage, flat, or both. One page-audited charge per successful page in every mode. |
generateLegalReport | boolean | true | Generate the Title II legal-citation PDF report for the run (charged only on success). |
generatePdfReport | boolean | false | Also generate a plain WCAG-only PDF report, no legal citation (charged only on success). |
waitForSelector | string | "" | Optional CSS selector to wait for before auditing. Empty means no wait. |
waitUntil | string | "load" | Navigation readiness: load, domcontentloaded, or networkidle. |
timeoutSecs | integer | 30 | Per-URL time budget in seconds for navigation, audit and screenshots. |
proxyConfiguration | object | {"useApifyProxy":true} | Apify Proxy settings used for the audit requests. |
maxConcurrency | integer | 5 | Maximum number of pages audited in parallel within one run. |
Output example
The dataset has three row shapes, distinguished by rowType.
Page row (one per audited URL):
{"rowType": "page","url": "https://www.example-city.gov","finalUrl": "https://www.example-city.gov/","status": "success","wcagLevel": "wcag21aa","viewport": "desktop","score": 88,"violationCount": 2,"incompleteCount": 0,"passCount": 0,"violationsByImpact": { "critical": 0, "serious": 0, "moderate": 2, "minor": 0 },"fullPageScreenshotUrl": "https://api.apify.com/v2/key-value-stores/.../records/fullpage-....png","waitForSelectorTimedOut": false,"errorCategory": null,"errorMessage": null,"auditedAt": "2026-10-07T12:00:00.000Z","engineVersion": "4.13.0"}
Violation row (one per individual finding, when outputMode is flat/both):
{"rowType": "violation","pageUrl": "https://www.example-city.gov","ruleId": "image-alt","impact": "critical","status": "violation","description": "Images must have alternate text","helpText": "Add an alt attribute","helpUrl": "https://dequeuniversity.com/rules/axe/4.13/image-alt","wcagCriteria": ["1.1.1"],"selector": "#logo","htmlSnippet": "<img id=\"logo\">","screenshotUrl": "https://api.apify.com/v2/key-value-stores/.../records/violation-....png","nodeCount": 1}
Summary row (exactly one per run, also saved to the key-value store as batchSummary):
{"rowType": "summary","totalPagesAudited": 1,"totalPagesFailed": 0,"totalViolations": 1,"violationsByImpact": { "critical": 1, "serious": 0, "moderate": 0, "minor": 0 },"topFailingRules": [{ "ruleId": "image-alt", "pageCount": 1 }],"pdfReportUrl": null,"legalReportUrl": "https://api.apify.com/v2/key-value-stores/.../records/legal-report-....pdf","applicableDeadline": null,"titleIICitation": {"regulation": "28 CFR Part 35 Subpart H (ADA Title II)","standard": "WCAG 2.1 Level A and AA (28 CFR 35.200(b)(1)-(2))","deadlineSource": "Current compliance dates per the DOJ's April 2026 Interim Final Rule (document 2026-07663); original 2024 final rule dates differ and no longer apply. IFR comment period closed June 22, 2026 - re-verify once DOJ issues a final rule.","scopingExceptions": "28 CFR 35.201(a)-(e): archived web content; preexisting conventional electronic documents not needed for current services; third-party-posted content without a contractual/licensing arrangement; individualized password-protected documents about a specific individual; preexisting social media posts.","affirmativeDefense": "28 CFR 35.204: a public entity may claim fundamental alteration or undue financial/administrative burden as a defense, with the burden of proof on the entity and a written-determination requirement. Compliance is not absolute or strict - this defense exists.","sources": ["https://www.govinfo.gov/ (28 CFR 35.200-35.204)", "https://public-inspection.federalregister.gov/2026-07663.pdf"],"disclaimer": "This report is an automated scan, not a legal opinion or an official conformance certificate."},"recurringAcrossSites": []}
applicableDeadline is null above because entityPopulationTier was left at its default, "unknown" -
the legal report then states both deadlines with an explicit prompt to confirm classification, never
silently defaulting to one. Set entityPopulationTier to get a single dated applicableDeadline.
recurringAcrossSites is populated only when the batch covers 2+ distinct hostnames and a rule recurs on
2 or more of them - see "Cross-site recurring issues" above.
Errors (never silent, never charged)
| Category | When |
|---|---|
invalid_url | Malformed URL, non-http(s) URL, or the URL resolves to a private/link-local/reserved IP address (SSRF protection, always on) |
not_found | DNS failure, connection refused, 404/410 |
blocked | 401/403/429 response, or a Chromium block error (e.g. ERR_BLOCKED_BY_RESPONSE) - common on state/local government CDN/WAF setups (Akamai/Incapsula). Never retried |
timeout | Navigation, the axe-core audit, or screenshot capture exceeded timeoutSecs combined |
render_error | Browser crash or an unclassified render failure |
upstream_changed | 5xx upstream server error |
A failed page is never charged. A legal report that cannot be produced (zero pages succeeded in the
batch) is not charged either - page-audited charges for pages that did succeed in the same batch are
unaffected.
Report size limits (dataset vs. PDF)
With outputMode flat or both, the dataset is complete: every violation/incomplete finding for every
URL is a full row, regardless of batch size. The limits below apply only to what's embedded in full detail
(HTML snippet + screenshot image) inside the PDF report body (generatePdfReport and/or
generateLegalReport):
- Per page: at most 20 findings embedded in full, confirmed violations before "needs manual review" items, most severe first.
- Per batch: a shared ceiling of 200 findings embedded in full across the whole run (up to the 100-URL-per-run maximum).
- Whatever is held back is never silently dropped - the report prints exactly how many additional findings exist on that page and how many of them are confirmed violations vs. items needing manual review, with a pointer to the full dataset.
- PDF rendering has an internal 3-minute outer deadline for the whole batch. If exceeded, generation
is aborted, logged, and not charged - page-level
page-auditedcharges already applied in the same run are unaffected.
This cap is ported unchanged from the already-live generic sibling (src/reportCaps.ts), where it fixed a
real unbounded-PDF-cost bug (docs/lessons.md #1) - never reintroduced or re-broken here.
Pay-per-event pricing
| Event key | When |
|---|---|
page-audited | One page successfully audited, including screenshots |
legal-report-generated | The Title II legal-citation report was produced successfully (default: on) |
report-generated | The plain WCAG-only PDF report was produced successfully (default: off) |
Every event name is checked against Apify Console's event-key charset (^[a-zA-Z0-9_-]{1,256}$, no
spaces) in tests/events.test.ts before a build is considered done.
Local development / Apify run
npm installnpx playwright install chromium # one-timenpm run typechecknpm testnpm run buildapify run --input-file smoke-input.json --purge
Use with AI agents / MCP
Call with urls as an array (never comma-separated). Check rowType first, then status/errorCategory
on page rows. summary.legalReportUrl, summary.applicableDeadline, summary.titleIICitation, and
summary.recurringAcrossSites are this Actor's government-specific fields on top of the generic WCAG
sibling's schema - everything else is identical.
FAQ
Am I charged for a failed or blocked audit? No. This is this Actor's central guarantee.
Is the legal report legal advice? No. See "Important legal disclaimer" above.
Will this tell me which scoping exception applies to my site? No - by design. See "What this Actor will never auto-decide" above.
Are the April 26, 2027 / 2028 dates final? No - they come from a DOJ Interim Final Rule whose comment period closed June 22, 2026 and which is not yet finalized. See "Standing legal-monitoring note" above.
What's not in v1 yet
- Per-entity grouped batch reports. This v1 produces one legal report per run, covering every URL in
that run (with
entityName/entityPopulationTierapplied uniformly to the whole batch) - it does not yet accept a per-URL entity mapping to split one run's URLs into separate per-entity report sections. For now, a COG/municipal league auditing multiple distinct entities with different names or population tiers should run this Actor once per entity (the cross-site recurring-issues feature above still works within a single run across that entity's own sites). A true multi-entity, per-entity-grouped report is a real, identified v1.1 candidate - intentionally not built in this pass to avoid half-building a new input shape beyond the approved spec. - Site-crawl/auto-discovery, CI/CD webhooks, scheduled audits, custom rule-set authoring - the same explicit deferral list as the generic sibling.