ScreenshotNeo

BlogHow-to

How to Take Screenshots of Web Pages Behind a Login

Capture a page you can access after signing in: use Firefox for a one-time image or Playwright for repeatable screenshots from an authorized session.

By the ScreenshotNeo team4 October 20267 min read

How do I take a screenshot of a web page behind a login? Sign in normally, open the page you are authorized to view, then capture the rendered page in that browser session. For a one-time capture, Firefox has built-in screenshot tools. For repeatable captures, use Playwright with a valid authenticated browser session. A screenshot captures what the session renders; these methods do not bypass login controls.

Choose the smallest capture that meets your need: the visible viewport, the full scrollable page, or one element. Review the output before sharing it, especially if the page contains personal, financial, workplace, or account information.

1. Take a one-time screenshot in Firefox

  1. Sign in through the site’s normal login flow and navigate to the page you are permitted to access.
  2. Right-click an empty part of the page and choose Take Screenshot. Firefox also documents the Ctrl+Shift+S shortcut on Windows and Linux, and Command+Shift+S on macOS.
  3. Choose the visible area or full page, then copy or download the image.
  4. For an element-only image, inspect the page and use the Inspector’s node screenshot action if available in your Firefox version.

Firefox’s built-in screenshot feature supports visible and full-page captures. Its interface can vary by version. See Mozilla’s Firefox screenshot instructions.

2. Capture an authenticated page repeatedly with Playwright

Playwright is useful when the capture must run as part of a script or be repeated. The script below loads a previously saved browser storage state, opens a page, waits for a page-specific element, and saves both viewport and full-page captures. It does not log in, solve MFA or CAPTCHA, or renew an expired session.

Install

mkdir authenticated-screenshots
cd authenticated-screenshots
npm init -y
npm install playwright
npx playwright install chromium

Create auth-state.json from a browser context that you authenticated through the site’s normal flow. For example, in an approved local setup, your own Playwright bootstrap can call await context.storageState({ path: 'auth-state.json' }) after you have signed in. Protect this file like a password: it may contain reusable session cookies. Do not commit it, upload it, or include it in a screenshot. Some sites bind sessions to a browser, device, or network, or keep authentication in browser-managed state that is not represented by storage state. In those cases, use the site’s documented session approach and do not try to evade its controls.

Runnable capture script

// capture.mjs
import { chromium } from 'playwright';

const url = process.env.PAGE_URL;
if (!url) throw new Error('Set PAGE_URL to the page URL you are authorized to access.');

const browser = await chromium.launch({ headless: true });
try {
  const context = await browser.newContext({ storageState: 'auth-state.json' });
  const page = await context.newPage();
  await page.goto(url, { waitUntil: 'domcontentloaded', timeout: 60000 });

  // Replace this with a stable selector that appears only when the page is ready.
  await page.locator('main').waitFor({ state: 'visible', timeout: 30000 });

  // Viewport capture and complete scrollable-page capture.
  await page.screenshot({ path: 'page-viewport.png', scale: 'css' });
  await page.screenshot({ path: 'page-full.png', fullPage: true, scale: 'css' });

  // Optional: capture one element instead of the whole page.
  // await page.locator('[data-testid="report"]').screenshot({ path: 'report.png' });
} finally {
  await browser.close();
}
PAGE_URL='https://example.com/account/report' node capture.mjs

Replace the example URL and readiness selector with values for the page you are allowed to view. The selector matters: a generic main element may appear before asynchronously loaded content does. Playwright supports page, element, and full-page screenshots; fullPage: true captures the full scrollable document. Playwright screenshot guide · Page screenshot API.

Choose the capture area and output

Need Playwright option Notes
Visible viewport page.screenshot({ path: 'page.png' }) Captures the current viewport by default.
Whole scrollable page fullPage: true Useful for reports and long pages. Extremely tall pages can create large images or hit browser and memory limits.
One component page.locator('selector').screenshot(...) Wait for the intended element and confirm the selector matches the right one.
Specific rectangle clip: { x, y, width, height } Coordinates are page screenshot coordinates; use a locator screenshot when possible to avoid brittle coordinates.
Smaller high-DPI output scale: 'css' Uses one image pixel per CSS pixel. 'device' preserves device-pixel resolution and may make output larger.
Hide sensitive region mask: [page.locator('selector')] Explicitly masks selected elements with an overlay. It does not discover sensitive data automatically; inspect the image.
Format and quality type: 'jpeg', quality: 80 Quality applies to JPEG and WebP, not PNG. The path extension can also determine the type.

Example with a deliberate mask and JPEG output:

await page.screenshot({
  path: 'redacted.jpg',
  type: 'jpeg',
  quality: 85,
  fullPage: true,
  scale: 'css',
  mask: [page.locator('[data-sensitive]')]
});

Playwright also exposes clipping, screenshot timeouts, transparent backgrounds, animation handling, and screenshot buffers. See the API option reference for the exact option set in your installed version.

3. Make repeat captures more reliable

  • Wait for content, not just navigation. A successful navigation does not guarantee that client-rendered data, charts, or images have finished loading. Wait for a stable, page-specific locator.
  • Handle redirects explicitly. After navigation, inspect page.url() and confirm the page is still the expected destination rather than a sign-in or access-denied page.
  • Keep state fresh and private. Sessions expire. Re-authenticate through the normal flow when authorized, refresh the state file, and keep it out of source control and logs.
  • Make output deterministic. Fix viewport dimensions with browser.newContext({ viewport: { width: 1440, height: 1000 }, storageState: 'auth-state.json' }). Prefer stable selectors and wait for fonts or key images if they affect the result.
  • Mask intentionally. Mask known sensitive fields before capture, then inspect the final artifact. Overlays, pseudo-elements, canvas content, and other data outside selected locators may still be visible.
  • Use the narrowest permissions and retention. Keep captures and session state in a private location, restrict access, and delete them when no longer needed.

4. Troubleshoot common problems

Symptom Likely cause What to do
Screenshot shows the login page State was missing, expired, or not accepted; site redirected the session. Check page.url(), authenticate through the normal flow, refresh the saved state, and try again. Do not attempt to bypass the site’s access controls.
Page is blank or only partly rendered Capture ran before client-side content was ready, or the page failed to load data. Wait for a stable, visible page-specific locator. Check the page and network errors in the authorized browser session.
Element locator times out Selector is wrong, content is in a frame, or the expected element never appeared. Inspect the rendered DOM, use a stable selector, and account for the correct frame when applicable.
Full-page image is huge or capture fails Long documents can require substantial memory and produce large files. Capture a needed section or element, use CSS scale, or split the work into appropriate sections.
Image has missing images or fonts Resources load after the screenshot or are blocked by the session/network. Wait for the relevant resources or page-specific ready state; verify the page itself displays them first.
Sensitive value remains visible Mask selector missed the value or the value was rendered elsewhere. Inspect the image, correct the selector, and add masks for each known region. Never assume automatic detection.
Works locally but fails in scheduled runs Different network, browser, environment, or expired session changes access. Run with an authorized environment and fresh valid state; log redirect destinations and errors without logging secret cookies or credentials.

5. Performance, reliability, and cost

Local browser automation has no screenshot API charge, but it uses compute and browser memory. Full-page captures, device-pixel scale, high-resolution images, and multiple browser contexts increase resource use. Capture only what you need, reuse a browser process for a batch where appropriate, and close pages and browsers reliably. Set navigation and locator timeouts so a stalled page does not hold a job indefinitely.

Authentication is the main reliability dependency: session expiry, MFA requirements, network restrictions, and site-specific session handling can interrupt automation. Build a clear failure path that records whether navigation reached the intended page, while keeping credentials and session artifacts private. Neither Firefox nor Playwright makes a page accessible if the current session is not authorized.

Or skip the browser setup

ScreenshotNeo is a website screenshot API and MCP server. One GET request takes a screenshot from a URL. For a page behind a login, use it only if the page can be accessed through a supported authorized request setup; a URL alone does not grant access to a private account page. See the ScreenshotNeo API documentation.

curl -G "https://api.screenshotneo.com/v1/shot" -d access_key=YOUR_API_KEY --data-urlencode url=https://stripe.com -o shot.webp
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)
const q = new URLSearchParams({ access_key: 'YOUR_API_KEY', url: 'https://stripe.com' });
const res = await fetch(`https://api.screenshotneo.com/v1/shot?${q}`);

ScreenshotNeo removes cookie banners, popups, and chat widgets before the shot. 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; paid plans start at $5 for 3,000. Sign up free and get 1,000 screenshots a month with no card.

FAQ

Can a screenshot tool get into an account for me?

No. Capture the page only after you have authorized access in a valid session.

Will the screenshot include content below the fold?

Firefox offers full-page capture. In Playwright, set fullPage: true; otherwise, the screenshot is the viewport.

Does masking guarantee the image contains no private information?

No. It masks the elements you select. Review the resulting image for other sensitive content.