Special offer. See more information about Outbyte and uninstall instructions. Please review EULA and Privacy policy.

Some links on this page are affiliate links: if you buy through them we may earn a commission, at no extra cost to you.

If a Playwright screenshot shows the logged-out page, the screenshot is usually working correctly: the page was captured in a browser context that lacked valid authentication, or it was captured before the protected UI finished loading. Save login state only after a real post-login signal, load that state into the same project or context that takes the screenshot, restore sessionStorage separately when your app uses it, and wait for the protected panel rather than a fixed delay.

What the screenshot is actually showing

A screenshot contains the pixels available to the page at capture time. Playwright does not transfer cookies, tokens or storage from one browser context to another automatically. A login performed in a setup page, a different test, or a different context therefore has no effect on the context that captures your account page unless you explicitly persist and load the state.

The other common failure is timing. A redirect may still be setting cookies, or the application may fetch the private panel after the document load event. Capture only after a final URL, an authenticated locator, or a successful data response proves that the protected view is ready.

Free tools Windows power users keep installed

One-click scans. No signup required.

Special offer. See more information about Outbyte and uninstall instructions. Please review EULA and Privacy policy.

Use a setup project to create reusable login state

This pattern logs in once, waits for the application’s own success signals, and writes a state file for dependent browser projects.

#1 Best Overall
Sale
Philips 24 Inch Computer Monitor FHD 100Hz VA VESA Flicker-Free, 241V8LB
  • CRISP CLARITY: This 23.8″ Philips V line monitor delivers crisp Full HD 1920x1080 visuals. Enjoy movies, shows and videos with remarkable detail
  • INCREDIBLE CONTRAST: The VA panel produces brighter whites and deeper blacks. You get true-to-life images and more gradients with 16.7 million colors
  • THE PERFECT VIEW: The 178/178 degree extra wide viewing angle prevents the shifting of colors when viewed from an offset angle, so you always get consistent colors
  • WORK SEAMLESSLY: This sleek monitor is virtually bezel-free on three sides, so the screen looks even bigger for the viewer. This minimalistic design also allows for seamless multi-monitor setups that enhance your workflow and boost productivity
  • A BETTER READING EXPERIENCE: For busy office workers, EasyRead mode provides a more paper-like experience for when viewing lengthy documents

1. Authenticate and save state

// tests/auth.setup.ts
import { test as setup, expect } from '@playwright/test';
import path from 'path';

const authFile = path.join(__dirname, '../playwright/.auth/user.json');

setup('authenticate', async ({ page }) => {
  await page.goto('/login');
  await page.getByLabel('Username').fill(process.env.E2E_USER!);
  await page.getByLabel('Password').fill(process.env.E2E_PASSWORD!);
  await page.getByRole('button', { name: 'Sign in' }).click();

  // A redirect can set cookies over several responses.
  await page.waitForURL('**/dashboard');
  await expect(page.getByTestId('user-menu')).toBeVisible();

  await page.context().storageState({ path: authFile });
});

Do not write the file immediately after clicking Sign in. The URL assertion or protected locator must be reached first. If your application has a different success marker, use that marker instead of the example test ID.

2. Make the test project depend on setup

// playwright.config.ts
import { defineConfig } from '@playwright/test';

export default defineConfig({
  projects: [
    { name: 'setup', testMatch: /.*\.setup\.ts/ },
    {
      name: 'chromium',
      use: {
        browserName: 'chromium',
        storageState: 'playwright/.auth/user.json'
      },
      dependencies: ['setup'],
    },
  ],
});

The path is resolved from the configuration context, so verify that the setup writes to the same location the browser project reads. A one-off test can instead select the file directly:

import { test } from '@playwright/test';
test.use({ storageState: 'playwright/.auth/user.json' });

If you create a context yourself with browser.newContext(), pass storageState while constructing it. A manually created fresh context will otherwise be logged out.

What’s actually slowing this PC down?

Pick the symptom - the matching free tool is one click away.

Special offer. See more information about Outbyte and uninstall instructions. Please review EULA and Privacy policy.

Know what storageState includes—and what it does not

Storage or credential Included by storageState What to do
Cookies Yes Check domain, path, Secure and expiry against the URL being captured.
localStorage Yes Confirm the saved origin matches the application origin.
IndexedDB Supported when requested by the Playwright version and application Keep the state generated by the same test environment.
Virtual WebAuthn credentials Supported credentials can be stored Use the documented Playwright WebAuthn setup for your test.
sessionStorage No automatic persistence Serialize it after login and restore it with an initialization script.

Inspect the JSON structure without printing cookie values. You should see expected cookie domains and origin entries. Treat the file as a credential: keep it in a gitignored directory, use a dedicated test account, and never commit or dump its contents to CI logs.

Rank #2
Philips 22 Inch Computer Monitor FHD 100Hz VA VESA Flicker-Free, 221V8LB
  • CRISP CLARITY: This 22 inch class (21.5″ viewable) Philips V line monitor delivers crisp Full HD 1920x1080 visuals. Enjoy movies, shows and videos with remarkable detail
  • 100HZ FAST REFRESH RATE: 100Hz brings your favorite movies and video games to life. Stream, binge, and play effortlessly
  • SMOOTH ACTION WITH ADAPTIVE-SYNC: Adaptive-Sync technology ensures fluid action sequences and rapid response time. Every frame will be rendered smoothly with crystal clarity and without stutter
  • INCREDIBLE CONTRAST: The VA panel produces brighter whites and deeper blacks. You get true-to-life images and more gradients with 16.7 million colors
  • THE PERFECT VIEW: The 178/178 degree extra wide viewing angle prevents the shifting of colors when viewed from an offset angle, so you always get consistent colors

Restore sessionStorage before the first navigation

Applications that keep a login marker only in sessionStorage will still appear logged out after loading a normal state file. Capture the storage after login, store it as a protected test artifact, and install it before navigating to the target origin.

const session = await page.evaluate(() => JSON.stringify(sessionStorage));
// Save `session` securely for this test run.

await context.addInitScript(storage => {
  if (window.location.hostname === 'app.example.com') {
    for (const [key, value] of Object.entries(storage)) {
      window.sessionStorage.setItem(key, value as string);
    }
  }
}, JSON.parse(session));

The hostname guard is important: sessionStorage is scoped to an origin. Do not copy values into unrelated domains, and install the script before the first page navigation so application startup code can see the restored keys.

Use API authentication when UI login is unnecessary

An API login can be faster and less sensitive to changes in the sign-in form. Authenticate with an APIRequestContext, save its state, then create the browser context with that state.

Special offer. See more information about Outbyte and uninstall instructions. Please review EULA and Privacy policy.
import { test as base, expect, request } from '@playwright/test';

base('API-authenticated screenshot', async ({ browser }) => {
  const api = await request.newContext({ baseURL: 'https://app.example.com' });
  const login = await api.post('/api/login', {
    data: {
      username: process.env.E2E_USER,
      password: process.env.E2E_PASSWORD,
    },
  });
  expect(login.ok()).toBeTruthy();

  const state = await api.storageState();
  const context = await browser.newContext({ storageState: state });
  const page = await context.newPage();
  await page.goto('/account');
  await expect(page.getByTestId('private-panel')).toBeVisible();
  await page.screenshot({ path: 'account.png', fullPage: true });

  await context.close();
  await api.dispose();
});

This works when the API response sets the cookies or local-storage values the browser application expects. If the site requires a browser-only challenge, complete that portion in a real page instead.

Rank #3
Sale
Dell 24 Monitor - SE2426H - 23.8-inch FHD (1920x1080) 144Hz 1ms Display, in-Plane Switching (IPS) Technology, AMD FreeSync™, TÜV 3-Star 2X HDMI, Tilt
  • Clear visuals. Fluid motion: A 144Hz refresh rate and 1ms MPRT deliver smooth, tear‑free motion across work, gaming, and streaming for clearer, more fluid viewing.
  • Eye comfort: TÜV Rheinland 3‑star* certification reduces harmful blue light while preserving stunning color quality without compromise. *TÜV Rheinland 3-star eye comfort certification.
  • Wide viewing angle: Get consistent views across a wide 178° /178° viewing angle.
  • In-Plane Switching (IPS): See excellent color accuracy and consistency across wide viewing angles with In-plane Switching (IPS) technology.
  • Ultra-thin bezels: Maximize your viewing experience with thin bezels.

Wait for the protected content, not an arbitrary timeout

URL or protected locator

await page.goto('/account');
await expect(page.getByRole('heading', { name: 'Account' })).toBeVisible();
await expect(page.getByTestId('private-panel')).toContainText('');
await page.screenshot({ path: 'account.png', fullPage: true });

Use the final application URL when redirects are meaningful, and assert on the panel itself when the page shell can load before private data arrives. A locator screenshot performs actionability checks and scrolls the target into view; it cannot create missing authentication.

Wait for the response that proves data arrived

const dataResponse = page.waitForResponse(
  response => response.url().endsWith('/api/me') && response.ok(),
);
await page.goto('/account');
await dataResponse;
await expect(page.getByTestId('private-panel')).toBeVisible();
await page.screenshot({ path: 'account.png' });

Start the response wait before the action that triggers the request. Avoid page.waitForTimeout() in production tests: fixed sleeps are inherently flaky, either wasting time on fast runs or racing slow ones.

Stabilize the final pixels

await expect(page).toHaveScreenshot('account.png');

toHaveScreenshot waits for two consecutive stable screenshots before comparing with a baseline. It helps with animation and layout settling after authentication, but it does not repair missing cookies, tokens or sessionStorage.

Special offer. See more information about Outbyte and uninstall instructions. Please review EULA and Privacy policy.

Diagnostic decision tree

The setup never saved valid state

  • Confirm the sign-in click is awaited.
  • Confirm the final URL or authenticated locator assertion is reached.
  • Confirm the state file timestamp changes and contains expected domains and origins, without exposing values.
  • If identity redirects cross domains, wait for the final application URL before saving.

The test did not load the state

  • Check the path and project name.
  • Ensure the setup project is listed in dependencies.
  • Ensure the test is running in the project whose use block declares storageState.
  • For a manually created context, pass the state during construction.

The state is expired or scoped incorrectly

Sessions and refresh tokens expire. Re-run setup, then compare the saved cookie domain, path, Secure flag and expiry with the URL under test. A cookie for a parent or alternate host may not authenticate the exact host you screenshot.

Rank #4
Samsung 27" Essential S3 (S36GD) Series FHD 1800R Curved Computer Monitor
  • CURVED FOR ENHANCED ENGAGEMENT: An immersive viewing experience with a curved monitor that wraps more closely around your field of vision; It creates a wider view, enhancing depth perception and minimizing peripheral distraction
  • SMOOTH PERFORMANCE FOR SEAMLESS CONTENT: Stay in the action when playing games, watching videos, or working on creative projects; The 100Hz refresh rate reduces lag and motion blur so you don't miss a thing in fast-paced moments¹
  • MORE GAMING POWER: Gain the edge with optimizable game settings; Color and image contrast can be adjusted to see scenes more vividly and spot enemies hiding in the dark; Game Mode adjusts any game to fill the screen so you can view every detail²
  • KEEP IT EASY ON THE EYES: Care for your eyes and stay comfortable, even during long sessions; Advanced eye comfort technology certified by TÜV reduces eye strain by minimizing blue light and reducing irritating screen flicker²
  • INCREASED VERSATILITY: Connect to more; Plug devices straight into your monitor for increased flexibility, making your computing environment even more convenient

The application uses sessionStorage

Implement the serialize-and-restore sequence above, with an origin guard and initialization before navigation. A normal storageState file alone cannot solve this case.

The panel exists but is not visible

  • If it is inside an iframe, use the correct frame locator.
  • If it is lazy-loaded, wait for its own text or visibility condition.
  • If an overlay covers it, dismiss or hide the overlay before capture.
  • Use a locator screenshot for a specific element only after authentication and visibility are proven.

State becomes invalid during a run

Use isolated test accounts and regenerate state when refresh behavior or server-side sessions invalidate it. Service workers, cross-origin identity providers and token refresh code can require application-specific tracing beyond the generic patterns here.

Choose an authentication lifecycle deliberately

Approach Best fit Main maintenance concern
UI login in a setup project Browser-only flows, MFA test doubles and realistic redirects Login form changes can break setup.
API login plus browser state Fast suites where the API issues browser-compatible credentials API and UI must share the expected session model.
Pre-generated state file Small one-off jobs or stable test environments Expiry, rotation and secret handling.
Per-test or worker fixture Tests needing separate accounts or parallel isolation More setup cost and account coordination.
Independent reader supportYour contribution helps us test, update, and keep practical guides available for everyone.Support on Ko-Fi

Or skip the browser setup

For a direct website capture, ScreenshotNeo accepts one GET request and returns PNG, JPEG, WebP or PDF. It can accept the cookie or consent banner before capture and remove more than 60 known consent platforms, newsletter popups and chat widgets; each cleanup step can be disabled. Bot checks, CAPTCHAs, blank pages, timeouts, failed loads and cache hits are not billed, and response headers identify the page verdict and billing result. Its MCP server provides take_screenshot, get_page_info and capture_pdf for Claude, Cursor and other MCP clients.

Special offer. See more information about Outbyte and uninstall instructions. Please review EULA and Privacy policy.
curl -G "https://api.screenshotneo.com/v1/shot" -d access_key=YOUR_API_KEY --data-urlencode url=https://stripe.com -o shot.webp

See the ScreenshotNeo documentation for authentication and options. The same request from Python:

import requests
r = requests.get("https://api.screenshotneo.com/v1/shot", params={"access_key": "YOUR_API_KEY", "url": "https://stripe.com"}, timeout=90)
open("shot.webp", "wb").write(r.content)

And Node.js:

const q = new URLSearchParams({ access_key: 'YOUR_API_KEY', url: 'https://stripe.com' });
const res = await fetch(`https://api.screenshotneo.com/v1/shot?${q}`);

For authenticated pages, provide the required headers or cookies using ScreenshotNeo’s request options rather than trying to reproduce a local Playwright profile. Other useful controls include full-page capture with lazy images, CSS-selector element capture, custom JavaScript and CSS, click and wait conditions, blocked requests, timezone and geolocation, transparent backgrounds, resizing, chosen cache TTLs, signed image links, asynchronous jobs with signed webhooks, bulk capture of up to 100 URLs per call, PDF page settings and a usage API. Every feature is on every plan: 1,000 shots per month are free with no card; paid plans start at $5 for 3,000 shots, with yearly billing giving two months free. Create a free ScreenshotNeo account to try it.

Best Value
Sale
Sceptre New 22-Inch Gaming Monitor, FHD 1080p, Up to 144Hz, HDMI, DisplayPort, Built-in Speakers, Machine Black (E225W-FW144 Series, 2026)
  • 【INTEGRATED SPEAKERS】Whether you're at work or in the midst of an intense gaming session, our built-in speakers provide rich and seamless audio, all while keeping your desk clutter-free.
  • 【EASY ON THE EYES】 Protect your eyes and enhance your comfort with Blue-Light Shift technology. This feature reduces harmful blue light emissions from your screen, helping to alleviate eye strain during long hours of use and promoting healthier viewing habits.
  • 【WIDEN YOUR PERSPECTIVE】Our sleek minimal bezel design ensures undivided attention. The nearly bezel-free display seamlessly connects in a dual monitor arrangement, delivering an unobstructed view that lets you focus on more at once, completely distraction-free.

Security and reliability checklist

  • Use dedicated, least-privilege test accounts.
  • Keep playwright/.auth outside source control and CI artifacts.
  • Never print cookie, token or sessionStorage values.
  • Regenerate state after expiry, password rotation or identity-provider changes.
  • Prefer URL, locator and response signals over sleeps.
  • Capture only after the exact protected content needed for the screenshot is visible.

Frequently Asked Questions

Can I copy cookies manually into a new Playwright page?

It is safer and more complete to use storageState, which preserves the supported cookies and local storage for the context. Manual copying can omit domain, path, expiry or other state.

Why does a full-page screenshot still miss content below the fold?

Full-page mode captures the page layout but does not guarantee that lazy content has loaded. Wait for the component’s own visibility or data condition before capturing.

Special offer. See more information about Outbyte and uninstall instructions. Please review EULA and Privacy policy.

Does toHaveScreenshot log a user in?

No. It only waits for stable pixels and compares them with a baseline; authentication must already be valid.

Product prices and availability are accurate as of the date/time indicated and are subject to change. Any price and availability information displayed on Amazon at the time of purchase will apply.