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

iTechGuides is reader-supported. When you buy through links on our site, we may earn an affiliate commission. As an Amazon Associate I earn from qualifying purchases. Learn more

Log in through the site’s supported flow, wait until the authenticated state is visible, and capture the protected page in that browser context with fullPage: true. To reuse the login in a later run, save the context’s storage state and load it into the capture context. Treat that state file like a password: it can contain credentials that allow someone to impersonate the account.

Capture a protected page in the authenticated context

If you are already logged in on the page you want to capture, you can take the screenshot directly. The essential option is fullPage: true, which captures the page’s full scrollable area instead of only the visible viewport. See the Playwright Page API.

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

If you need to log in first, keep the same browser context for the protected-page visit and screenshot. Replace the example URLs, accessible labels, and success signal with the ones used by the target site:

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

const browser = await chromium.launch();
const context = await browser.newContext();
const page = await context.newPage();

await page.goto('https://example.com/login');
await page.getByLabel('Username').fill(process.env.SITE_USERNAME!);
await page.getByLabel('Password').fill(process.env.SITE_PASSWORD!);
await page.getByRole('button', { name: /sign in/i }).click();
await expect(page.getByRole('button', { name: /account|profile/i })).toBeVisible();

await page.goto('https://example.com/protected');
await expect(page.getByRole('main')).toBeVisible();
await page.screenshot({ path: 'page.png', fullPage: true });

await context.close();
await browser.close();

Do not put real credentials directly in source code or check them into version control. Supply them securely through your run environment or secret-management system. A successful click is not proof that login finished: redirects, application initialization, and cookie setup may still be in progress. Wait for a site-specific authenticated element or final URL before continuing.

Save login state to reuse it in another run

For repeated captures, authenticate once, save the browser context’s storage state, then create a context from that file in the capture run. Playwright’s authentication guide recommends keeping authentication files in playwright/.auth and adding that directory to .gitignore.

  1. Authenticate: Open the login page, fill credentials securely, submit, and wait for a reliable post-login signal.
  2. Save state: Call context.storageState({ path: authFile }) only after the success condition is met.
  3. Load state: Create a new context with storageState: authFile, then visit the protected URL.
  4. Wait and capture: Wait for meaningful page readiness and call page.screenshot({ path: 'page.png', fullPage: true }).
import { chromium, expect } from '@playwright/test';

const authFile = 'playwright/.auth/user.json';
const browser = await chromium.launch();

// Login run
const loginContext = await browser.newContext();
const loginPage = await loginContext.newPage();
await loginPage.goto('https://example.com/login');
await loginPage.getByLabel('Username').fill(process.env.SITE_USERNAME!);
await loginPage.getByLabel('Password').fill(process.env.SITE_PASSWORD!);
await loginPage.getByRole('button', { name: /sign in/i }).click();
await expect(loginPage.getByRole('button', { name: /account|profile/i })).toBeVisible();
await loginContext.storageState({ path: authFile });
await loginContext.close();

// Capture run, using the saved authenticated state
const captureContext = await browser.newContext({ storageState: authFile });
const capturePage = await captureContext.newPage();
await capturePage.goto('https://example.com/protected');
await expect(capturePage.getByRole('main')).toBeVisible();
await capturePage.screenshot({ path: 'page.png', fullPage: true });

await captureContext.close();
await browser.close();

The saved file can contain cookies and headers that allow account impersonation. Keep it out of source control, restrict who and what can read it, avoid printing its contents, and delete or regenerate it when it expires or is no longer needed. Playwright documents the storage-state mechanisms in its BrowserContext API.

Choose state reuse based on how the account is used

Saved state avoids repeating the UI login, but it may expire or become invalid. Playwright’s guide documents a setup-project pattern for shared authentication when tests do not conflict over server-side state. If parallel tests mutate shared server-side data, use separate accounts per worker rather than assuming one saved session is safe to share.

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

Know what storage state does—and does not—preserve

Playwright storage state covers cookies and local storage. The BrowserContext API also documents optional snapshots for IndexedDB (added in v1.51), WebAuthn credentials (v1.61), and OPFS (v1.63). Use those options only if the application needs the corresponding storage mechanism; the API notes that OPFS is not supported in ephemeral WebKit contexts.

Session storage is a key exception: Playwright’s normal storage-state workflow does not persist it across page loads. If the application relies on it for authentication, the Playwright authentication guide describes a manual approach: read the values from the page, save them securely, and use context.addInitScript to restore them on the matching hostname before the application loads. Scope the script narrowly and never expose session tokens in logs. If the site uses MFA, SSO, CAPTCHA, short-lived tokens, device binding, or server-side session invalidation, its supported login flow or a fresh session may be required; behavior varies by site.

Wait for the content that should appear in the screenshot

A full-page screenshot captures the full scrollable page, but it does not guarantee that every deferred asset or application widget has loaded. Wait for a meaningful, site-specific condition—for example, a key element being visible or a known loading indicator disappearing—rather than relying on an arbitrary pause alone. If the site loads images or feed items only after scrolling, reproduce the necessary interaction and verify the resulting image; there is no universal Playwright setting that forces every lazy-loaded or infinite-scroll component to render.

Choose a file capture or visual assertion

Use page.screenshot when you want to write an image artifact. If you are using Playwright Test to check a visual baseline, use expect(page).toHaveScreenshot() instead. Its screenshot assertion waits for two consecutive screenshots to match before comparing against the baseline; it is a test assertion, not a substitute for saving a one-off screenshot. See the PageAssertions API.

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

Troubleshoot common failures

  • The screenshot shows a login page: The login may not have completed, the protected URL may redirect unauthenticated visitors, or the saved state may have expired. Wait for an authenticated UI signal before saving state; after loading it, verify that the protected page reaches its expected URL and content.
  • The success check times out: The example’s labels and account/profile button are illustrative. Inspect the site’s actual accessible labels and choose a stable post-login element or final URL. Some sites require handling an intermediate redirect or consent step.
  • State works in one run but not another: Check whether authentication depends on session storage, IndexedDB, another documented storage type, or a short-lived/device-bound session. Use the appropriate supported mechanism and create fresh state when the site invalidates old sessions.
  • The page is captured before it is ready: Replace a generic navigation wait with an application-specific readiness condition. For delayed content, trigger the site’s required scroll or interaction and confirm that the content appears before capturing.
  • The screenshot is unexpectedly incomplete: Confirm that you used fullPage: true. Then check whether the missing content is actually in the page’s scrollable document or is rendered only after a site-specific action.
  • Authentication state is exposed: Treat the state file as a credential. Remove it from any tracked repository, restrict access, rotate or regenerate the session, and avoid logging its contents.
Independent reader supportYour contribution helps us test, update, and keep practical guides available for everyone.Support on Ko-Fi

Or skip the browser setup

ScreenshotNeo is a website screenshot API and MCP server from Yorker Media. It returns a screenshot or PDF from one GET request; it is a practical alternative when you want a hosted capture rather than managing a Playwright browser and authentication state yourself. It is not a way to bypass a protected login: this example does not provide a mechanism for supplying a site’s authenticated session.

For a public page, one call can capture the URL as WebP:

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 API parameters and options. Cookie banners, popups, and chat widgets are removed before capture; bot checks, blank pages, and failed loads are never billed. Its MCP server lets AI agents take screenshots. The free plan includes 1,000 screenshots a month with no card, and paid plans start at $5 for 3,000. Sign up for ScreenshotNeo’s free plan.

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.

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