WCAG Accessibility Audit
Pricing
from $8.50 / 1,000 domain auditeds
WCAG Accessibility Audit
Audit any website for WCAG 2.1 and 2.2 AA accessibility issues with axe-core in a real browser. One row per domain: issues by severity, top failing rules, sample elements, a score, and European Accessibility Act exposure signals. Optional statement, Impressum, and privacy checks.
Pricing
from $8.50 / 1,000 domain auditeds
Rating
0.0
(0)
Developer
Mamba Labs
Maintained by CommunityActor stats
0
Bookmarked
2
Total users
1
Monthly active users
9 hours ago
Last modified
Categories
Share
๐ What can WCAG Accessibility Audit do?
Give it a domain. It opens the homepage in a real Chromium browser, runs axe-core 4.14 against the standard you pick, and returns one flat row: the accessibility issues automated checks find, by severity, the worst failing rules, sample elements, a score, and European Accessibility Act (EAA) exposure signals.
Optional compliance checks add an accessibility statement link, an accessibility overlay widget, a privacy policy link, a German Impressum and its required field types, and the US privacy choice link and Global Privacy Control file.
- Pick the standard. WCAG 2.0 A or AA, WCAG 2.1 AA, WCAG 2.2 AA, Section 508, ADA (the WCAG 2.1 AA set the ADA Title II rule names), or EN 301 549, the European standard the EAA points to.
- One row per domain. Load a list of domains and get a table you can sort, filter, and join on
domain. - A real browser, a hard budget. Each page gets 45 seconds. A page that runs past it, blocks the browser, or cannot be reached comes back as a free row that says what happened.
- EAA exposure signals. EU language, EU hreflang, an EU country code domain, EUR prices, an EU country in the footer, and a cart or checkout. Signals, never a legal finding.
- Desktop or mobile. Mobile renders at 390 by 844 with touch, where reflow and target size issues show.
๐ฅ Who this is for
Accessibility and web agencies that want a first pass on a prospect list, EU e-commerce and SaaS teams preparing for the EAA, US teams checking WCAG 2.1 AA exposure under ADA Title II and Section 508, and outbound teams that sell remediation and need a reason to reach out.
โ ๏ธ What automated checks can and cannot tell you
Automated checks find a share of WCAG failures, not all of them. A row with zero failing rules is not a conformance claim, and this actor never says a site is compliant. Rules that axe cannot decide are counted in incomplete and need a human check. The score ranks sites against each other; it is not a grade under any law.
โจ๏ธ Input
| Field | What it does |
|---|---|
domain | One website domain, for example mambabuilt.com. The homepage is audited. |
domains | Optional list, one row per domain. Used instead of domain when filled. |
standard | wcag21aa (default), wcag22aa, wcag2aa, wcag2a, section508, ada, or en301549. |
pages | 1 to 5. Pages after the homepage come from the sitemap, or from the homepage navigation. |
viewport | desktop (default) or mobile. |
compliance_checks | Any of accessibility_statement, overlay, privacy_policy, impressum, us_privacy_links. |
skipCache | false reuses an identical audit from the last 24 hours. true audits fresh. |
max_charge_usd | Optional cost cap for the run. The run stops before a domain that could cross it. |
Example input:
{"domains": ["mambabuilt.com", "example.de"],"standard": "wcag22aa","pages": 2,"compliance_checks": ["accessibility_statement", "impressum", "overlay"]}
๐ค Output
One row per domain with 40 fields. Every row carries every field; a value that does not apply is null, never missing.
| Field | Meaning |
|---|---|
domain | The domain audited, without protocol or www. |
url_audited | The homepage URL after redirects. |
standard | The standard whose axe rule tags were run: wcag2a, wcag2aa, wcag21aa, wcag22aa, section508, ada, or en301549. |
viewport | desktop (1280 by 800) or mobile (390 by 844). |
pages_requested | How many pages the input asked for, 1 to 5. |
pages_audited | How many pages were rendered and audited. 0 when the homepage could not be audited. |
urls_audited | Every URL that was audited, homepage first. |
violations_total | Distinct axe rules with at least one issue found by automated checks, across all audited pages. |
violations_critical | Failing rules with impact critical. |
violations_serious | Failing rules with impact serious. |
violations_moderate | Failing rules with impact moderate. |
violations_minor | Failing rules with impact minor. |
violation_nodes_total | Page elements affected, summed over every failing rule and page. |
passes | Distinct rules that passed on every audited page. |
incomplete | Distinct rules axe could not decide automatically, which need a human check. |
top_rules_json | JSON array of up to 10 failing rules, worst first: rule_id, impact, nodes, wcag_tags, help_url. |
sample_selectors_json | JSON array of up to 10 CSS selectors of affected elements, as rule_id and selector pairs. |
score | 0 to 100. 100 minus an impact weighted penalty per failing rule. The weights are arbitrary and published in the README. Not a conformance claim. |
eaa_exposure | True when at least one EU market signal is present. A signal for the European Accessibility Act, never a legal finding. |
eaa_signals | Which signals fired: eu_language, eu_hreflang, eu_tld, eur_prices, eu_country_in_footer, checkout. |
compliance_checks_requested | The compliance modes that ran for this row, or null when none were selected. |
accessibility_statement_found | Mode accessibility_statement: true when the homepage links to an accessibility statement or accessibility page, in any of 13 EU languages. |
accessibility_statement_url | Mode accessibility_statement: the linked URL. |
overlay_detected | Mode overlay: true when the homepage loads a known accessibility overlay widget. |
overlay_vendor | Mode overlay: accessibe, userway, audioeye, equalweb, recite_me, max_access, eye_able, user1st, or purple_lens. |
privacy_policy_found | Mode privacy_policy: true when the homepage links to a privacy policy. |
privacy_policy_url | Mode privacy_policy: the linked URL. |
impressum_found | Mode impressum, German language or .de sites only: true when the homepage links to an Impressum. Null when the mode does not apply. |
impressum_url | Mode impressum: the linked URL. |
impressum_fields_present | Mode impressum: which required field types appear on the page: address, email, phone, register_number, vat_id, representative. Presence only, never the values. |
us_privacy_choice_link_found | Mode us_privacy_links: true when the homepage carries a Do Not Sell or Share or Your Privacy Choices link. |
gpc_well_known_found | Mode us_privacy_links: true when /.well-known/gpc.json answers with a gpc field. |
render_status | rendered, blocked (challenge, refusal, or robots.txt), timeout (past the 45 s page budget), unreachable, or error. Only rendered rows are charged. |
render_ms | Wall time spent rendering and auditing the pages of this row. |
axe_version | The axe-core engine version that ran. |
from_cache | True when the row came from the 24 hour cache. |
row_status | ok, partial (audited, but an extra page or a compliance read failed), or error (nothing audited). |
error_reason | Why a row is partial or error, in plain words. Null on ok rows. |
billable_events_json | JSON array of the events charged for this row, for example [{"event":"domain-audited","count":1}]. [] when free. |
checked_at | When the row was produced, ISO 8601 UTC. |
Example row, shortened:
{"domain": "example.de","standard": "wcag21aa","pages_audited": 1,"violations_total": 9,"violations_critical": 1,"violations_serious": 4,"violation_nodes_total": 61,"score": 58,"eaa_exposure": true,"eaa_signals": ["eu_language", "eu_tld", "eur_prices", "checkout"],"impressum_found": true,"impressum_fields_present": ["address", "email", "register_number", "vat_id"],"render_status": "rendered","row_status": "ok","billable_events_json": "[{\"event\":\"domain-audited\",\"count\":1},{\"event\":\"compliance-checked\",\"count\":1}]"}
How the score works
100 minus a penalty per failing rule. Each failing rule costs its impact weight (critical 15, serious 8, moderate 4, minor 1), plus up to the same again as the number of affected elements grows toward 10. The floor is 0. The weights are arbitrary and stated here so you can rebuild the number or ignore it and use the counts directly.
๐ต How much does it cost?
Pay per event. You pay for audits that ran, never for a blocked, timed out, or unreachable domain.
| Event | Free plan | Bronze | Silver | Gold |
|---|---|---|---|---|
domain-audited, one per domain with a rendered audit | $0.01000 | $0.00950 | $0.00900 | $0.00850 |
page-audited, each page after the homepage | $0.00200 | $0.00190 | $0.00180 | $0.00170 |
compliance-checked, once per domain when any compliance check is selected | $0.00300 | $0.00285 | $0.00270 | $0.00255 |
apify-actor-start, once per run | $0.00250 | $0.00250 | $0.00250 | $0.00250 |
That is $10.00 per 1,000 audited homepages on the free plan, $8.50 on Gold, plus $0.0025 per run for the start event, which covers starting the browser container. Batch domains into one run to pay it once.
Free plan cap: free Apify plan users get 150 audited domains a month, which is $1.50 of evaluation. Paid plans have no cap.
Stopping at your limit: the run reads Apify's maximum cost per run and the max_charge_usd input, and stops before starting a domain it could not pay for.
๐ก Usage examples
Apify API
curl -X POST "https://api.apify.com/v2/acts/mambalabs~wcag-accessibility-audit/runs?token=$APIFY_TOKEN" \-H 'content-type: application/json' \-d '{"domains":["mambabuilt.com","example.de"],"standard":"wcag22aa"}'
Clay. Add an Apify column, pick this actor, and map your domain column to domain. Every input is read as a string, so Clay's string values work as is. One row comes back per domain.
MCP. The MCP server @mambalabsdev/mcp-wcag-accessibility-audit exposes the tool audit_wcag_accessibility to Claude, Cursor, and any MCP client.
๐งฏ Error handling
| What happened | render_status | row_status | Charged |
|---|---|---|---|
| Audit ran on every requested page | rendered | ok | yes |
| Audit ran, but an extra page or a compliance read failed | rendered | partial | yes, for what ran |
| Bot challenge, HTTP 403 or 429, or robots.txt disallows the homepage | blocked | error | no |
| Page did not finish in 45 seconds | timeout | error | no |
| DNS, TLS, or connection failure | unreachable | error | no |
| Input could not be read as a domain | null | error | no |
error_reason says what happened in plain words on every partial and error row.
โ ๏ธ Limitations
- Automated checks find a subset of WCAG failures. Keyboard flow, screen reader meaning, captions, and most content rules need a human.
- Only the rendered state after load is audited. Menus, modals, and forms behind a click are not opened.
- Content inside iframes, such as embedded video players and third party widgets, is not audited.
- Media and fonts are not loaded, to stay inside 1,024 MB. Color contrast over background images can land in
incomplete. - EAA scope, and the microenterprise exemption, cannot be read from a page.
eaa_exposureis a signal. - The Impressum check reports which field types appear, never the values, and runs only on German language or .de sites.
- Sites behind bot protection return
blocked. No proxy is used. - The legal references in this README were confirmed on 2026-10-17 from ada.gov, section508.gov, gesetze-im-internet.de, cppa.ca.gov, and the W3C GPC specification. The EUR-Lex pages refused automated reads that day.
โ FAQ
Does this call an AI model? No. Every field comes from axe-core rules or a presence check on the page.
Why is a site I know is accessible showing failing rules? axe flags real code issues, and most large sites have some. Read top_rules_json and the help_url for each rule.
Do you respect robots.txt? Yes. A homepage disallowed for all agents is not fetched, and extra pages that are disallowed are skipped.
Is a cached row charged? Yes, at the same price, and from_cache is true on it. Set skipCache to true to audit fresh.
๐งฉ Want other GTM data?
Mamba Labs builds a fleet of GTM enrichment actors that share one flat,
Clay-ready output convention, so their rows join on company_domain with no
cleaning step:
Every actor in the suite takes a domain or a company and returns one flat row, so they stack in the same Clay table without reshaping anything.
๐ ๏ธ Need something custom built for you or your team? Tell us what you are trying to find and we will build it. Talk to Mamba Labs.
๐ Support
Something wrong, or a site the actor reads incorrectly? Open an issue on the Issues tab with the domain and the row, and we will look at it.
โน๏ธ Sourcing and legal. Every field is a property of a website: rule results, link presence, and file presence. The Impressum check reports field types, never names, emails, or numbers. Every fetch honors
robots.txt. axe-core is used unmodified under the Mozilla Public License 2.0. You are responsible for how you use the output.
Built by Mamba Labs.