Zurück zum Blog

Playwright Screenshot Leitfaden: Full Page, Element & Visual Diffs

Von MorganVeröffentlicht 7. Mai 202610 min Lesezeit

Ein Playwright-Screenshot ist ein einzeiliger API-Aufruf: await page.screenshot({ path: 'page.png' }). Playwright erfasst standardmäßig den Viewport, die komplette scrollbare Seite mit fullPage: true oder jedes DOM-Element über einen Locator. Es liefert auch eingebaute visuelle Regression mit toHaveScreenshot() und funktioniert in Node, Python, Java und .NET.

Wenn du code-getriebene Erfassungen innerhalb einer Test-Suite oder eines Scrapers brauchst, ist Playwright in 2026 die beste Wahl. Für Ad-hoc-Desktop-Screenshots passt ein GUI-Tool besser.

Wann du Playwright für Screenshots nutzen solltest

Playwright ist für Browser-Automatisierung gebaut. Greife darauf zurück, wenn du folgendes brauchst:

  • Automatisierte Screenshots in CI für visuelle Regressionstests
  • Scraping von Seiten, die mit JavaScript rendern
  • Generieren von Social Cards, OG-Bildern oder PDFs aus HTML
  • Cross-Browser-Erfassungen (Chromium, Firefox, WebKit) aus einem Skript

Wenn du nur eine schnelle Desktop-Erfassung oder ein markiertes Bild für ein Doc brauchst, überspringe das Setup und nutze ein natives Tool. Wir behandeln das kurz am Ende.

Setup: Playwright in 60 Sekunden installieren

Du brauchst Node.js 18 oder neuer. Vom Projekt-Root aus:

npm init -y
npm install -D @playwright/test
npx playwright install

Der Schritt npx playwright install lädt die Browser-Binärdateien für Chromium, Firefox und WebKit herunter. Sie landen in einem Playwright-Cache, nicht in node_modules, sodass sie nur einmal pro Maschine heruntergeladen werden.

Smoke-Test

Speichere dies als smoke.js und führe node smoke.js aus:

const { chromium } = require('playwright');

(async () => {
  const browser = await chromium.launch();
  const page = await browser.newPage();
  await page.goto('https://example.com');
  await page.screenshot({ path: 'smoke.png' });
  await browser.close();
})();

Wenn smoke.png neben deinem Skript landet, hat die Installation funktioniert. Dieselben fünf Zeilen lassen sich direkt nach Python (from playwright.sync_api import sync_playwright), Java (Playwright.create()) und .NET (await using var playwright = await Playwright.CreateAsync()) portieren. Wähle die Sprache, die dein Team bereits ausliefert, und spare dir die Umschreibe-Kosten.

Projektstruktur für Tests

Wenn du mehr als eine Handvoll Screenshot-Skripte schreiben willst, gerüste ein echtes Test-Projekt:

npm init playwright@latest

Das erstellt playwright.config.ts, einen Beispieltest und eine CI-Workflow-Datei. In der Konfiguration legst du Baseline-Viewport-Größe, Standard-Timeout und die Browser fest, gegen die getestet wird.

Kern-Screenshot-Operationen mit Code-Beispielen

Jedes Beispiel unten nutzt die Node.js-API. Die Signaturen für Python, Java und .NET sind nahezu identisch, nur umbenannt für die Host-Sprache.

Seiten-Screenshot (Standard-Viewport)

await page.screenshot({ path: 'page.png' });

Erfasst nur das, was im aktuellen Viewport sichtbar ist. Standardgröße ist 1280 mal 720. PNG ist das Standardformat.

Full-Page-Screenshot

await page.screenshot({ path: 'full.png', fullPage: true });

Playwright passt den Screenshot an die volle Dokumenthöhe an, scrollt die Seite virtuell im Hintergrund und fügt das Bild zusammen. Du musst nicht selbst scrollen. Fixierte und sticky Elemente können sich während der Erfassung bewegen, das ist normal.

Diagramm Full-Page versus einzelner Element-Screenshot
Diagramm Full-Page versus einzelner Element-Screenshot

Element-Screenshot

const heading = page.locator('h1');
await heading.screenshot({ path: 'h1.png' });

Die Locator-API beschränkt die Erfassung auf einen einzelnen DOM-Knoten. Playwright wartet automatisch, bis das Element angehängt, sichtbar und stabil ist, bevor es schießt. Allein das eliminiert eine Klasse von Flakes, die du mit manuellen setTimeout-Waits hättest.

Eine bestimmte Region zuschneiden

await page.screenshot({
  path: 'clip.png',
  clip: { x: 0, y: 0, width: 800, height: 400 }
});

Nützlich, wenn ein Element-Selektor fragil ist, aber die Koordinaten bekannt sind, zum Beispiel ein Diagramm, das auf einem gezeichnet wird.

Buffer statt Datei

const buffer = await page.screenshot();
// Zu S3 hochladen, an Slack-Nachricht anhängen, aus einem Lambda zurückgeben...
await s3.putObject({ Bucket: 'shots', Key: 'a.png', Body: buffer }).promise();

Lass das path-Argument weg und du bekommst direkt einen Node-Buffer. Praktisch in Serverless-Flows, wo das Dateisystem read-only ist.

Custom Viewport (Retina, Mobile, Ultrawide)

const context = await browser.newContext({
  viewport: { width: 1920, height: 1080 },
  deviceScaleFactor: 2  // Retina-Ausgabe
});
const page = await context.newPage();

deviceScaleFactor: 2 verdoppelt die Pixeldichte, derselbe Trick, den ein Mac-Display für scharfen Text nutzt. Verwende es, wenn der Screenshot auf einer Retina-Marketing-Seite landen wird.

Animationen deaktivieren

await page.screenshot({
  path: 'stable.png',
  animations: 'disabled'
});

Das ist die Lösung für flaky CI-Läufe. Playwright pausiert CSS-Animationen und Transitions und spult sie an den Anfang zurück, sodass ein Spinner mitten in der Drehung deinen Diff nicht zerstören kann.

Sensible Elemente maskieren

await page.screenshot({
  path: 'safe.png',
  mask: [page.locator('.user-email'), page.locator('.api-key')]
});

Mask malt einen pinken Kasten (konfigurierbar mit maskColor) über die passenden Elemente. Perfekt für Marketing-Site-Erfassungen, in denen echte Kundendaten durchsickern.

Visuelle Regression mit `toHaveScreenshot()`

Das ist das Killer-Feature. Playwright bündelt eine Pixel-Diff-Assertion, die Baselines speichert, in CI ausführt und bei Fehlschlag Diff-Bilder schreibt. Keine zusätzliche Bibliothek, kein Percy-Konto, keine Gebühr.

import { test, expect } from '@playwright/test';

test('homepage looks right', async ({ page }) => {
  await page.goto('https://example.com');
  await expect(page).toHaveScreenshot('home.png', {
    maxDiffPixelRatio: 0.01,
    animations: 'disabled'
  });
});

Der Workflow

  1. Führe npx playwright test --update-snapshots einmal aus. Playwright speichert die Baseline neben deiner Test-Datei.
  2. Committe diese Baselines in git.
  3. Beim nächsten Lauf macht Playwright einen frischen Screenshot, vergleicht ihn mit der Baseline und schreibt home-diff.png, wenn die Änderung maxDiffPixelRatio überschreitet.
  4. Prüfe den Diff. Wenn die Änderung beabsichtigt ist, führe --update-snapshots erneut aus. Wenn nicht, behebe den Bug.
Visuelle Regressions-Diff-Illustration mit Baseline- und aktuellen Screenshots
Visuelle Regressions-Diff-Illustration mit Baseline- und aktuellen Screenshots

Für eine tiefere Anleitung inklusive Baseline-Strategie und Toleranz-Tuning siehe unseren Leitfaden zu visuellen Regressionstests.

Visueller Diff auf Element-Ebene

await expect(page.locator('.pricing-card')).toHaveScreenshot('card.png');

Eine Komponente zu diffen ist schneller und weit weniger flaky als eine ganze Seite zu diffen. Fang dort an.

Häufige Stolperfallen (und wie du sie behebst)

Diese erwischen fast jeden in der ersten Woche.

Lazy-geladene Bilder verpassen den Screenshot

Die Lösung ist, zu warten, bis das Netzwerk ruhig ist, oder das Element zuerst in den Sichtbereich zu scrollen.

await page.goto(url, { waitUntil: 'networkidle' });
// oder für ein einzelnes Element
await page.locator('img.lazy').scrollIntoViewIfNeeded();

networkidle wartet 500 ms nach der letzten Anfrage. Es funktioniert für die meisten Sites, kann aber bei Seiten mit Long-Poll-Verbindungen hängen.

Animationen machen Screenshots flaky

Übergib immer animations: 'disabled'. Wenn du auch JS-Animationen auf einem hast, mocke den Timer:

await page.addInitScript(() => {
  window.requestAnimationFrame = (cb) => cb(0);
});

Viewport vs. Dokument

Ein Standard-Screenshot erfasst nur den Viewport, auch wenn die Seite 8.000 Pixel hoch ist. Übergib fullPage: true oder ein clip-Rechteck. Das ist die häufigste Verwirrung in Bug-Reports.

Headless vs. headed Unterschiede

Headless Chromium kann Schriften leicht anders rendern als der Headed-Build, besonders auf Linux. Wenn dein lokaler Mac und dein Ubuntu-CI-Runner unterschiedliche Baselines produzieren, setze in beiden dasselbe Docker-Image. Das offizielle mcr.microsoft.com/playwright-Image bringt die Schriften mit.

Eingeloggte Seiten und Auth-Status

Logge dich nicht in jedem Test ein. Logge dich einmal ein, speichere den Storage State und nutze ihn wieder.

// global-setup.js
await page.context().storageState({ path: 'auth.json' });

// playwright.config.ts
use: { storageState: 'auth.json' }

Jetzt startet jeder Screenshot-Test bereits eingeloggt. Das hält auch Geheimnisse aus den Test-Dateien fern und verkürzt die Test-Laufzeit, indem wiederholte Login-Flows übersprungen werden.

Falsches Format oder falsche Qualität

PNG ist Standard und das, was du für visuelle Diffs willst, da es verlustfrei ist. Für Social Cards oder Hero-Bilder, wo Größe zählt, wechsle zu JPEG mit einem Quality-Flag:

await page.screenshot({ path: 'card.jpg', type: 'jpeg', quality: 85 });

Quality ist eine Skala von 0 bis 100 und gilt nur für JPEG. WebP wird als Ausgabeformat noch nicht unterstützt, du kannst aber den Buffer mit sharp konvertieren, wenn du es brauchst.

Häufige Stolperfallen Referenzillustration mit Warnsymbolen und Code
Häufige Stolperfallen Referenzillustration mit Warnsymbolen und Code
ScreenSnap Pro
Gesponsert von den Machern

Genug von langweiligen Screenshots? Probier ScreenSnap Pro.

Wunderschöne Hintergründe, professionelle Annotationen, GIF-Aufnahme und sofortiges Cloud-Sharing — alles in einer App. Einmalig 29 $, für immer deins.

Sieh, was es kann

Playwright vs. Puppeteer für Screenshots

Beide Bibliotheken können einen Screenshot in einer Zeile erstellen. Wo sie auseinandergehen:

FunktionPlaywrightPuppeteer
BrowserChromium, Firefox, WebKitChromium, Firefox (Beta)
SprachenJS, TS, Python, Java, .NETNur JS, TS
Visueller Diff eingebautJa (toHaveScreenshot)Nein (braucht pixelmatch)
Sensible Elemente maskierenJaNein
Auto-Wait vor ErfassungJaEingeschränkt
Animations-FlagJaNein

Für reines Chrome-only-Scraping ist Puppeteer schlanker. Für Tests oder irgendetwas Cross-Browser gewinnt Playwright. Die volle Aufschlüsselung ist in unserem Puppeteer vs. Playwright Vergleich.

Wenn du auch gehostete Screenshot-Dienste für Produktionsverkehr evaluierst, deckt unsere Übersicht der besten Screenshot-APIs ab, wann eine API einen selbst betriebenen headless Browser schlägt.

Playwright-Screenshots in CI ausführen (GitHub Actions)

Lege das in .github/workflows/screenshots.yml ab:

name: Screenshot tests
on: [push, pull_request]

jobs:
  test:
    runs-on: ubuntu-latest
    steps:
      - uses: actions/checkout@v4
      - uses: actions/setup-node@v4
        with:
          node-version: 20
      - run: npm ci
      - run: npx playwright install --with-deps
      - run: npx playwright test
      - uses: actions/upload-artifact@v4
        if: always()
        with:
          name: playwright-report
          path: playwright-report/
          retention-days: 30

Das --with-deps-Flag installiert System-Bibliotheken, die Chromium auf einem frischen Ubuntu-Runner braucht. Der Artefakt-Upload bewahrt Diff-Bilder und den HTML-Report, wenn ein Test fehlschlägt, sodass du prüfen kannst, was sich geändert hat, ohne neu zu laufen.

Für Docker-basierte Pipelines tausche den Runner gegen das offizielle Image, um Schriften identisch zur lokalen Entwicklung zu halten:

container:
  image: mcr.microsoft.com/playwright:v1.50.0-jammy
GitHub Actions Playwright CI-Workflow-Illustration
GitHub Actions Playwright CI-Workflow-Illustration

Wann du Playwright nicht brauchst

Playwright ist für Automatisierung. Wenn das Ziel ein schneller Screenshot deines Bildschirms, eines Fensters oder einer Region ist, plus ein oder zwei Pfeile, sind die Setup-Kosten verschwendet. Ein natives Tool ist schneller.

Für Ad-hoc-Captures mit Annotation, sofortigen Cloud-Links und null Code schau dir ScreenSnap Pro an. Es läuft auf Mac und Windows, liefert 15 Annotations-Tools und ist ein einmaliger Kauf für 29 $ statt eines Abos. Keine Playwright-Konfiguration nötig.

Du kannst auch Screenshots online annotieren mit unserem kostenlosen Browser-Tool, wenn du nur ein bestehendes PNG markieren musst.

Häufig gestellte Fragen

Wie erstelle ich einen Full-Page-Screenshot in Playwright?

Übergib fullPage: true an page.screenshot(). Playwright passt die Erfassung an die volle Dokumenthöhe an und fügt das Bild zusammen, sodass du nicht manuell scrollen musst. Beispiel: await page.screenshot({ path: 'full.png', fullPage: true }).

Was ist der Unterschied zwischen `page.screenshot()` und `locator.screenshot()`?

page.screenshot() erfasst den Viewport oder die ganze Seite mit fullPage: true. locator.screenshot() erfasst ein einzelnes DOM-Element, beschränkt auf seine Bounding Box. Die Locator-Variante wartet auch automatisch, bis das Element sichtbar und stabil ist, bevor es schießt, was eine häufige Quelle von Flakes eliminiert.

Kann ich Screenshots im headless-Modus erstellen?

Ja, headless ist Standard. Führe chromium.launch() aus und Playwright startet ohne UI-Fenster. Um visuell zu debuggen, übergib { headless: false } und beobachte, wie der Browser sich selbst steuert. Beide Modi produzieren denselben Screenshot, headless kann Schriften auf Linux aber leicht anders rendern.

Wie vergleiche ich Screenshots in Playwright?

Nutze expect(page).toHaveScreenshot('name.png') innerhalb einer Playwright-Test-Datei. Der erste Lauf speichert eine Baseline. Folgende Läufe vergleichen damit und schreiben name-diff.png, wenn die Änderung deine Toleranz überschreitet. Stelle die Empfindlichkeit mit maxDiffPixelRatio oder maxDiffPixels ein.

Funktioniert Playwright in CI?

Ja. Das offizielle Docker-Image (mcr.microsoft.com/playwright) wird mit vorinstallierten Browsern und Schriften ausgeliefert. Auf GitHub Actions führe npx playwright install --with-deps aus und du bist startklar. Lade das playwright-report/-Verzeichnis als Artefakt hoch, damit fehlgeschlagene Diffs den Lauf überleben.

Wie mache ich einen Screenshot einer eingeloggten Seite?

Logge dich einmal in einem Global-Setup-Skript ein, speichere die Cookies und Local Storage mit context.storageState({ path: 'auth.json' }) und richte deine Konfiguration auf diese Datei. Jeder Test startet bereits eingeloggt, kein wiederholter Login-Flow pro Test.

Kann Playwright ein PDF oder canvas-Element per Screenshot erfassen?

Ja für canvas, da es ein DOM-Element ist. Nutze page.locator('canvas').screenshot(). Für PDFs kann Playwright keinen nativen PDF-Viewer per Screenshot erfassen, aber page.pdf() (nur Chromium) rendert die aktuelle HTML-Seite als PDF-Datei.

Zusammenfassung

Playwright's Screenshot-API deckt alles ab, von einer einzeiligen Viewport-Erfassung bis zu einer kompletten visuellen Regressions-Suite, über vier Sprachen und drei Browser-Engines hinweg. Beginne mit page.screenshot({ fullPage: true }), ergänze animations: 'disabled' und mask für Stabilität und steige dann auf toHaveScreenshot() um, wenn du willst, dass CI UI-Regressionen für dich abfängt.

Wenn dein Screenshot-Bedarf eher "ein markiertes PNG in Slack ablegen" als "eine Homepage in CI diffen" ist, überspringe das Setup und nutze ein Desktop-Tool. So oder so hast du jetzt das Playbook.

Autor
Morgan

Morgan

Indie Developer

Indie developer, founder of ScreenSnap Pro. A decade of shipping consumer Mac apps and developer tools. Read full bio

@m_0_r_g_a_n_
ScreenSnap Pro — turn plain screenshots into polished visuals with backgrounds and annotations
Verfügbar fürmacOS&Windows

Lass jeden Screenshot pro aussehen.

ScreenSnap Pro verwandelt einfache Screenshots in polierte Visuals — Hintergründe, Annotationen, GIF-Aufnahme und sofortige Cloud-Links.

ScreenSnap Pro entdecken