ScreenshotNeo

BlogHow-to

How to Screenshot a Private Web Page with Playwright in Java

Authenticate a Playwright Java browser context, reuse saved state safely, and capture a private page as a viewport, full-page, or element screenshot.

By the ScreenshotNeo team4 October 20269 min read

To screenshot a private page with Playwright in Java, create a browser context that has the site’s valid authentication state, navigate to the protected URL, then call Page.screenshot(). For repeatable captures, save supported authentication state with BrowserContext.storageState() and load it into a fresh context. Use credentials and state only for accounts and pages you are authorized to access.

The example below shows the workflow. Replace the URLs and add the login steps used by your application. The login interaction is deliberately left as an application-specific step; there is no universal selector or authentication flow.

1. Set up Playwright Java

Add the Playwright Java dependency using the version and build tool already used by your project. After adding the dependency, install the browser binaries required by your environment using the Playwright installation instructions for that version. The code below uses the Java API and Chromium.

2. Sign in, save state, and capture the private page

import com.microsoft.playwright.*;
import java.nio.file.Files;
import java.nio.file.Path;
import java.nio.file.Paths;

public class PrivatePageScreenshot {
  public static void main(String[] args) throws Exception {
    Path authDir = Paths.get("playwright", ".auth");
    Path stateFile = authDir.resolve("state.json");
    Path screenshotFile = Paths.get("private-page.png");
    Files.createDirectories(authDir);

    try (Playwright playwright = Playwright.create()) {
      Browser browser = playwright.chromium().launch();
      try {
        // Establish a signed-in context through the application's normal login flow.
        BrowserContext signedIn = browser.newContext();
        try {
          Page loginPage = signedIn.newPage();
          loginPage.navigate("https://example.com/login");

          // Complete the site's login steps here with authorized test credentials.
          // For example, fill the application's actual fields and submit its form.
          // Wait for a reliable signed-in condition before saving state.

          signedIn.storageState(
              new BrowserContext.StorageStateOptions().setPath(stateFile));
        } finally {
          signedIn.close();
        }

        // Create an isolated context initialized with the saved browser state.
        BrowserContext context = browser.newContext(
            new Browser.NewContextOptions().setStorageStatePath(stateFile));
        try {
          Page page = context.newPage();
          page.navigate("https://example.com/private");
          page.screenshot(new Page.ScreenshotOptions().setPath(screenshotFile));
        } finally {
          context.close();
        }
      } finally {
        browser.close();
      }
    }
  }
}

The state file is sensitive: it may contain cookies or headers that can impersonate the account. Use a dedicated test account, restrict access to the file, and keep it out of version control. For example, add playwright/.auth to .gitignore. Delete or rotate exposed state and credentials if the file is accidentally committed. See the [Playwright Java authentication guide](https://playwright.dev/java/docs/auth) and [screenshot guide](https://playwright.dev/java/docs/screenshots).

3. Choose the screenshot scope and output

Choose the smallest capture that contains the evidence you need. The screenshot APIs work on the authenticated page just as they do on a public page.

Capture Java pattern Use it for
Current viewport page.screenshot(new Page.ScreenshotOptions().setPath(Paths.get("view.png"))) The content currently visible in the browser window.
Full scrollable page page.screenshot(new Page.ScreenshotOptions().setPath(Paths.get("full.png")).setFullPage(true)) A tall capture of the page beyond the current viewport.
One element page.locator(".account-summary").screenshot(new Locator.ScreenshotOptions().setPath(Paths.get("summary.png"))) A specific component or region identified by a CSS selector.
Image bytes byte[] image = page.screenshot(); Passing the image to another in-memory processing or comparison step.

For a locator capture, wait for the locator to be present and visible, and choose a selector that uniquely identifies the intended element. For sensitive pages, the screenshot API also supports controls such as masking locators, clipping, and screenshot scale. Check the [Java Page API](https://playwright.dev/java/docs/api/class-page) and [Java Locator API](https://playwright.dev/java/docs/api/class-locator) for the options available in your installed version.

4. Reuse authentication state safely

Saving state once and loading it into a new context avoids repeating an interactive login for every capture. The documented Java pattern is context.storageState(new BrowserContext.StorageStateOptions().setPath(Paths.get("state.json"))), followed by browser.newContext(new Browser.NewContextOptions().setStorageStatePath(Paths.get("state.json"))).

  • Save only after login succeeds. Wait for an authenticated URL, account-specific element, or another reliable signal. Otherwise you may save an anonymous session.
  • Use an isolated context per capture or worker. Browser contexts created with browser.newContext() are isolated, non-persistent sessions; they do not write ordinary browsing data to disk.
  • Refresh expired state through the approved login flow. A saved cookie can expire or be revoked. Do not treat a state file as a permanent credential.
  • Protect state like a password. Keep it out of source control and public artifacts. Limit access and avoid printing its contents in logs.
  • Check which storage the application uses. Playwright storage state supports cookies, local storage, IndexedDB, and virtual WebAuthn credentials according to the application’s authentication design. A site may require more than one mechanism.

Session storage is a special case: storageState does not automatically persist it. Playwright’s authentication guide describes saving and restoring it separately with page evaluation and an initialization script. The Java Page.sessionStorage() API is listed as available starting in v1.61; verify the behavior supported by your installed version and the target app. Consult the [authentication guide](https://playwright.dev/java/docs/auth) before implementing session-storage handling.

5. Wait for the page state you need

A successful navigation does not guarantee that the page has finished rendering the data you want to capture. Single-page applications may fetch account data after the document loads, and a route may redirect an expired session to a login page.

  1. Navigate to the protected URL.
  2. Wait for a stable, page-specific condition, such as a visible account heading or a completed loading indicator. Prefer this to an arbitrary sleep when the application provides a reliable signal.
  3. Check the final URL and a page-specific locator before saving the image, especially when authentication can expire.
  4. Capture the viewport, full page, or target locator after the intended content is ready.

Choose a readiness condition that reflects the app’s behavior. Avoid assuming that a generic page-load event means every asynchronous widget or private API request has completed.

6. cURL, Python, and Node.js alternatives

These alternatives show the same kind of browser-state requirement in other environments. They are not substitutes for a valid authenticated session. For an existing Java workflow, the Playwright Java example above is the direct solution.

cURL

cURL can request a route with a cookie when the service uses cookie-based authentication and you have an authorized cookie value. It does not run the page’s JavaScript or reproduce an interactive browser session by itself.

curl -L \
  -H 'Cookie: session=YOUR_AUTHORIZED_SESSION_VALUE' \
  'https://example.com/private' \
  -o response.html

Python with Playwright

Python can load a Playwright storage-state file produced by an authorized sign-in flow, then capture the page. The state file format and secret-handling concerns are the same.

from pathlib import Path
from playwright.sync_api import sync_playwright

with sync_playwright() as p:
    browser = p.chromium.launch()
    context = browser.new_context(storage_state="playwright/.auth/state.json")
    page = context.new_page()
    page.goto("https://example.com/private")
    page.screenshot(path="private-page.png", full_page=True)
    context.close()
    browser.close()

Node.js with Playwright

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

(async () => {
  const browser = await chromium.launch();
  const context = await browser.newContext({
    storageState: 'playwright/.auth/state.json'
  });
  const page = await context.newPage();
  await page.goto('https://example.com/private');
  await page.screenshot({ path: 'private-page.png', fullPage: true });
  await context.close();
  await browser.close();
})();

7. Or skip the browser setup

ScreenshotNeo is a website screenshot API and MCP server. Its one-call API is for URLs the service can access; a private page that requires your own login state still needs an authorized access method and should not be treated as accessible just because you have an API key. For public or otherwise accessible URLs, the call is:

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. Before a capture it accepts cookie or consent banners like a visitor and removes 60+ known consent platforms, newsletter popups, and chat widgets; each step can be turned off. Bot checks, blank pages, failed loads, timeouts, and cache hits are not billed, and response headers identify the page verdict and billing status. Its MCP server provides take_screenshot, get_page_info, and capture_pdf for Claude, Cursor, and other MCP clients. The free plan includes 1,000 screenshots a month with no card; paid plans start at $5 for 3,000 screenshots.

Sign up for 1,000 free screenshots a month, with no card required.

8. Troubleshooting

Symptom Likely cause Fix
The protected route shows a login page. The state was saved before login completed, has expired, or lacks a required storage mechanism. Confirm login success before saving, refresh the state through the approved flow, and check whether the app depends on session storage or another auth mechanism.
Navigation redirects to a different route. The session is invalid, the account lacks permission, or the app redirects on a missing prerequisite. Inspect the final URL and page content; verify the test account’s access and the app’s expected login flow.
The screenshot is blank or missing data. The capture ran before client-side rendering or a data request finished. Wait for a page-specific locator or loading condition before capturing; confirm the page is displaying the expected account data.
The state file cannot be read. The path is wrong, the file was not created, or the process user cannot access it. Create the parent directory, use the same resolved path for saving and loading, and check file permissions.
A new context is unexpectedly signed out. The site’s auth depends on state not included in storage state, commonly session storage, or the saved session was revoked. Follow the authentication guide for the missing storage type and verify the installed Playwright version.
A locator screenshot fails or captures the wrong element. The selector matches no element, multiple elements, or a hidden element. Use a stable, unique selector; wait for visibility; inspect the matched locator before capture.
The full-page image is extremely tall or slow to process. The page has a very long scroll area, expanding content, or lazy-loaded regions. Use a viewport or locator screenshot if it meets the need; otherwise ensure lazy content has loaded and plan for the larger image.
Browser launch fails in a clean environment. The Playwright browser binary or required runtime dependencies are unavailable. Install the browser binaries and system dependencies using the official instructions for your operating system and Playwright version.

9. Performance, reliability, and cost

  • Reuse the browser process, isolate contexts. Keeping a browser open across multiple captures avoids repeated browser startup while separate contexts isolate cookies and page data. Close pages, contexts, and the browser when finished.
  • Wait on conditions, not long fixed delays. A page-specific readiness signal avoids capturing too early and avoids unnecessary waiting when content is already ready.
  • Capture only what you need. Viewport or locator images are generally smaller outputs than full-page images. Full-page capture may involve a large image that takes longer to encode, transfer, or compare.
  • Make batch jobs resilient. Handle navigation and screenshot failures per URL, record the target and failure stage without logging cookies or state contents, and refresh authentication when the app rejects the session.
  • Budget for browser infrastructure. A self-hosted Playwright workflow needs a compatible runtime, browser binaries, and enough memory and disk for browser processes and screenshots. The sources do not establish numerical performance or cost benchmarks.
  • Use a hosted API when it fits the access model. ScreenshotNeo charges only for clean shots; its stated plans range from 1,000 free monthly shots to paid tiers. A browser-based private-page capture still needs a safe, supported way to provide authorization; do not send private credentials or cookies to a service unless its documented workflow and your security requirements permit it.

10. FAQ

Does Playwright’s storage-state file contain the password?

It is not a password manager. It can contain sensitive cookies and headers that may let someone impersonate the account, so protect it as a credential.

Can I capture a page without signing in through the UI every time?

Yes, if the site’s authentication can be represented by supported saved state and that state remains valid. Save it after a successful authorized login and reload it into a fresh context.

Will storageState preserve session storage?

No. Session storage needs separate handling; consult the authentication documentation and confirm support in your Playwright Java version.

Can I save the screenshot without writing a file first?

Yes. Page.screenshot() returns a byte[], which can be passed to a later processing step or written using your application’s storage code.