ScreenshotNeo

BlogHow-to

How to Take a Selenium Screenshot of a Page Behind a Login

Log in with Selenium, wait for protected content, and save a screenshot. Includes cookie setup, full-page options, troubleshooting, and an API alternative.

By the ScreenshotNeo team4 October 20269 min read

To take a Selenium screenshot of a page behind a login, establish an authenticated browser session, navigate to the protected page, wait for a page-specific readiness signal, and save the screenshot. If authentication is setup for a test, Selenium recommends establishing application state outside the browser login flow when possible, such as using a permitted API to log in and then setting a cookie. If you are testing the login flow itself, automate the form.

1. Choose how to authenticate

Use the approach that matches what the test is meant to verify:

Goal Approach Why
Test a protected page or feature Use an application-supported test fixture or permitted authentication API to establish state, then set the required cookie if that is how the application works. It avoids repeating UI login setup and can make tests faster and more stable. Selenium describes API login followed by setting a cookie as one way to gain access to the application under test. Selenium: Generating application state.
Test the login behavior Drive the login form with Selenium and verify the authenticated result. The login interaction is part of the behavior under test. Authentication methods vary; an old Selenium article discusses form-based and HTTP authentication, but it is historical context rather than a recipe for every current provider. Selenium: A Tour of 4, Authentication.

Cookie injection is not a universal login shortcut. An application may require multiple cookies, server-side state, a CSRF token, a particular cookie path or security attribute, or a different authentication mechanism. Use only an application’s authorized test interface, and treat session credentials as secrets: do not commit or log them.

This example assumes the application’s authorized test setup provides a valid session cookie. Replace the domain, cookie name and value, protected route, readiness selector, and output path with values for your test environment. The cookie value below comes from an environment variable so it does not need to appear in source control.

import os
from pathlib import Path

from selenium import webdriver
from selenium.webdriver.common.by import By
from selenium.webdriver.support.ui import WebDriverWait

base_url = "https://example.test"
protected_url = f"{base_url}/account"
cookie_value = os.environ["TEST_SESSION_COOKIE"]
output_path = Path("artifacts/account.png")
output_path.parent.mkdir(parents=True, exist_ok=True)

driver = webdriver.Chrome()
try:
    # WebDriver can add a cookie only while on a page in its valid domain.
    driver.get(base_url)
    driver.add_cookie({"name": "session", "value": cookie_value})

    driver.get(protected_url)

    # Wait for an application-specific signal that protected content is ready.
    WebDriverWait(driver, 15).until(
        lambda d: d.find_element(By.CSS_SELECTOR, "[data-testid='account-page']")
    )

    saved = driver.get_screenshot_as_file(str(output_path.resolve()))
    if not saved:
        raise OSError(f"Could not save screenshot to {output_path.resolve()}")
finally:
    driver.quit()

Install Selenium and provide the browser driver in the environment as appropriate for your setup. For example, install the Python package with python -m pip install selenium, set TEST_SESSION_COOKIE through your test runner’s secret mechanism, and run the script. Selenium’s cookie API requires first navigating to a page on the cookie’s valid domain; the cookie is associated with the current browsing context. See Selenium: Working with cookies.

What to adapt

  • session: use the cookie name expected by the application. A session cookie may not be sufficient by itself.
  • base_url: use the exact scheme and hostname to which the cookie applies. If needed, match its domain, path, and security attributes to the application’s requirements.
  • account-page: choose a selector that appears only after the expected authenticated page is ready. A login form or generic page shell is not a useful readiness signal.
  • output_path: choose a writable location. The Python method writes PNG and expects a full path with a .png filename.

3. If the login itself is under test

Use the form flow when the test needs to verify login behavior. The exact selectors, credentials, and post-login signal depend on the application:

import os
from pathlib import Path

from selenium import webdriver
from selenium.webdriver.common.by import By
from selenium.webdriver.support.ui import WebDriverWait

output_path = Path("artifacts/account.png")
output_path.parent.mkdir(parents=True, exist_ok=True)

driver = webdriver.Chrome()
try:
    driver.get("https://example.test/login")
    driver.find_element(By.NAME, "username").send_keys(os.environ["TEST_USERNAME"])
    driver.find_element(By.NAME, "password").send_keys(os.environ["TEST_PASSWORD"])
    driver.find_element(By.CSS_SELECTOR, "button[type='submit']").click()

    WebDriverWait(driver, 15).until(
        lambda d: d.find_element(By.CSS_SELECTOR, "[data-testid='account-page']")
    )

    if not driver.get_screenshot_as_file(str(output_path.resolve())):
        raise OSError(f"Could not save screenshot to {output_path.resolve()}")
finally:
    driver.quit()

Use test credentials with only the access needed for the test. Keep them in environment variables or a secret store. If the login flow has a redirect, multi-factor step, or extra verification, handle it through an authorized test configuration rather than assuming that submitting a username and password always creates a session.

4. Wait for the right content before capturing

A successful navigation does not necessarily mean the protected content is ready. Wait for an application-specific condition: a page landmark, a data-loaded indicator, or a state change that means the content you intend to capture is visible. Selenium’s explicit waits poll for a condition; see the official waits documentation.

# Wait for a specific element
WebDriverWait(driver, 15).until(
    lambda d: d.find_element(By.CSS_SELECTOR, "[data-testid='account-page']")
)

# Or wait for a loading indicator to disappear
WebDriverWait(driver, 15).until(
    lambda d: not d.find_elements(By.CSS_SELECTOR, ".loading-indicator")
)

Prefer a condition tied to the page’s state over a fixed sleep. If the page performs asynchronous requests after rendering its shell, a generic document load may happen before the data arrives. A stable selector or application test hook makes the capture more repeatable.

5. Current-window and full-page screenshots

Python’s driver.get_screenshot_as_file(path) saves the current browser window to a PNG. It returns True on success and False for an I/O error. Check the return value and use a full output path. See the Python WebDriver API.

For a full-document capture, support depends on the browser and driver. Selenium’s Firefox WebDriver API documents get_full_page_screenshot_as_png() for the full document. Do not assume that this Firefox-specific API is portable to every browser/driver combination; check the API for the driver you run. See the Firefox WebDriver API.

6. Or skip the browser setup

If you already have a publicly accessible page URL, ScreenshotNeo can return a screenshot with one GET request. It is a website screenshot API and MCP server from ScreenshotNeo. This direct URL capture does not reuse your Selenium session or authenticate to a private account page; use your authorized browser workflow for pages that require your login session. 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,
)
r.raise_for_status()
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", new Uint8Array(await res.arrayBuffer()));

With ScreenshotNeo, cookie banners, newsletter 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; and 1,000 screenshots a month are free with no card, with paid plans starting at $5 for 3,000. Sign up for 1,000 free screenshots a month, with no card required.

7. Troubleshooting

Symptom Likely cause Fix
The screenshot shows the login page. Authentication was rejected, the cookie was added for the wrong domain, or the protected navigation redirected. Confirm the authorized test credential is valid; navigate to the cookie’s domain before adding it; inspect the final URL and wait for a protected-page selector.
add_cookie fails or the cookie has no effect. The browser is not on a URL matching the cookie’s domain, or cookie fields do not match the application’s requirements. Navigate to the correct host first. Verify the cookie name, value, path, domain, and security requirements with the application’s test setup. Selenium documents the domain-context requirement, not that any cookie will authenticate every app.
The wait times out. The selector is wrong, the page is still loading, authentication failed, or the element appears only in a different state. Check the final URL and page state, choose a selector that identifies the expected authenticated content, and set a timeout appropriate for the test environment.
The image is cut off. The standard screenshot captures the current window, not necessarily the whole document. Use the driver’s supported full-document screenshot API where available, or capture the required viewport. Check browser-specific API support.
No file appears or the method returns False. The output directory may not exist or be writable, or the filename may not be a full path with a PNG extension. Create the directory, use an absolute .png path, and check the method’s boolean return value.
The screenshot is blank or missing data. The capture ran before the protected content finished rendering, or the page’s data request failed. Wait for an app-specific ready condition and investigate the application’s loading state before capturing.

8. Reliability, performance, and cost considerations

  • Repeatability: When login is setup rather than the subject of the test, a supported API or fixture can avoid repeating brittle UI interactions. Keep the state setup explicit and scoped to the test.
  • Authentication reliability: Cookie injection depends on the application’s session model and browser context. A successful call to add_cookie does not prove the server accepted the session; verify the protected page itself.
  • Capture timing: Explicit waits for meaningful page state reduce races. A longer fixed delay can waste time and still fail when load times vary.
  • Screenshot scope: Current-window capture is straightforward and documented in the common Python WebDriver API. Full-document capture is driver-specific in the references above, so account for browser differences when comparing output.
  • File handling: Create the output directory, use deterministic filenames when appropriate, and avoid storing screenshots containing private data in public build artifacts.
  • Service cost: Selenium itself runs in your test environment; browser infrastructure and compute costs depend on where and how you run it. ScreenshotNeo’s stated plans are Free for 1,000 shots/month, Starter $5 for 3,000, Growth $15 for 15,000, Pro $39 for 60,000, Scale $99 for 250,000, and Business $249 for 1,000,000. Yearly billing gives two months free, and every feature is on every plan. For ScreenshotNeo specifically, only clean shots are billed; bot checks, blank pages, timeouts, failed loads, and cache hits cost nothing, and responses report the page verdict and billing status.

FAQ

Can I keep Selenium logged in between runs?

Use an application-supported test state setup, or manage a browser profile/session only where that fits your test and security requirements. For isolated repeatable tests, Selenium’s guidance favors establishing application state through a suitable test mechanism rather than performing UI login setup before every test.

No. It works only if the application accepts that cookie in the current domain context and the session requirements are satisfied. Some applications need additional state or a different authentication flow.

Does get_screenshot_as_file save a full-page image?

It saves the current window. Full-document capture is a separate capability and must be checked for the specific browser and driver.

Can ScreenshotNeo take a screenshot of my private logged-in page?

The one-call example captures the URL you provide; it does not inherit a Selenium browser session. For a page protected by your login, use the authenticated browser workflow above.