webauditlabs
← Not a developer? See the overview for website owners and agencies

Local website audits from your terminal, CI or coding agent.

The webauditlabs CLI runs Chromium on your machine and writes structured findings with screenshots. No account, no API key. The same engine and result format power webauditlabs Cloud.

Install$ npx webqa-platform audit http://localhost:5173

One run against a multilingual demo site

Unedited CLI output from the Nordhaus demo shop (Dutch, English, German) with five planted defects. Generated by website/scripts/capture-demo.mjs.

$ webqa run webqa.json --allow-private
webqa issues found: 6 finding(s) on 6 page(s)
  warning http     [all] /en/
          1 resource failed to load.
  warning clipping [all] /de/
          The a "In den Warenkorb legen" does not fit; its text is cut off.
  warning overflow [mobile] /de/
          1 control sticks out of the viewport and is partly unreachable.
  error   overflow [mobile] /de/
          The page is 213px wider than the 390px viewport and scrolls sideways.
  warning links    [all] /nl/contact.html
          1 link on this "nl" page leads to locale "en".
  error   lang     [all] /en/products.html
          The page declares lang="nl" but belongs to locale "en".
Evidence: .webqa/runs/2026-10-24T14-28-38-216Z
Mobile screenshot of the German Nordhaus homepage. The shop button runs past the right edge of the screen; the area is outlined in red.Evidence: /de/ · mobile 390px
Real output: the webauditlabs CLI run against the Nordhaus demo shop.

What the CLI detects

Fourteen rule-based checks (keyboard is opt-in) with stable identifiers (check/code). The same identifiers are used by the CLI, webauditlabs Cloud, the REST API and MCP.

AreaRules
Runtime and networkhttp/http_statushttp/resource_failedhttp/api_failedhttp/console_errorhttp/third_party_failed
Linkslinks/link_deadlinks/link_server_errorlinks/link_redirect_looplinks/link_redirectslinks/anchor_brokenlinks/link_emptylinks/link_wrong_locale
Locales and translationslang/lang_missinglang/lang_mismatchlang/translation_missinglang/hreflang_wrong_localelang/hreflang_brokenlang/hreflang_redirectlang/hreflang_not_reciprocal
Layoutoverflow/horizontal_overflowoverflow/control_offscreenclipping/text_clipped
Mediamedia/image_brokenmedia/image_not_loadedmedia/image_alt_missing
Contentcontent/placeholder_textcontent/template_leakcontent/heading_emptycontent/content_empty
Formsforms/field_unlabeledforms/button_unnamedforms/link_button_no_hrefforms/form_insecure_actionforms/form_offsite_action
SEOseo/title_missingseo/title_too_longseo/meta_description_missingseo/canonical_missingseo/canonical_offsiteseo/canonical_wrong_localeseo/heading_level_skippedseo/noindexseo/canonical_target_brokenseo/canonical_target_redirectsseo/structured_data_invalidseo/og_image_missingseo/og_image_brokenseo/robots_missingseo/robots_blocks_pageseo/robots_no_sitemapseo/soft_404seo/favicon_missingseo/sitemap_url_brokenseo/sitemap_url_redirectsseo/sitemap_url_noindexseo/sitemap_url_canonical_elsewhere
Accessibilitya11y/a11y_<axe rule> (serious and critical, axe-core)
Consistencyconsistency/price_mismatchconsistency/date_expiredconsistency/duplicate_text
Privacyprivacy/tracker_before_consentprivacy/tracker_after_rejectprivacy/tracker_without_bannerprivacy/consent_no_reject
Securitysecurity/mixed_contentsecurity/http_not_redirectedsecurity/tls_expiringsecurity/hsts_missingsecurity/security_headers_missing
Keyboard (off by default)keyboard/focus_not_visiblekeyboard/focus_hidden_elementkeyboard/focus_trapkeyboard/skip_link_missing
Runtime and networkhttp/http_statushttp/resource_failedhttp/api_failedhttp/console_error
Linkslinks/link_deadlinks/link_server_errorlinks/link_redirect_looplinks/link_redirectslinks/anchor_brokenlinks/link_emptylinks/link_wrong_localelinks/contact_link_invalid
Locales and translationslang/lang_missinglang/lang_mismatchlang/translation_missinglang/hreflang_wrong_localelang/hreflang_brokenlang/hreflang_redirectlang/hreflang_not_reciprocallang/untranslated_ui_text
Layoutoverflow/horizontal_overflowoverflow/control_offscreenoverflow/element_overlapoverflow/text_too_smallclipping/text_clipped
Mediamedia/image_brokenmedia/image_not_loadedmedia/image_alt_missing
Contentcontent/placeholder_textcontent/template_leakcontent/heading_emptycontent/content_emptycontent/copyright_outdated
Formsforms/field_unlabeledforms/button_unnamedforms/link_button_no_hrefforms/form_insecure_actionforms/form_offsite_actionforms/autocomplete_missingforms/input_type_mismatch
SEOseo/title_missingseo/title_too_longseo/meta_description_missingseo/canonical_missingseo/canonical_offsiteseo/canonical_wrong_localeseo/heading_level_skippedseo/noindex
Accessibilitya11y/a11y_<axe rule> (serious and critical, axe-core)
Consistencyconsistency/price_mismatchconsistency/date_expiredconsistency/duplicate_textconsistency/contact_mismatch
AI step (--ai, optional)Untranslated text and plain-language explanations, marked for review

Command reference

npx webqa-platform audit <url>

Discovery and checks in one command, with a JSON and HTML report.

webqa init <url>

Detects language versions from hreflang, the language switcher or <html lang> and writes an editable webqa.json.

webqa run <spec | url>

Captures pages at every configured viewport (desktop and mobile by default), runs the checks and writes result.json and screenshots to .webqa/runs/.

--json

Writes result.json to stdout instead of the summary, for scripts and agents.

--checks a,b

Runs only the checks you name, for example --checks links,seo.

--ai

Adds the optional AI step: untranslated text and plain-language explanations, within a token budget.

--allow-private

Allows localhost and private network addresses, for local and staging sites.

--mode remote-cdp

Uses your own browser endpoint over the Chrome DevTools Protocol.

webqa mcp

Starts the local MCP server for Claude Code, Cursor and other MCP clients.

webqa login · project link · --sync

Connects to webauditlabs Cloud and uploads an existing local result.

  • Read-only: no form submissions or non-GET requests
  • Restricted to the hosts in the configuration
  • Private addresses blocked unless --allow-private
  • Tool errors reported separately from site issues

One engine, three ways to run the browser.

localChromium on your machine. No account.
remote-cdpYour own compatible browser endpoint. No account.
cloudManaged browsers through the webauditlabs backend. Browser provider credentials never leave the backend.

Run output

Each run writes a result file validated against the published v1 schema, a full-page screenshot per page and viewport, and an annotated copy for pages with findings. The same finding format is used by the cloud, the API and MCP.

.webqa/runs/2026-10-24T14-28-38-216Z/
├── result.json                    # result.v1
├── p03-desktop.png
├── p03-mobile.png
├── p03-mobile.annotated.png       # problem elements outlined
└── …
result.json · f4result.v1
{
  "id": "f4",
  "check": "overflow",
  "code": "horizontal_overflow",
  "severity": "error",
  "url": "http://127.0.0.1:8090/de/",
  "locale": "de",
  "viewport": "mobile",
  "message": "The page is 213px wider than the 390px viewport and scrolls sideways.",
  "provenance": "deterministic",
  "evidence": {
    "expected": "390px",
    "actual": "603px",
    "elements": [
      {
        "tag": "div",
        "selector": "body > section.hero:nth-of-type(1) > div.wrap > div",
        "rect": {
          "x": 18,
          "y": 599,
          "width": 585,
          "height": 415
        },
        "text": "HERBSTKOLLEKTION 2026 Handgemacht für jeden Tag Keramik, Leuchten und Textilien aus kleinen Werkstätten in Skandinavien "
      },
      {
        "tag": "img",
        "selector": "body > section.hero:nth-of-type(1) > div.wrap > img",
        "rect": {
          "x": 18,
          "y": 132,
          "width": 585,
          "height": 439
        }
      }
    ]
  }
}

A verification step your coding agent can run.

Agents need a deterministic way to check their work: run the audit, read structured findings, fix, and run again.

  • Structured findings

    Versioned JSON with rule, severity, page, viewport, elements and screenshot path.

  • Verify after a fix

    Exit code 0 means no findings remain; 1 means issues are still present.

  • Local MCP server

    webqa mcp over stdio for Claude Code, Cursor and other MCP clients. No account.

  • REST API and remote MCP

    Cloud projects, runs and findings for agents and scripts, on every cloud plan.

MCP configuration
{
  "mcpServers": {
    "webqa": { "command": "npx", "args": ["webqa-platform", "mcp"] }
  }
}

Sync local results without scanning twice.

Optional. Sync uploads the result.json and screenshots of a run you already did to a linked cloud project. The run is stored with execution mode local.

  1. localwebqa audit

    Runs locally in Chromium.

  2. localresult.json

    Findings and screenshots on disk.

  3. cloudwebqa audit --sync

    Uploads the existing result.

  4. cloudwebauditlabs Cloud

    History, inbox and team access.

01

Configuration file

webqa init writes a webqa.json for version control: locales, pages or a sitemap with a page limit, viewports, checks and timeouts.

{
  "version": 1,
  "name": "www.example.nl",
  "locales": [
    { "code": "nl", "url": "https://www.example.nl/nl/" },
    { "code": "de", "url": "https://www.example.nl/de/" }
  ],
  "pages": { "sitemap": "https://www.example.nl/sitemap.xml", "maxPages": 50 },
  "viewports": [{ "name": "mobile", "width": 390, "height": 844 }],
  "checks": ["http", "lang", "overflow", "links", "clipping"],
  "timeouts": { "pageMs": 30000, "runMs": 600000 }
}
02

Exit codes

Exit codes distinguish site issues from tool and runtime errors.

0passedNo findings
1issues_foundOne or more findings
2invalid inputInvalid configuration or arguments
3execution_errorTool or browser error, not a site issue
4timed_outRun exceeded its time limit
03

CI integration

Fail a build when findings appear and keep the run folder as a build artifact.

# .github/workflows/webqa.yml
- run: npx playwright install --with-deps chromium
- run: npx webqa-platform audit https://staging.example.com --json > webqa-result.json
- uses: actions/upload-artifact@v4
  if: failure()
  with:
    name: webqa-evidence
    path: .webqa/runs/