WCAG 2.1 accessibility audit service for websites β with pay-per-use via x402 protocol.
Built by a blind developer for blind and low-vision users.
π€ Telegram Bot: @accessibilityAuditAgentBot | π Web: hexdrive.tech
This repository is the main Accessibility Auditor service. The GenLayer adjudication prototype lives here: https://github.com/web3blind/genlayer-accessibility-court
The prototype adds an independent GenLayer judgement / provenance layer on top of selected accessibility audit evidence.
Audits any website for WCAG 2.1 accessibility compliance. Returns a score (0β100), letter grade (AβF), and detailed issue breakdown across 12 categories:
- Semantic HTML structure
- Image alt text
- Link text quality
- Heading hierarchy
- Form accessibility (labels, IDs)
- Keyboard navigation
- ARIA attributes
- Media captions (video/iframe)
- Contrast ratio
- Language declaration
- Page structure and landmarks
- Responsive design (viewport)
AI agents and developers can pay per audit via the x402 protocol β no API keys required.
POST https://hexdrive.tech/api/audit/paid
Payment: 0.10 USDC on Arc mainnet
Network: eip155:5042
Facilitator: self-hosted private Arc relayer (source: arc_facilitator/)
Discovery endpoint:
GET https://hexdrive.tech/api/x402/info
The discovery response also describes the auditor as an ERC-8004 registered agent on Arc mainnet and exposes a simple pay-per-audit model for other agents. Client agents should treat the published price as a spending-policy input: check their maximum price per audit, remaining daily budget, and allowed target domains before submitting payment.
Free audits are available via the web interface only (not via API).
The fixed-price API accepts 0.10 USDC on Arc mainnet (eip155:5042).
Our self-hosted facilitator source includes the
server, official SDK integration, nonce/gas ledger, tests, sample configuration
and explicit paid client. It is an off-chain relayer, not a custom Solidity
contract: settlement calls the existing Arc USDC EIP-3009 interface.
Contract and SDK source references
and verified production handoff are included.
For this private loopback service, configure X402_FACILITATOR_URL,
X402_FACILITATOR_NETWORKS=arc_mainnet, X402_NETWORK_KEY=arc_mainnet and
X402_PRIVATE_FACILITATOR_TOKEN through the environment; no values of secrets
are committed. The relayer has its own wallet. Mainnet and testnet both passed
live paid tests; production offers mainnet only. The separate Base multi-page
escrow remains unchanged.
Circle is optional. Other facilitators need neither of the Circle credential variables below. Our private Arc facilitator uses its own Bearer token. Buyer payment offers and the fixed $0.10 audit price are unchanged.
For Circle, configure X402_FACILITATOR_URL as
https://api.circle.com/v1/facilitator/x402 (production) or
https://api-sandbox.circle.com/v1/facilitator/x402 (sandbox). Set
X402_FACILITATOR_NETWORKS to the intended network keys, for example
arc_testnet; the primary server intersects them with /supported exact v2
capabilities. An authoritative empty intersection disables paid audits (503),
not payment enforcement. An unavailable capability probe retains the operator's
list, which the SDK validates when initializing its middleware.
Configure exactly one server-side secret through your environment manager:
X402_CIRCLE_API_KEY: Circle API key sent in the HTTP Authorization Bearer header. This production mode needs no seller private key. Circle documents that a settlement bindspayToto the Circle account and ends its keyless trial.X402_CIRCLE_SELLER_PRIVATE_KEY: key controlling the payout EOA, for Circle's keyless trial only. Each verify/settle request gets a fresh EIP-712Facilitator-Seller-Proof, bound to its purpose, network, payTo and exact body bytes, with a 5-minute expiry. ERC-1271 external signers are not implemented.
Never set both modes; remove both when switching to a non-Circle facilitator. The adapter refuses to send credentials to non-official Circle URLs and does not follow redirects. Secrets/proofs are not added to discovery responses or offers. No secret values belong in source, browser chat, logs or tests. Invalid auth configuration disables the paid route rather than silently dropping auth.
Circle returns success: false / settlement_pending when a transaction is
unresolved. This adapter leaves that result unchanged; it does not implement
status reconciliation or turn pending into success. Never retry with a newly
signed buyer authorization after a timeout/pending response.
Protocol references (checked against the actual SDK x402==2.9.0):
verify authentication,
seller proof,
keyless trial,
supported networks.
Local tests (mock HTTP transport; no paid/on-chain calls):
.venv/bin/python -m pytest -q tests/test_x402_facilitator_auth.py tests/test_agentkit_payment_controls.py
Any AgentKit-powered agent can call this service directly:
from agentkit_action_provider import accessibility_audit_action_provider
from coinbase_agentkit import AgentKit, AgentKitConfig
agent_kit = AgentKit(AgentKitConfig(
wallet_provider=wallet_provider,
action_providers=[accessibility_audit_action_provider()]
))
# Agent can now call:
# accessibility_paid_audit(
# url="https://example.com",
# max_price_usd=0.10,
# remaining_daily_budget_usd=1.00,
# )from eth_account import Account
from x402.client import x402Client
from x402.http.clients.httpx import x402HttpxClient
from x402.mechanisms.evm.exact.client import ExactEvmScheme
from x402.mechanisms.evm.signers import EthAccountSigner
account = Account.from_key("YOUR_PRIVATE_KEY")
client = x402Client()
client.register("eip155:84532", ExactEvmScheme(signer=EthAccountSigner(account)))
async with x402HttpxClient(client) as http:
response = await http.post(
"https://hexdrive.tech/api/audit/paid",
json={"url": "https://example.com"},
)
print(response.json()) # score, grade, issues, report_urlThe public web UI and Telegram bot intentionally stay single-page and free. Multi-page website audits are reserved for Fortytwo x402Escrow-style paid agent flows because the final cost depends on how many pages are discovered and successfully audited.
Discovery / quote:
GET https://hexdrive.tech/api/x402escrow/info
POST https://hexdrive.tech/api/site-audit/quotePaid endpoint:
POST https://hexdrive.tech/api/x402escrow/site-audit
X-PAYMENT: <Fortytwo x402Escrow authorization>Request body:
{
"url": "https://example.com",
"max_pages": 30,
"include_summary": true,
"same_domain_only": true,
"max_budget_usdc": "3.30",
"output_format": "markdown",
"per_page_timeout_seconds": 45,
"max_duration_seconds": 600
}Safety boundaries:
- hard cap: 100 pages;
- same-domain only;
- dangerous/private paths such as logout, admin, checkout, payment and account pages are skipped;
- per-page timeout and whole-job timeout prevent hanging scans;
- pages that fail before a report is produced are not billed;
- Markdown output is available for agents at
/site-audits/{site_audit_id}.mdand/api/site-audits/{site_audit_id}/markdown.
If the endpoint is called without X-PAYMENT, it returns HTTP 402 with the
payment requirements. Local dry-run requests can be enabled only by the operator
with X402ESCROW_ALLOW_DRY_RUN_REQUESTS=1; production should leave that off.
Live settlement is wired behind explicit env switches. To activate it, configure:
export X402ESCROW_LIVE=true
export X402ESCROW_NETWORK=base # or monad
export X402ESCROW_RPC_URL="..."
export X402ESCROW_FACILITATOR_PRIVATE_KEY="..."
# optional override if Fortytwo changes/deploys a different proxy:
export X402ESCROW_CONTRACT_ADDRESS="0x9562f50f73d8ee22276f13a18d051456d8d137a0"Before enabling production traffic, verify the configured wallet:
GET https://hexdrive.tech/api/x402escrow/facilitator-statusThe address must have FACILITATOR_ROLE on the configured Fortytwo contract;
otherwise settle() / release() will revert and the service must not run the
multi-page job. Fortytwo docs say DEFAULT_ADMIN_ROLE can grant/revoke
facilitators. If this deployment is not the contract admin, request the role from
Fortytwo or deploy an owned escrow instance.
Send any URL to @accessibilityAuditAgentBot:
/start β welcome and help
https://example.com β send a URL to audit
Open https://hexdrive.tech, enter a URL and click Analyze.
Results appear at https://hexdrive.tech/audits/<audit_id>.
- Request arrives via Telegram, web form, or paid API (
/api/audit/paid). - For paid requests: x402 middleware intercepts, requires 0.10 USDC payment via EIP-3009.
- On payment confirmation: headless Chromium (Playwright) fetches the full page.
- BeautifulSoup runs 12 accessibility checks.
- Score + HTML report generated, returned immediately for paid requests.
For agentic workflows, the intended control pattern is deliberately simple: ERC-8004 identity for discoverability, x402 settlement for one audit, and client-side spending limits before payment.
- Python 3.12 / FastAPI / Uvicorn
- Playwright β headless Chromium for full page rendering
- BeautifulSoup4 β HTML parsing and accessibility checks
- x402 (
pip install x402[evm,fastapi]) β HTTP payment protocol - python-telegram-bot 20.x β Telegram integration
- nginx β reverse proxy with TLS
- coinbase-agentkit β AgentKit action provider
git clone https://github.com/web3blind/accessibility-auditor.git
cd accessibility-auditor
python3 -m venv venv
source venv/bin/activate
pip install -r requirements.txt
playwright install chromiumexport TELEGRAM_BOT_TOKEN="your_token"
export X402_SERVER_ADDRESS="your_wallet_address" # receives payments
# Optional:
export X402_NETWORK="eip155:84532" # default: Base Sepolia
export X402_FACILITATOR_URL="https://x402.org/facilitator"python3 bot_final.pyStarts Telegram bot + FastAPI server on http://localhost:3000.
accessibility-auditor/
βββ bot_final.py # Telegram bot + FastAPI server + x402 middleware
βββ agentkit_action_provider.py # AgentKit action provider for AI agents
βββ auditor.py # Core WCAG 2.1 checks
βββ fetch_page.py # Playwright subprocess page fetcher
βββ storage.py # Audit result persistence
βββ report_generator.py # HTML report generator
βββ requirements.txt
βββ nginx.conf
βββ keep-alive.sh
| Endpoint | Method | Auth | Description |
|---|---|---|---|
/api/audit/paid |
POST | x402 (0.10 USDC) | Single-page audit, returns JSON immediately |
/api/x402escrow/site-audit |
POST | Fortytwo x402Escrow | Multi-page metered audit, JSON/Markdown result |
/api/site-audit/quote |
POST | none | Quote max budget for a multi-page paid audit |
/api/x402/info |
GET | none | Payment discovery info for agents |
/api/x402escrow/info |
GET | none | Fortytwo x402Escrow multi-page discovery |
/api/audit |
POST | none* | Submit single-page audit (web UI only) |
/api/audit/{id}/status |
GET | none | Poll audit status + result |
/audits/{id} |
GET | none | Single-page HTML report |
/site-audits/{id} |
GET | none | Multi-page HTML report |
/site-audits/{id}.md |
GET | none | Multi-page Markdown report for agents |
*Free endpoint checks Referer: hexdrive.tech β not available for external API calls.
- No secrets in repository β
wallets_x402.json,.env,config.jsonare all gitignored - Audit results stored locally, not public by default
- All input validated before processing
Built with Hermes Agent Β· Real problem. Real solution.