Verwendung über die CLI
Ein Befehl statt Code — kein Test-Framework und kein Node-Skript nötig, gut geeignet als Pipeline-Schritt oder für eine schnelle Prüfung eines Build-Artefakts.
Erster Scan
$ npm install -g @surea11y/cli$ surea11y scan ./index.html$ surea11y scan https://example.com/ --wcag 2.2
Erfordert Node.js ^20.19.0 || ^22.13.0 || >=24.0.0. Die Zusammenfassung nennt das Release von @surea11y/core, das den Scan ausgeführt hat:
$ surea11y scan ./index.htmlsurea11y scan: file:///path/to/index.htmlengine: @surea11y/core 1.14.1pass: 16 fail: 4 cantTell: 4 notApplicable: 121occurrences by tier: fail: 4 cantTell: 4needs review: likely fail: 1 likely pass: 0 needs a person: 3FAIL (4 rule(s)):button-name-present (serious, 1 fail occurrence(s))- html > body > main > buttonThis button has no accessible name.hint: Give the button visible text, or name it with aria-label, so screenreader users know what it does.contrast-enhanced (serious, 1 fail occurrence(s))- html > body > main > pElement has insufficient color contrast (AAA) of 2.85:1 (foreground:#999999, background: #ffffff, font size: 16px, font weight: normal).Expected contrast ratio of 7:1 (normal text).hint: Change the text color, the background color, or both, so thecontrast ratio reaches at least 7:1.contrast-minimum (serious, 1 fail occurrence(s))- html > body > main > pElement has insufficient color contrast of 2.85:1 (foreground: #999999,background: #ffffff, font size: 16px, font weight: normal). Expectedcontrast ratio of 4.5:1 (normal text).hint: Change the text color, the background color, or both, so thecontrast ratio reaches at least 4.5:1.img-alt-present (serious, 1 fail occurrence(s))- html > body > main > imgThis <img> has no alt attribute.hint: Add an alt attribute that says what the image shows, or alt="" ifthe image is purely decorative.LIKELY FAIL — confirm (1 occurrence(s)):- heading-order (minor): html > body > main > h3This heading jumps from level 1 to level 3, skipping a level.why: The heading skips a level after the one before it.cantTell — needs human review (4 rule(s)): heading-order, link-name-quality,manual-review, page-title-patternscriteria (WCAG 2.2):fail 1.1.1 Non-text content: text alternatives; 1.4.3 Contrast: minimum;1.4.6 Contrast: enhanced; 4.1.2 Name, role, value: accessible namecantTell 1.2.1 Audio-only and video-only (prerecorded): transcript; 1.2.2Captions (Prerecorded); 1.3.1 Info and Relationships; 1.3.4Orientation; 1.3.5 Identify Input Purpose; 1.4.1 Use of Color;1.4.2 Audio Control; 1.4.4 Resize Text; 1.4.5 Images of Text;1.4.12 Text Spacing; 2.1.1 Keyboard; 2.1.3 Keyboard (No Exception);2.2.1 Timing Adjustable; 2.2.2 Pause, Stop, Hide; 2.2.4Interruptions; 2.4.1 Bypass Blocks; 2.4.2 Page titled; 2.4.3 Focusorder; 2.4.4 Link Purpose (In Context); 2.4.6 Headings and Labels;2.4.7 Focus visible; 2.4.9 Link Purpose (Link Only); 2.5.8 Targetsize: minimum; 3.1.1 Language of page; 3.1.2 Language of Parts;3.2.5 Change on Request; 3.3.1 Error Identification; 3.3.2 Labelsor Instructions; 3.3.8 Accessible Authentication (Minimum); 4.1.2Name, role, value: ARIA validity; 4.1.3 Status MessagesnotApplicable: 2A criterion that passes here means the checks that ran found nothing in it,not that the page conforms.
Die Zeile needs review ordnet die Fragen danach, was die prüfende Person mit ihnen tut: likely fail (die Hinweise auf der Seite deuten auf einen Fehlschlag, wie die übersprungene Überschriftenebene hier), likely pass und needs a person. Die wahrscheinlichen Fehlschläge werden mit dem Grund aufgelistet, aus dem sie in diese Richtung tendieren, und jede Frage in --json und in den Berichten enthält die Schritte, mit denen sie sich beantworten lässt (howToCheck).
Der Block criteria liest denselben Scan nach WCAG-Erfolgskriterium, so wie man meist fragt („scheitert sie an 1.4.3?“): zuerst fail, dann cantTell und eine Anzahl für notApplicable. Seit @surea11y/core 1.14 steht kein Kriterium mehr unter pass: Ein Kriterium gilt nur dann als bestanden, wenn seine Regeln alles prüfen, was es verlangt, und noch keines ist als vollständig geprüft erfasst. Ergeben alle seine Regeln pass, bleibt es daher cantTell, damit eine Person den Rest prüft. Der Block ändert den Exit-Code nie, und --compact zeigt ihn als Anzahlen. Schlägt keine Regel fehl, endet die Zusammenfassung mit dem Hinweis, dass das keine Aussage über Konformität ist, und nennt, was eine Person noch prüft.
Mehrere Seiten oder eine Sitemap
Nennen Sie mehrere Seiten, listen Sie sie in einer Datei auf (ein Pfad oder eine URL pro Zeile, mit #-Kommentaren), oder richten Sie den Scan auf eine Sitemap:
$ surea11y scan ./dist/index.html ./dist/pricing.html$ surea11y scan --urls pages.txt$ surea11y scan --sitemap https://example.com/sitemap.xml # up to 50 pages; --max-pages to change it
Jede Seite erhält einen eigenen Abschnitt in der Zusammenfassung, eine letzte Zeile zählt die Seiten mit Fehlschlägen, und der Lauf schlägt fehl, sobald eine Seite fehlschlägt. --json gibt ein Array aus, --sarif und --junit schreiben eine Datei für alle Seiten, --html schreibt einen Bericht pro Seite (report.html, report-2.html …), und eine Baseline merkt sich, auf welcher Seite jeder bekannte Fehlschlag war. Eine Sitemap kann eine URL oder eine lokale Datei sein, unkomprimiert oder mit gzip, und einem Sitemap-Index wird eine Ebene tief gefolgt. Eine Seite, die sich nicht scannen lässt, beendet den Lauf mit Exit-Code 2 und wird genannt, bevor etwas geschrieben wird.
In einem echten Browser
Standardmäßig liest die CLI statisches HTML. Für Seiten, deren Inhalt ihr JavaScript rendert, installieren Sie Playwright in Ihrem Projekt und ergänzen --browser: Jede Seite wird in Headless-Chromium geöffnet, ihre Skripte laufen, und der Scan sieht, was gerendert wird, mit echtem Layout für die Regeln, die es messen. Die Engine ist dasselbe @surea11y/core, und jede Option funktioniert damit, auch Berichte, Baselines, Packs und eigene Regeln.
$ npm install --save-dev playwright$ npx playwright install chromium$ surea11y scan https://app.example.com/ https://app.example.com/settings --browser
Eine Anwendung, die ihre Daten nach dem Laden abruft, kann den Scan darauf warten lassen, und eine Seite lässt sich in Smartphone-Breite, im dunklen Modus oder in jeder Kombination mehrerer Werte scannen:
$ surea11y scan https://app.example.com/orders --browser --wait-for "#orders-table"$ surea11y scan https://example.com/ --browser --width 320 --color-scheme dark$ surea11y scan https://example.com/ --browser --width 1280,320 --color-scheme light,dark
--wait-for wartet bis zu 30 Sekunden (--wait-timeout ändert das) und beendet den Lauf mit Exit-Code 2, wenn das Element nie erscheint. Mehrere Breiten oder Farbschemata laden die Seite einmal und führen die Scans zu einem Ergebnis pro Seite zusammen: das schlechteste Ergebnis jeder Regel, und jeder Befund einmal, mit den Kombinationen, in denen er auftrat (seen in:).
Bevor jede Seite lädt, installiert die CLI den Internals- und den Listener-Hook von core. Der Scan beurteilt daher Namen, die Web Components über ElementInternals setzen, und Klick-Handler, die per Skript hinzugefügt wurden: Ein role="button", den Enter und Leertaste nie erreichen, ergibt fail. --live-regions ergänzt den Live-Region-Hook, sodass der Scan zu einer Statusmeldung, die schon mit ihrem Text eingefügt wurde und die Screenreader oft nicht ansagen, eine Frage stellt; --no-hooks lässt die ersten beiden weg. Die Zusammenfassung nennt Viewport, Farbschema und Hooks jedes Scans. Die CLI klickt, tippt und meldet sich nicht an: Für Inhalte, die erst danach erscheinen, steuern Sie den Browser mit einem der Bindings. Frames innerhalb der Seite werden noch nicht gescannt.
Auswählen, was läuft
--wcag wählt die Regeln für ein WCAG-Konformitätsziel aus, nach der Stufe, die jedes Kriterium in dieser Version hat; --wcag-level legt dessen Stufe fest (AA, sofern nichts anderes angegeben ist). --best-practices ergänzt die Regeln, die kein WCAG-Kriterium prüfen, etwa region und heading-order; allein angegeben führt es nur diese aus. --profile führt ein Konformitätsprofil aus, etwa en301549-v4.1.1 oder das eines Packs.
$ surea11y scan ./dist/index.html --wcag 2.2 # WCAG 2.2, Level A and AA$ surea11y scan ./dist/index.html --wcag 2.1 --wcag-level A # WCAG 2.1, Level A$ surea11y scan ./dist/index.html --wcag 2.2 --best-practices # and the best practices
4.1.1 Syntaxanalyse, das WCAG 2.2 entfernt hat, gehört zu einem Ziel 2.1, nicht aber zu einem Ziel 2.2. --rules und --tags ergänzen die Regeln eines Ziels, und --exclude-rules wirkt danach. Neben --profile ergänzt --best-practices seine Regeln, und das Profil gilt weiterhin; --wcag, --rules und --tags wählen die Regeln anstelle eines Profils, daher endet --profile zusammen mit einem davon mit Exit-Code 2. Sie entsprechen runOnly.wcag, runOnly.bestPractices und engineOptions.profile (siehe Engine-Optionen).
Prüfungen selbst benennen
Sind beide angegeben, führen --rules und --tags die Regeln aus, die zu beiden passen. Für „dieser Bereich, und dazu diese Prüfungen“ geben Sie --include-mode or an, das die Regeln ausführt, die zu einem von beiden passen. Ohne diese Option führt der Scan unten keine Regel aus, da contrast-computable nicht mit forms getaggt ist, und endet mit 2, statt ohne geprüfte Regel zu bestehen.
$ surea11y scan ./dist/form.html --tags forms --rules contrast-computable --include-mode or
Ein Scan, der Prüfungen benennt, meldet die WCAG-Kriterien, zu denen sie gehören, auf jeder Stufe. contrast-computable prüft 1.4.3 (AA) und 1.4.6 (AAA), sodass eine Website, die AA erfüllt, ein nicht bestandenes AAA-Kriterium zeigen kann, das sie nie angestrebt hat. Ohne --wcag legt --wcag-level die Stufe der gemeldeten Kriterien fest, ohne zu ändern, welche Regeln laufen:
$ surea11y scan ./index.html --rules contrast-computable --wcag-level AAsurea11y scan: file:///path/to/index.htmlengine: @surea11y/core 1.14.1WCAG level reported: AApass: 1 fail: 0 cantTell: 0 notApplicable: 0occurrences by tier: fail: 0 cantTell: 0criteria (WCAG 2.2 AA):cantTell 1.4.3 Contrast: minimum (partly checked: 1 of 2 checks not selected)A criterion that passes here means the checks that ran found nothing in it,not that the page conforms.No rule failed, which is not a claim that the page conforms: the automated rulesfound nothing definite. A person still checks the cantTell findings, keyboarduse, how a screen reader reads the page, and the content itself.
1.4.3 ist teilweise geprüft: Seine andere Prüfung, contrast-minimum, wurde nicht ausgewählt, daher deckt sein Ergebnis nur die ausgeführte Prüfung ab, und da keine Regel fehlgeschlagen ist, endet die Zusammenfassung mit dem Hinweis, dass das keine Aussage über Konformität ist. Regel-IDs und Stufen werden ohne Rücksicht auf Groß- und Kleinschreibung gelesen (--rules IMG-ALT-PRESENT, --wcag-level aa). --include-mode entspricht engineOptions.includeMode, und --wcag-level ohne --wcag entspricht engineOptions.wcagLevel.
Packs
--pack lädt ein Pack (Regeln, eine Norm oder eine Checkliste und deren Profile) über den Paketnamen, aufgelöst aus dem Projekt des Arbeitsverzeichnisses, oder über einen Pfad; --profile führt eines seiner Profile aus. Wiederholen Sie --pack, um mit mehreren zu scannen.
$ surea11y scan ./dist/index.html --pack @acme/a11y-policy --profile acme-web-2026$ surea11y scan ./dist/index.html --pack ./acme-policy-pack.js --profile acme-web-2026
Die Zusammenfassung nennt das Profil und die Packs, die gelaufen sind, und --json enthält sie als engine.profile und engine.packs. Ein Pack, das sich nicht finden oder laden lässt oder das die Engine überspringt, endet mit Exit-Code 2, ohne dass ein Bericht geschrieben wird, sodass ein Scan nie besteht, während die Prüfungen des Packs nicht gelaufen sind.
Nur bei schwerwiegenden Problemen fehlschlagen
--fail-on-severity (critical, serious, moderate oder minor) lässt den Lauf nur bei fehlschlagenden Regeln ab diesem Schweregrad fehlschlagen; mit --baseline nur bei neuen. Jeder Fehlschlag wird weiter gemeldet, und die Zusammenfassung markiert die unterhalb der Stufe. So kann ein Team zuerst bei schwerwiegenden Problemen blockieren und die Schwelle verschärfen, während der Rückstand schrumpft.
$ surea11y scan --urls pages.txt --fail-on-severity serious
Fragen, die wahrscheinlich nicht erfüllt sind
--fail-on-lean lässt den Lauf auch bei den Fragen fehlschlagen, die wahrscheinlich nicht erfüllt sind (leaningFailures() aus core), ab dem Schweregrad von --fail-on-severity, wenn Sie einen angeben; --lean-fail-wcag-only zählt nur die von Regeln, die einem WCAG-Kriterium zugeordnet sind, ohne die Best Practices. Damit meldet --junit eine solche Regel als fehlgeschlagenen Test und --sarif einen solchen Befund als error, und --write-baseline zeichnet auch die heutigen wahrscheinlichen Fehlschläge auf, sodass --baseline nur bei neuen blockiert. Das ist optional, weil eine Tendenz ein Hinweis ist, kein Beweis: Ob ein Befund tendiert, und in welche Richtung, kann sich in einer Minor-Version von core ändern.
$ surea11y scan ./dist/index.html --fail-on-lean --lean-fail-wcag-only$ surea11y scan ./dist/index.html --fail-on-lean --write-baseline baseline.json # once, commit it$ surea11y scan ./dist/index.html --fail-on-lean --baseline baseline.json # in CI, from then on
Kompakte Ergebnisse
--compact reduziert jedes pass- und notApplicable-Ergebnis auf Regel, Ergebnis und Typ (engineOptions.output.detail: 'findings'): ein kleineres --json für ein Ergebnis, das als CI-Artefakt aufbewahrt wird. Zusammenfassung, Exit-Code, Baseline sowie HTML-, SARIF- und JUnit-Berichte sind dieselben wie ohne die Option.
$ surea11y scan ./dist/index.html --compact --json > result.json
Exit-Codes und Einschränkungen
cantTell beeinflusst den Exit-Code nicht, außer mit --fail-on-lean: 0 bestanden, 1 mindestens ein — bzw. beim Scannen mit --baseline mindestens ein neues — fail auf einer Seite (der Fall für CI-Gating; --fail-on-severity zählt nur die ab seiner Stufe; unter Baseline / Allowlist steht, was als „bekannt“ und was als „neu“ gilt), 2 ein Aufruf- oder Scan-Fehler oder ein Scan, der nichts oder weniger als verlangt geprüft hätte: eine --rules-/--tags-Liste, die keine bekannte Regel und kein bekanntes Tag nennt, ein --context-Selektor, der auf nichts passt, eine eigene Regel oder ein Pack, die nicht gelaufen sind, ein --profile, das nicht angewendet wurde. Eine mit core 1.13 geschriebene Baseline passt weiterhin zu den Befunden, deren Reason Codes 1.14 nach Ursache aufgeteilt hat; --migrate-baseline baseline.json schreibt sie mit den neuen Codes neu.
Ohne --browser liest die CLI nur statisches HTML — eine lokale Datei oder den rohen Body eines HTTP(S)-GET — und führt nie JavaScript der Seite aus. Keiner der beiden Modi klickt, tippt oder meldet sich an: Für Inhalte, die erst danach erscheinen, verwenden Sie eines der Bindings oder rufen die Engine direkt in einem Browser auf, den Sie selbst steuern (Pattern 2 in INTEGRATION.md, dem Integrationsleitfaden auf GitHub).
Vollständige Referenz der Flags, Vertrag für eigene Regeln, Packs und CI-Rezepte: docs/CLI.md. Fertige Vorlagen für CI-Pipelines finden Sie unter CI-Integration.