ScreenshotNeo

BlogHow-to

Python Playwright Screenshot with HTTP Authentication

Set HTTP credentials on a Playwright browser context, capture a protected page, and handle full-page, origin-scope, and application-login cases.

By the ScreenshotNeo team4 October 20267 min read

Set http_credentials on the Playwright browser context before creating a page. Then navigate to the protected URL and call page.screenshot(). The example below saves a full-page PNG; set an explicit origin when the credentials should only apply to one site.

from playwright.sync_api import sync_playwright

with sync_playwright() as p:
    browser = p.chromium.launch()
    context = browser.new_context(
        http_credentials={
            "username": "YOUR_USERNAME",
            "password": "YOUR_PASSWORD",
            "origin": "https://example.com",
        }
    )
    page = context.new_page()
    page.goto("https://example.com/protected", wait_until="networkidle")
    page.screenshot(path="screenshot.png", full_page=True)
    browser.close()

Use credentials only for systems you are authorized to access. The authentication option belongs to the browser context: setting credentials on a separate API request context does not authenticate browser page navigation.

1. Install Playwright and its browser

Install the Python package, then install the browser binary that the script will launch. The following commands use Chromium:

python -m pip install playwright
python -m playwright install chromium

Save the example as screenshot.py, set the target URL and credentials, then run python screenshot.py. In production, load credentials from environment variables or a secret manager instead of putting them in source code.

2. Configure HTTP authentication on the browser context

Playwright’s browser.new_context() accepts http_credentials. The context applies those credentials to pages created from it. The browser context must be configured before new_page() and navigation.

The dictionary accepts username, password, and optional origin and send fields. An origin has the form scheme://host:port. For example, https://example.com uses the default HTTPS port. If you include a non-default port, include it in the origin.

Credential send behavior

Setting Behavior When to use it
send: "unauthorized" Default. Sends credentials after a 401 response with a WWW-Authenticate challenge. Use for the usual HTTP authentication flow.
send: "always" Sends credentials with each request. Use only if the server requires preemptive credentials, and scope them to a specific origin.

Without an origin, credentials may be sent to any server that challenges with unauthorized status. Set the origin when you know which site needs authentication. For multiple origins, the API accepts a list of credential records. The first entry matching the request origin is selected; an entry without an origin can match any request, so avoid catch-all entries when credentials must be restricted.

context = browser.new_context(
    http_credentials=[
        {
            "username": "REPORT_USER",
            "password": "REPORT_PASSWORD",
            "origin": "https://reports.example.com",
        },
        {
            "username": "ADMIN_USER",
            "password": "ADMIN_PASSWORD",
            "origin": "https://admin.example.com",
            "send": "always",
        },
    ]
)

Confirm the exact fields available in the version you install in the Playwright Browser API reference.

3. Choose the screenshot output

Playwright screenshots can be written to a file or returned as bytes. A regular screenshot captures the current viewport; full_page=True captures the full scrollable page.

Viewport PNG saved to a file

page.screenshot(path="screenshot.png")

Full-page PNG saved to a file

page.screenshot(path="screenshot.png", full_page=True)

Screenshot bytes for further processing

image_bytes = page.screenshot(full_page=True)
with open("screenshot.png", "wb") as image_file:
    image_file.write(image_bytes)

For an element capture, use a locator rather than the older discouraged ElementHandle screenshot API:

page.locator("main article").screenshot(path="article.png")

See the Playwright screenshot guide for screenshot options supported by the installed version, including file type and image handling.

4. Handle application login separately

HTTP authentication and a website’s own sign-in form are different mechanisms. If the site authenticates with a form and stores a session in cookies, local storage, IndexedDB, or another browser mechanism, http_credentials will not sign in to the application.

For application login, automate the sign-in flow or save authenticated browser state and load it into a later context. A saved state file can contain cookies and headers that allow someone to impersonate the account. Keep it out of version control and treat it like a password.

# After completing an authorized application login in `context`:
context.storage_state(path="playwright/.auth/state.json")

# Later, initialize a new context with the saved state:
authenticated_context = browser.new_context(
    storage_state="playwright/.auth/state.json"
)

Follow the Playwright authentication guide for storage-state details and security handling.

5. Wait for the right page state

A successful navigation does not always mean the page is ready to capture. Choose a wait condition appropriate to the page:

  • wait_until="load" waits for the load event (the default).
  • wait_until="domcontentloaded" waits for initial document parsing, which can be faster when the page continues loading assets.
  • wait_until="networkidle" waits for network activity to settle; analytics, polling, or long-lived requests can prevent it from settling.

For a known page element, a targeted wait is often more reliable than waiting for all network traffic to stop:

page.goto("https://example.com/protected", wait_until="domcontentloaded")
page.locator("main h1").wait_for(state="visible", timeout=15000)
page.screenshot(path="screenshot.png", full_page=True)

Use a finite timeout and make the readiness condition specific to the content you need. A delay can be useful for a known animation, but it is less dependable than waiting for a selector that indicates the page is ready.

6. Troubleshoot common failures

Symptom Likely cause Fix
401 response or authentication prompt remains The server uses a different authentication scheme, the credentials are incorrect, or the origin does not match. Check username and password, scheme, host, and port. Confirm the protected endpoint actually uses HTTP authentication and that its origin matches the configured origin.
Credentials work in an API call but not in the page Credentials were configured on an API request context rather than the browser context. Set http_credentials on browser.new_context() before creating the page.
Credentials are not sent until after a challenge The default send mode is unauthorized. Keep the default for challenge-based authentication. If the server requires preemptive auth, use send: "always" with a precise origin scope.
Application redirects to a sign-in page The site uses application-level login rather than HTTP authentication. Automate its login flow or initialize the context from valid saved browser state.
Navigation times out on a page that appears loaded The page may keep connections open or continuously make requests. Use a different navigation wait condition, then wait for a specific visible content selector before capturing.
Screenshot is blank or missing content The capture ran before the required content rendered, or the target selector did not match. Wait for a visible page element and verify the URL and page state before capture. For lazy-loaded full pages, inspect whether scrolling or page-specific loading is needed.
Browser launch fails on a new machine The Playwright package is installed but its browser binary or system dependencies are missing. Run python -m playwright install chromium; consult the Playwright installation instructions for the operating system.
Auth state exposes a session A storage-state file was committed, logged, or shared. Remove the file from tracked artifacts, restrict access, and invalidate the stored session if it may have been exposed.

7. Reliability, performance, and cost

Browser screenshots include the cost of launching or reusing a browser, navigating the site, waiting for the page, and rendering the image. Reusing a browser process can avoid repeated startup work in a long-running worker; create isolated contexts for separate jobs or identities so cookies and credentials do not leak between captures.

Full-page screenshots can take longer and use more memory than viewport captures, especially for very long pages. Use viewport or locator screenshots when they satisfy the task. Set navigation and selector timeouts, close pages and contexts when finished, and handle navigation failures explicitly in batch jobs. Do not log passwords, authorization headers, cookies, or storage-state contents.

Playwright is software you run, so there is no per-screenshot service charge from Playwright itself; account for the compute and infrastructure you operate. If a managed screenshot API better fits the workload, compare its authentication support, capture controls, failure handling, and billing model against your requirements.

8. Or skip the browser setup

ScreenshotNeo is a website screenshot API and MCP server. A single GET request can return a PNG, JPEG, WebP, or PDF. See the ScreenshotNeo API documentation for its parameters and response details.

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}`);
if (!res.ok) throw new Error(`Screenshot request failed: ${res.status}`);
await Bun.write('shot.webp', res);

For Python and Node.js, install the relevant HTTP client or use a runtime that provides the shown APIs. Store the API key as a secret. The example captures a public URL; use the documented request options for authenticated targets.

  • Cookie banners are accepted like a visitor, and 60+ known consent platforms, newsletter popups, and chat widgets are removed before the shot; each step can be turned off.
  • Bot checks, blank pages, timeouts, failed loads, and cache hits cost nothing. Response headers identify the page verdict and billing status.
  • An 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, no card required.

9. FAQ

Does HTTP authentication make the screenshot public?

No. The credentials let the Playwright browser request protected content. The output image may itself contain private information, so store and share it with the same care as the page.

Can one browser context use credentials for multiple sites?

Yes. Pass a list of credential records scoped to their origins. The first matching origin is used; avoid unscoped entries if credentials should only reach named sites.

Can I capture only one component?

Yes. Use page.locator("your-selector").screenshot(path="component.png") after the target is visible.

Where can I check the current API details?

Use the official Playwright references for network authentication, browser context credentials, screenshots, and API request contexts.