Recommended Free Tools
To screenshot a page that requires login, add its valid session cookie to a Playwright browser context before navigating, open the target URL in that context, verify the page is authenticated, and then save the screenshot. The cookie must be current and scoped to the destination; some sites also require authentication state beyond cookies.
Capture a page with a session cookie
Install Playwright and its Chromium browser if you have not already, then provide the session cookie through an environment variable rather than embedding it in source code. The cookie name, value and scope below are examples: use the actual values issued by the site for an account you are authorized to access.
pip install playwright
playwright install chromium
Save this as screenshot.py and run it with SESSION_COOKIE='your-cookie-value' python screenshot.py:
import os
from playwright.sync_api import sync_playwright
url = "https://example.com/account"
session_cookie = os.environ["SESSION_COOKIE"]
with sync_playwright() as p:
browser = p.chromium.launch(headless=True)
context = browser.new_context(viewport={"width": 1440, "height": 1000})
context.add_cookies([{
"name": "sessionid",
"value": session_cookie,
"url": "https://example.com",
"httpOnly": True,
"secure": True,
}])
page = context.new_page()
page.goto(url, wait_until="networkidle")
# Check an application-specific sign of successful login before capturing.
page.get_by_role("link", name="Sign out").wait_for()
page.screenshot(path="authenticated-page.png", full_page=True)
context.close()
browser.close()
The sign-out locator is illustrative; replace it with a reliable element or URL condition for the application. A screenshot can be saved successfully even when the site redirected to a login or access-denied page, so the verification step matters.
#1 Best Overall
Set cookie scope and attributes correctly
Playwright installs cookies on a BrowserContext. Pages created in that context share its browser session. Add cookies before opening or navigating to the target page. A cookie can specify either url, as above, or both domain and path. For example:
context.add_cookies([{
"name": "sessionid",
"value": session_cookie,
"domain": ".example.com",
"path": "/",
"httpOnly": True,
"secure": True,
}])
- Use the exact cookie name and value from an authorized login session. A stale, revoked or malformed value will not authenticate.
- Match the cookie URL or domain and path to the destination. A scope mismatch can prevent the browser from sending it where expected. A leading dot in a domain applies the cookie to subdomains.
secureandhttpOnlyare cookie attributes; setting them does not repair an expired credential or incorrect scope.- Only use HTTPS for a secure cookie. Do not assume a cookie for one host is valid on another.
See the Playwright BrowserContext reference for the current cookie API, including its asynchronous Python interface.
Rank #2
Wait for the page you actually need
wait_until="networkidle" is a useful starting point, but it is not proof that a dynamic application is ready. A page may continue background requests after it has rendered, or appear idle before the content you need is present. Prefer an application-specific readiness check, such as waiting for a heading, account control or data element that appears only after login. Use a fixed delay only when you have a site-specific reason; it is not a reliable universal readiness test.
Set full_page=True when you need the full page beyond the viewport. Omit it for a viewport-sized image. Playwright’s screenshot guide documents capture options and current behavior.
When a cookie is not enough: reuse authenticated state
Some applications authenticate with a combination of cookies, local storage, IndexedDB or passkeys. If you can log in through Playwright, save the supported browser state and load it into a fresh context for later captures:
from playwright.sync_api import sync_playwright
with sync_playwright() as p:
browser = p.chromium.launch(headless=True)
# First run: complete the site's authorized login flow, then save state.
context = browser.new_context()
page = context.new_page()
page.goto("https://example.com/login")
# Complete login using the site's normal flow and verify it succeeded.
context.storage_state(path="state.json")
context.close()
# Later run: initialize a context with the saved state.
context = browser.new_context(storage_state="state.json")
page = context.new_page()
page.goto("https://example.com/account", wait_until="networkidle")
page.get_by_role("link", name="Sign out").wait_for()
page.screenshot(path="authenticated-page.png", full_page=True)
context.close()
browser.close()
The first-run login is intentionally site-specific: implement the site’s normal authorized login steps rather than assuming a universal form. Playwright’s regular storage-state mechanism does not include session storage. If the application depends on session storage, follow the Playwright authentication guide for its initialization-script approach and restrict that script to the intended hostname.
Keep authentication material private
A raw session cookie is a credential. Saved authentication-state files may contain cookies and headers that can be used to impersonate the account. Do not print credentials, commit them, include them in screenshots, or expose them in logs or public examples. Store them in an appropriate secret manager or environment-backed secret, and add local state files such as state.json to .gitignore. Use only sessions and accounts you are authorized to use, and respect the site’s access rules.
Troubleshoot common failures
| Symptom | Likely cause | What to check |
|---|---|---|
| The screenshot shows the login page | The cookie is expired, invalid, not sent, or not the only state the app requires. | Confirm the cookie is current, use the exact name and value, check domain/path/URL scope, and verify whether the app also needs saved storage state. |
| The cookie appears to be ignored on a subdomain | The cookie scope does not cover the target host. | Set the correct URL or domain and path; use a leading-dot domain only when the cookie should apply to subdomains. |
| The page loads but the expected account content is missing | The capture ran before the app finished rendering, or the locator used to validate login is wrong. | Wait for a site-specific authenticated element or application-ready signal, and confirm the login condition matches the page. |
| Cookie injection works but a later run does not | The session may have expired, or the app relies on state not represented by that cookie. | Establish a fresh authorized session and consider saving Playwright storage state for repeat captures. |
| State-file reuse still returns an unauthenticated page | The app may depend on session storage or another unsupported or separately initialized mechanism. | Check the application’s authentication design; session storage needs separate initialization and is not included in regular storage state. |
Or skip the browser setup
ScreenshotNeo is a website screenshot API and MCP server. For a public page, one request returns an image or PDF; its API documentation is at screenshotneo.com/docs.
Quick wins for a faster PC:
Repair Windows errors before they cause bigger problemsFix Now →Scan for outdated or missing drivers - takes under a minuteDriver Scan →Clear out junk files and repair common Windows errorsFree Scan →Best Value
curl -G "https://api.screenshotneo.com/v1/shot" -d access_key=YOUR_API_KEY --data-urlencode url=https://example.com/account -o shot.webp
That call does not inject your private Playwright session cookie: use the Python method above when the capture requires your authenticated browser session. ScreenshotNeo can remove cookie/consent banners, newsletter popups and chat widgets before capture; bot checks, blank pages and failed loads are not billed; its MCP server lets AI agents take screenshots; and the Free plan includes 1,000 screenshots per month without a card. Paid plans start at $5 for 3,000 screenshots. Sign up for free.
Frequently Asked Questions
Can Playwright Python reuse saved login cookies?
Yes. Save supported browser authentication state with context.storage_state(path="state.json"), then create a context with browser.new_context(storage_state="state.json"). Keep the file private.
Does adding a cookie prove the screenshot is authenticated?
No. The screenshot can capture a redirect or access-denied page. Check a reliable, application-specific sign of successful login before saving it.
Quick Recap
Product prices and availability are accurate as of the date/time indicated and are subject to change. Any price and availability information displayed on Amazon at the time of purchase will apply.




