Curbcut

Web app docs

The Curbcut web app scans whole sites against WCAG 2.2 on our servers. These docs cover every part of it; the CI gate has its own page. Plans and limits are on the pricing page.

Getting started

  1. Buy a plan on the pricing page. Polar emails a license key right after checkout; it is also on the order page and in the Polar customer portal.
  2. Open https://app.saffo.dev and paste the key. The server checks it with Polar and signs you in with a session cookie that lasts 30 days. There are no accounts, emails or passwords.
  3. Add your site by its home URL, for example https://www.example.com/.
  4. Verify the site (below). Unverified sites cannot be scanned.
  5. Set the page limit, the schedule and, if you want, path patterns and the viewport. Then choose Run now or wait for the first scheduled scan.

Site verification

Each site gets its own verification token. Prove that you control the site in one of two ways:

Then choose Verify. You can remove the record or file afterwards, but keep it if you want a CI preview host to qualify (see CI docs). Scan only sites you own or are allowed to test.

Site settings

The crawler

Scans are done by CurbcutBot. Its rules are fixed in code:

Each page is rendered in headless Chromium and checked with the open-source axe-core engine and our rule texts. No screenshots are taken. To block the crawler, add a User-agent: CurbcutBot group with Disallow: / to robots.txt.

Scans

A scan is queued, then running, then done or failed. While it runs, the scan page shows progress and each page's status. Starter allows 4 manual scans a month per workspace; Team and Agency allow one manual scan per site per hour. A new manual or scheduled scan waits until the site's previous one has finished.

Issues

The issues view lists every issue of the latest scan, grouped by rule or by WCAG success criterion, with the number of affected pages, the explanation and the fix steps. Each issue is marked new or unchanged compared with the previous scan of the site, and issues that disappeared are counted as fixed. A page view lists one URL's issues with their CSS selectors, markup snippets and the page's HTTP status, and links to the live page, where the free browser extension can highlight the element.

Ignore

Choose Ignore on an issue and add a note, for one page or for the same element on every page. Later scans keep it ignored; the issue is still stored, and you can stop ignoring it at any time.

Trends

For each site, a chart and a table of issue counts by impact per scan over the last 13 months, with pages scanned, new issues and fixed issues per scan.

Reports

Team access keys

Under Settings, create an access key for each colleague, with a label such as their name or role. They sign in with it the same way you sign in with the license key. Starter allows 2 keys, Team 10 and Agency any number. Revoke a key in settings and it stops working. Keys are shown once when created and stored only as hashes.

Webhooks

Each site can send up to 5 HTTPS webhooks. After every finished manual or scheduled scan, each webhook gets a POST with content-type: application/json and the CurbcutBot user agent. The event is scan.finished; when the scan found new critical or serious issues, a second message with the event issues.new follows. Delivery has a 10-second timeout and is not retried; settings show the last status. Webhook URLs must be on public hosts.

JSON format (newIssues only on issues.new, at most 50, critical and serious only):

{
  "event": "issues.new",
  "site": { "id": "6c0f4a1e-2b7d-4a55-9a7e-0d6f3e1b2c44", "url": "https://www.example.com/" },
  "scan": {
    "id": "9b2d7f3a-51c4-4e8b-b0a6-7c1d2e3f4a5b",
    "kind": "scheduled",
    "status": "done",
    "url": "https://app.saffo.dev/scans/9b2d7f3a-51c4-4e8b-b0a6-7c1d2e3f4a5b",
    "startedAt": "2026-11-06T02:00:03.000Z",
    "finishedAt": "2026-11-06T02:09:41.000Z",
    "pages": 214,
    "totals": { "critical": 1, "serious": 6, "moderate": 12, "minor": 3, "new": 2, "fixed": 4, "unchanged": 18 }
  },
  "newIssues": [
    {
      "ruleId": "color-contrast",
      "impact": "serious",
      "page": "https://www.example.com/pricing/",
      "selector": ".plan > p.note",
      "criteria": ["1.4.3"]
    }
  ]
}

Slack format: a single text field, with a summary line and a link to the scan in Slack's <url|text> syntax:

{ "text": "Curbcut: <summary line> <https://app.saffo.dev/scans/9b2d7f3a-51c4-4e8b-b0a6-7c1d2e3f4a5b|Open the scan>" }

What is stored

No names, emails, passwords, payment details or screenshots are stored; payment data stays with Polar.

Retention and deletion

The privacy policy has the full details.

Limits

Automated checks find only part of all WCAG failures. Test with a keyboard and a screen reader as well. Curbcut does not make a site compliant and does not change your pages.

Help

Write to support@saffo.dev.