US Government Title II ADA Accessibility Audit avatar

US Government Title II ADA Accessibility Audit

Pricing

from $45.00 / 1,000 page auditeds

Go to Apify Store
US Government Title II ADA Accessibility Audit

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

Barak Eliov

Maintained by Community

Actor stats

0

Bookmarked

2

Total users

1

Monthly active users

a month ago

Last modified

Categories

Security

Limited permissions

Share

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

  1. 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.
  2. 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.
  3. 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.

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.

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.

FieldTypeDefaultMeaning
urlsarray["https://www.usa.gov"]Public page URLs to audit, one audit per URL (up to 100 per run). No crawling.
wcagLevelstring"wcag21aa"WCAG level to check. wcag21aa is the minimum 28 CFR 35.200(b)(1)-(2) requires.
entityPopulationTierstring"unknown"Population tier of the audited entity, used only to state the correct deadline. Never inferred from a URL.
entityNamestring""Optional, purely cosmetic entity name for the legal report's cover page.
viewportstring"desktop"Screen preset: desktop, tablet, mobile, or custom.
viewportWidthinteger1280Custom viewport width in px (used only when viewport is custom).
viewportHeightinteger800Custom viewport height in px (used only when viewport is custom).
includeScreenshotsbooleantrueElement screenshot per violation plus one full-page screenshot per URL.
includeIncompletebooleantrueAlso return axe-core checks that need human review (status = incomplete).
includePassesbooleanfalseAlso return the count of rules that passed.
outputModestring"both"Row shapes: perPage, flat, or both. One page-audited charge per successful page in every mode.
generateLegalReportbooleantrueGenerate the Title II legal-citation PDF report for the run (charged only on success).
generatePdfReportbooleanfalseAlso generate a plain WCAG-only PDF report, no legal citation (charged only on success).
waitForSelectorstring""Optional CSS selector to wait for before auditing. Empty means no wait.
waitUntilstring"load"Navigation readiness: load, domcontentloaded, or networkidle.
timeoutSecsinteger30Per-URL time budget in seconds for navigation, audit and screenshots.
proxyConfigurationobject{"useApifyProxy":true}Apify Proxy settings used for the audit requests.
maxConcurrencyinteger5Maximum 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)

CategoryWhen
invalid_urlMalformed URL, non-http(s) URL, or the URL resolves to a private/link-local/reserved IP address (SSRF protection, always on)
not_foundDNS failure, connection refused, 404/410
blocked401/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
timeoutNavigation, the axe-core audit, or screenshot capture exceeded timeoutSecs combined
render_errorBrowser crash or an unclassified render failure
upstream_changed5xx 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-audited charges 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 keyWhen
page-auditedOne page successfully audited, including screenshots
legal-report-generatedThe Title II legal-citation report was produced successfully (default: on)
report-generatedThe 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 install
npx playwright install chromium # one-time
npm run typecheck
npm test
npm run build
apify 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/entityPopulationTier applied 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.