Do these 3 things before closing this tab:
1Clear out junk files and repair common Windows errors2Fix the driver behind crashes, sound loss and screen glitches3Repair Windows errors before they cause bigger problemsTo capture several authenticated pages, save a logged-in Playwright context with context.storageState(), then create a browser context from that state and visit each URL. Take each image with page.screenshot(). The example below saves one full-page PNG per URL and checks for a signed-in element to avoid silently capturing a login redirect.
What storage state does—and what it does not
A Playwright BrowserContext holds browser state and can contain multiple Page objects (tabs). Save state from a context after a successful login, then pass the saved file when creating another context. Pages visited in that context use the same initialized login state, so you can capture several URLs without logging in separately for each one.
As an Amazon Associate I earn from qualifying purchases.
Storage state is not a guarantee that every site will accept the session indefinitely. Expiration, MFA, device binding, IP restrictions, or site-specific rules can require a fresh login or a different flow. Choose a reliable post-login check for the site—such as a signed-in navigation item or a final URL—and verify it again after navigating to each protected page.
Log in once and save the state
Install Playwright for Node.js if needed, then save this as save-auth.js. Replace the example URL, selectors, and credentials with values appropriate to your application. The selectors and successful-login condition are site-specific; do not assume that a button click alone proves authentication succeeded.
#1 Best Overall
const { chromium } = require('playwright');
(async () => {
const browser = await chromium.launch({ headless: false });
const context = await browser.newContext();
const page = await context.newPage();
try {
await page.goto('https://example.com/login');
await page.locator('input[name="email"]').fill(process.env.APP_EMAIL);
await page.locator('input[name="password"]').fill(process.env.APP_PASSWORD);
await page.getByRole('button', { name: 'Sign in' }).click();
// Replace this with a condition that confirms login for your application.
await page.getByTestId('signed-in-navigation').waitFor({ state: 'visible' });
await context.storageState({ path: 'playwright/.auth/user.json' });
console.log('Saved authenticated state.');
} finally {
await context.close();
await browser.close();
}
})();
Create the destination directory before running the script. For example, from a shell, run mkdir -p playwright/.auth, set APP_EMAIL and APP_PASSWORD in your environment, and run node save-auth.js. Interactive login, MFA, or an application-specific authentication step may need to be completed in the browser before the post-login check can pass.
Protect the state file
The file can contain cookies or headers that let someone impersonate the account. Treat it like a credential: exclude playwright/.auth from Git, do not put the file in public artifacts, and limit who can read it. If the session expires, authenticate again and replace the state file.
Capture multiple authenticated pages
Save this as capture-pages.js. Replace the URLs and signed-in selector with application-specific values. This version visits the pages sequentially in one context, checks that a signed-in element remains visible, and writes distinct full-page PNG files.
Quick wins for a faster PC:
Repair Windows errors before they cause bigger problemsFix Now →Fix the driver behind crashes, sound loss and screen glitchesFind Drivers →Clear out junk files and repair common Windows errorsFree Scan →Rank #2
const { chromium } = require('playwright');
const targets = [
{ url: 'https://example.com/account', file: 'screenshots/account.png' },
{ url: 'https://example.com/account/settings', file: 'screenshots/settings.png' },
{ url: 'https://example.com/account/billing', file: 'screenshots/billing.png' },
];
(async () => {
const browser = await chromium.launch();
const context = await browser.newContext({
storageState: 'playwright/.auth/user.json',
viewport: { width: 1440, height: 1000 },
});
try {
const page = await context.newPage();
for (const target of targets) {
await page.goto(target.url, { waitUntil: 'domcontentloaded' });
// Replace with a reliable signed-in indicator from your site.
await page.getByTestId('signed-in-navigation').waitFor({ state: 'visible' });
// Replace with an application-specific ready condition if needed.
await page.screenshot({ path: target.file, fullPage: true });
console.log(`Saved ${target.file}`);
}
} finally {
await context.close();
await browser.close();
}
})();
Make sure the output directory exists first: mkdir -p screenshots. Run the capture with node capture-pages.js. The loop reuses one page and one context. You can instead create several pages with context.newPage() in the same context when separate tabs are useful; each page still uses that context’s initialized browser state.
Choose a readiness condition, not just a delay
domcontentloaded means the document has been parsed; it does not mean that client-rendered data, images, or all application content is ready. Wait for the specific content that matters to the screenshot, for example:
await page.getByRole('heading', { name: 'Account settings' }).waitFor({ state: 'visible' });when that heading signals the page is ready.await page.locator('.report-table tbody tr').first().waitFor({ state: 'visible' });when the capture depends on report rows.await page.waitForLoadState('networkidle');only when network quiet is suitable for the application; polling or long-lived connections can make it an unreliable condition.
A fixed delay can be used when the application has no better observable signal, but it can make captures slow and still fail when loading takes longer than expected.
Rank #3
Viewport or full-page capture
By default, page.screenshot({ path }) captures the visible viewport. Setting fullPage: true captures the full scrollable page. The filename extension determines the image format; the examples use PNG. If you omit path, Playwright returns image bytes instead of writing a file. Use unique paths when capturing different pages so a later screenshot does not overwrite an earlier one.
What’s actually slowing this PC down?
Pick the symptom - the matching free tool is one click away.
Use one context or several?
- One account, sequential screenshots: one context initialized from one storage-state file is the simple choice. Pages in that context share the same browser state.
- Several tabs for one account: create multiple
Pageobjects in the same context. This shares the context’s state and browser settings. - Different identities or roles: create separate contexts initialized from the corresponding saved states. Do not try to represent two accounts with pages in one context.
- Parallel work that changes server-side state: separate accounts may avoid interference. Reusing one account in parallel tests can lead to conflicts when those tests modify shared server-side data.
For read-only screenshot tours, sequential navigation in one context is generally straightforward. If the pages trigger writes or otherwise affect account data, assess the application’s side effects before running captures concurrently.
Storage-state limits and sessionStorage
The saved state can include cookies and local storage. The BrowserContext API also documents options for saving IndexedDB, virtual WebAuthn credentials, and origin private file system (OPFS) data. These options are version-dependent: IndexedDB capture was added in Playwright v1.51, virtual WebAuthn credentials in v1.61, and OPFS in v1.63. Check the API documentation for the Playwright version installed in your project before relying on them. The API notes that OPFS is currently unsupported in ephemeral WebKit contexts. Restoring virtual WebAuthn credentials installs a virtual authenticator, which prevents real authenticators from working in that context; saved credentials include private-key material.
Session storage is different: Playwright’s authentication guide says there is no built-in storageState API for persisting it. It is domain-specific and is not persisted across page loads. If—and only if—the target app depends on session storage for authentication, the guide demonstrates reading it from a page and restoring it with context.addInitScript() so it is present before application code runs. That requires an application-aware workaround; do not add it when cookies or local storage already provide the needed session.
Troubleshooting missed or misleading screenshots
The page redirects to login
Check that the state was saved only after the successful-login condition passed, that the capture script points to the correct state file, and that the session has not expired. Confirm that the post-navigation signed-in indicator exists on the target pages; a screenshot of a login page can otherwise look like a successful capture.
Free tools Windows power users keep installed
One-click scans. No signup required.
The login succeeded, but a later page is unauthenticated
The application may rely on sessionStorage, an additional identity provider step, device or network restrictions, or a page-specific authorization check. Confirm the app’s authentication mechanism and follow its required flow. If sessionStorage is required, restore it before application scripts run rather than expecting storageState to contain it.
The readiness wait times out
Verify that the selector belongs to the current page and is visible in the signed-in state. A selector may differ between pages, be hidden responsively at the chosen viewport, or appear only after a different application event. Use a per-URL ready selector when necessary, and inspect the final URL or page content to distinguish a slow load from a redirect.
Output files are missing or overwritten
Create the output directory before capture and make every target’s file path unique. Check that the script is running from the directory you expect; relative paths are resolved from the process’s working directory. Keep the extension aligned with the desired image format.
The screenshot is incomplete or inconsistent
Wait for the specific content that must appear, rather than assuming document parsing means the page is ready. Stabilize the viewport and browser settings between runs. For long pages use fullPage: true; remember that the result is still only a visual capture and does not prove that expected data or authentication was correct.
The Tool Desk
Outbyte Driver Updater FREEScan for outdated or missing drivers - takes under a minuteDriver Scan →Outbyte PC Repair FREEClear out junk files and repair common Windows errorsFree Scan →Or skip the browser setup
For a public page that does not require your logged-in browser session, ScreenshotNeo can return a screenshot with one GET request. For example, using cURL:
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 API documentation for the request options. ScreenshotNeo accepts consent banners as a visitor and removes 60+ known consent platforms, newsletter popups, and chat widgets before capture; each step can be turned off. Bot checks/CAPTCHAs, blank pages, timeouts, failed loads, and cache hits are not billed, and response headers indicate the page verdict and billing status. Its MCP server provides take_screenshot, get_page_info, and capture_pdf tools for AI agents. The free plan includes 1,000 screenshots per month with no card; paid plans start at $5 for 3,000 shots. This API workflow is for pages the service can access; it does not reuse the authenticated browser state saved in your Playwright context.
Sign up for ScreenshotNeo to get 1,000 screenshots a month free, with no card.
Visual comparison is a different task
If the goal is to save reference images, page.screenshot() writes the files shown above. Playwright Test’s toHaveScreenshot() is instead intended for visual snapshot comparisons. Its snapshots are PNG by default and can be updated with --update-snapshots; use it when you need comparison assertions rather than simply collecting screenshots.
Recommended Free Tools
Quick Recap
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.




