ScreenshotNeo

BlogHow-to

How to Use a Screenshot API to Capture a Page Behind a Login

Capture a login-protected page with a session cookie, HTTP Basic auth, or token header. Learn when to use Playwright, how to protect credentials, and how to verify the screenshot.

By the ScreenshotNeo team4 October 20269 min read

A screenshot API can capture a page behind a login when the browser that performs the capture receives authentication the site accepts. For a repeatable capture, that usually means passing a valid session cookie or an Authorization header; HTTP Basic authentication may also work when the site uses it. If login requires clicking through a form, handling redirects, or completing multiple steps, use browser automation such as Playwright to sign in, preserve the resulting browser state, navigate to the protected page, wait for its content, and capture it.

Use only an account and session you are authorized to access. Authentication values and saved browser state can grant access to the account, so treat them as secrets.

1. Choose the authentication method

What the site requires Capture approach What to check
Session cookie Pass the current cookie to a hosted screenshot endpoint that supports cookies. Cookie name, value, domain, path, expiry, and secure settings must match the site.
HTTP Basic authentication Use the endpoint’s documented Basic Auth option, if available. Confirm the endpoint expects an authentication object and whether redirects remain protected.
Bearer token or other request header Set the appropriate Authorization header in the browser request configuration. Some applications authenticate their page through browser storage or API calls instead of the initial document request.
Interactive or multi-step login Use Playwright to complete sign-in and reuse the authenticated browser state. Handle MFA and other account controls through an authorized workflow; do not attempt to bypass them.

Hosted screenshot APIs differ: support for cookies, credentials, and headers is provider-specific. For example, Cloudflare Browser Run documents cookie input, HTTP Basic authentication through an authenticate parameter, and token authentication through setExtraHTTPHeaders. Its endpoint also documents navigation waits, viewport settings, full-page capture, and selector capture. Consult the [Cloudflare Browser Run screenshot documentation](https://developers.cloudflare.com/browser-run/quick-actions/screenshot-endpoint/) for its current request schema; do not assume those fields work with another provider.

This Cloudflare Browser Run example illustrates a hosted capture request using a session cookie. Replace the endpoint account identifier and API token with your own Cloudflare values, and use the exact request format in the current documentation. The API token authorizes your request to Cloudflare; the cookie separately authenticates the browser to the target website.

curl -X POST 'https://api.cloudflare.com/client/v4/accounts/ACCOUNT_ID/browser-rendering/screenshot' \
  -H 'Authorization: Bearer CLOUDFLARE_API_TOKEN' \
  -H 'Content-Type: application/json' \
  --data '{
    "url": "https://example.com/account",
    "cookies": [
      {
        "name": "session",
        "value": "SESSION_COOKIE_VALUE",
        "domain": "example.com",
        "path": "/"
      }
    ],
    "gotoOptions": {
      "waitUntil": "networkidle",
      "timeout": 30000
    },
    "viewport": {
      "width": 1440,
      "height": 1000
    },
    "screenshotOptions": {
      "fullPage": true
    }
  }' \
  --output authenticated-page.png

Cookie fields and output behavior are provider-specific. A cookie scoped to app.example.com may not be sent to example.com; a cookie scoped to /admin may not apply to another path. Use a current cookie from the authorized session and avoid putting its value in shell history, shared logs, or source control.

HTTP Basic authentication

When the target uses HTTP Basic authentication, use the screenshot provider’s documented authentication object. Cloudflare documents an authenticate parameter with a username and password. Check its current schema and protect both credentials as secrets. Do not assume that adding a Basic Authorization header is equivalent for every endpoint: some providers require a separate field or browser option.

Bearer tokens and custom headers

For a site that accepts a bearer token in browser requests, configure an Authorization: Bearer … header using the provider’s browser header mechanism. Cloudflare documents setting extra browser headers with setExtraHTTPHeaders. A token that only authorizes an API request to the screenshot service does not automatically authenticate the browser to the target site. Keep these two credentials separate.

3. Use Playwright for interactive login and reusable state

Choose browser automation when authentication depends on filling a form, following a redirect, accepting an authorized prompt, or preserving state that a simple screenshot request cannot express. The example below is runnable with Node.js and Playwright. It signs in, saves browser storage state, opens the protected page, waits for a page-specific element, and writes a full-page screenshot.

import { chromium } from 'playwright';

const browser = await chromium.launch({ headless: true });
const context = await browser.newContext();
const page = await context.newPage();

try {
  await page.goto('https://example.com/login', { waitUntil: 'domcontentloaded' });
  await page.getByLabel('Email').fill(process.env.SITE_EMAIL);
  await page.getByLabel('Password').fill(process.env.SITE_PASSWORD);
  await page.getByRole('button', { name: 'Sign in' }).click();

  // Replace this with a selector that proves your app is signed in.
  await page.waitForURL('**/dashboard', { timeout: 30000 });
  await page.getByTestId('account-dashboard').waitFor({ state: 'visible', timeout: 30000 });

  // The file contains reusable authentication material. Keep it private.
  await context.storageState({ path: 'playwright/.auth/state.json', indexedDB: true });

  await page.goto('https://example.com/account/report', { waitUntil: 'domcontentloaded' });
  await page.getByTestId('report-content').waitFor({ state: 'visible', timeout: 30000 });
  await page.screenshot({ path: 'authenticated-page.png', fullPage: true });
} finally {
  await browser.close();
}

Install Playwright and its browser runtime in your project before running this script. Supply SITE_EMAIL and SITE_PASSWORD through your secret manager or environment, not as literals committed to a repository. Adapt labels and test IDs to the page. The official [Playwright authentication guide](https://github.com/microsoft/playwright/blob/main/docs/src/auth.md) explains saved state and its contents; the [Playwright Page API](https://playwright.dev/docs/api/class-page) documents navigation and screenshots.

Reuse saved state in another run

After the authorized sign-in step has produced a state file, create a context from it and capture the page:

import { chromium } from 'playwright';

const browser = await chromium.launch({ headless: true });
const context = await browser.newContext({
  storageState: 'playwright/.auth/state.json'
});
const page = await context.newPage();

try {
  await page.goto('https://example.com/account/report', { waitUntil: 'domcontentloaded' });
  await page.getByTestId('report-content').waitFor({ state: 'visible', timeout: 30000 });
  await page.screenshot({ path: 'authenticated-page.png', fullPage: true });
} finally {
  await browser.close();
}

Playwright storage state covers cookies, local storage, IndexedDB when requested, and virtual WebAuthn passkeys. Session storage is domain-specific and is not automatically preserved by the usual storage-state workflow; if the app depends on it, save and restore it explicitly for the correct origin. Saved state may contain cookies and headers usable to impersonate the account, so exclude it from source control, restrict file permissions, and refresh it when the session expires.

4. Wait for the signed-in content and validate the image

A successful HTTP response or screenshot job does not prove that the captured page is authenticated or fully rendered. After navigation, wait for a stable, page-specific signal such as a dashboard heading, report container, or account marker. A generic network-idle wait can be insufficient for applications that continually poll or load content after the initial page response.

  1. Navigate to the protected URL after authentication has been applied.
  2. Wait for a selector that appears only when the expected signed-in content is present.
  3. Choose viewport or full-page capture based on what the image needs to show; capture a selector when only one panel matters.
  4. Inspect the resulting image for a login screen, expired-session notice, blank region, or unfinished chart.
  5. If it is wrong, verify the cookie scope and expiry, header forwarding, redirects, storage origin, and readiness selector before changing image dimensions.

5. Common errors and fixes

Symptom Likely cause Fix
Screenshot shows the login page Cookie is missing, expired, scoped to another domain/path, or not forwarded; required Authorization header was not set. Check the target site’s accepted authentication method and verify the browser request receives the right credential. Refresh the session if needed.
Capture shows an access-denied page The account lacks permission, the session is invalid, or the application requires additional state. Confirm the account can access the page in a normal browser and reproduce its required authorized flow.
Page is blank or only partly rendered Capture occurred before client-side content, charts, or images were ready. Wait for a page-specific selector or a suitable delay, then inspect the result. Use a timeout appropriate to the page and provider.
Login succeeds but the next navigation is unauthenticated Auth state was not saved or loaded for the same origin; session storage may be required. Save context state after sign-in, load it into the later context, and explicitly handle session storage if the app uses it.
Cookie is rejected Cookie domain/path or secure requirements do not match the destination, or the value has expired. Use the current cookie and correct domain/path attributes. Avoid copying unrelated cookies.
Navigation or selector times out Redirects differ from the expected URL, the selector changed, or the page never reaches the chosen readiness state. Inspect the final URL and page state, select a stable signed-in marker, and adjust the timeout only after identifying the expected behavior.
Request returns an API error The service token, account identifier, endpoint, or provider-specific JSON fields are wrong. Separate the service API credential from target-site authentication and compare the request with the provider’s current API documentation.

6. Security, reliability, and cost considerations

  • Credentials: Treat cookies, bearer tokens, passwords, and Playwright state files as account credentials. Keep them out of repositories, logs, screenshots, and public examples. Restrict access and rotate or refresh them according to your site’s session rules.
  • Output privacy: A screenshot can expose personal or confidential data even when the credentials remain secret. Store and share captures according to the data’s sensitivity.
  • Reliability: Sessions expire, sites change login flows, and client-side content can load asynchronously. Use a page-specific readiness check and validate captured output; retry only when the failure is plausibly transient, and refresh authentication when it has expired.
  • Hosted versus self-managed: A hosted API avoids running the browser runtime yourself, but depends on its supported authentication fields and service availability. Playwright offers direct control over browser actions and state, while requiring you to operate the runtime and protect saved credentials.
  • Cost: Provider pricing and billing behavior vary. The reviewed technical sources do not establish a neutral price or performance comparison; check the current provider terms and account for browser execution, retries, storage, and operational work in your own workflow.

Or skip the browser setup

ScreenshotNeo is a website screenshot API and MCP server. For a page your authorized session can reach, send the supported cookie or authorization material in the request configuration described in the ScreenshotNeo API documentation. Here is the one-call public-page form; adapt the target URL and add authentication parameters supported by the API docs for your use case.

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}`);

Cookie banners, popups, and chat widgets are removed before the shot. Bot checks, blank pages, and failed loads are never billed. An 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. Check the docs for supported authentication parameters before sending credentials.

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

FAQ

Can a screenshot API log into any website?

No. It can capture authenticated content only when the target’s authentication method and any required browser state are supported. Some flows need interactive automation, and some sites may require custom handling.

Is the screenshot service API key the same as the website password?

No. The service key authorizes your request to the screenshot provider. The target site’s cookie, password, or token authenticates the browser to that site.

Why does a screenshot look successful but contain a login screen?

The capture can complete normally while the browser lacks valid target-site authentication. Confirm the rendered content itself, not just the job or HTTP status.

Can I use this for a private dashboard?

Yes, when you are authorized to access it and can provide the required authentication safely. Also protect the resulting image, which may contain private information.