Skip to main content

Authentication

Playwright can be used to automate scenarios that require authentication.

Tests written with Playwright execute in isolated clean-slate environments called browser contexts. This isolation model improves reproducibility and prevents cascading test failures. New browser contexts can load existing authentication state. This eliminates the need to login in every context and speeds up test execution.

Note: This guide covers cookie/token-based authentication (logging in via the app UI). For HTTP authentication use browser.new_context(**kwargs).

Automate logging in

The Playwright API can automate interaction from a login form.

The following example automates logging into GitHub. Once these steps are executed, the browser context will be authenticated.

page = context.new_page()
page.goto('https://github.com/login')

# Interact with login form
page.get_by_text("Login").click()
page.get_by_label("User Name").fill(USERNAME)
page.get_by_label("Password").fill(PASSWORD)
page.get_by_text('Submit').click()
# Continue with the test

Redoing login for every test can slow down test execution. To mitigate that, reuse existing authentication state instead.

Reuse signed in state

Playwright provides a way to reuse the signed-in state in the tests. That way you can log in only once and then skip the log in step for all of the tests.

Web apps use cookie-based or token-based authentication, where authenticated state is stored as cookies or in local storage. Playwright provides browserContext.storageState([options]) method that can be used to retrieve storage state from authenticated contexts and then create new contexts with prepopulated state.

Cookies and local storage state can be used across different browsers. They depend on your application's authentication model: some apps might require both cookies and local storage.

The following code snippet retrieves state from an authenticated context and creates a new context with that state.

# Save storage state into the file.
storage = context.storage_state(path="state.json")

# Create a new context with the saved storage state.
context = browser.new_context(storage_state="state.json")

Session storage

Rarely, session storage is used for storing information associated with the logged-in state. Session storage is specific to a particular domain and is not persisted across page loads. Playwright does not provide API to persist session storage, but the following snippet can be used to save/load session storage.

import os
# Get session storage and store as env variable
session_storage = page.evaluate("() => JSON.stringify(sessionStorage)")
os.environ["SESSION_STORAGE"] = session_storage

# Set session storage in a new context
session_storage = os.environ["SESSION_STORAGE"]
context.add_init_script("""(storage => {
if (window.location.hostname === 'example.com') {
const entries = JSON.parse(storage)
for (const [key, value] of Object.entries(entries)) {
window.sessionStorage.setItem(key, key)
}
}
})('""" + session_storage + "')")

Multi-factor authentication

Accounts with multi-factor authentication (MFA) cannot be fully automated, and need manual intervention. Persistent authentication can be used to partially automate MFA scenarios.

Persistent authentication

Note that persistent authentication is not suited for CI environments since it relies on a disk location. User data directories are specific to browser types and cannot be shared across browser types.

User data directories can be used with the browser_type.launch_persistent_context(user_data_dir, **kwargs) API.

from playwright.sync_api import sync_playwright

with sync_playwright() as p:
user_data_dir = '/path/to/directory'
browser = p.chromium.launch_persistent_context(user_data_dir, headless=False)
# Execute login steps manually in the browser window

Lifecycle

  1. Create a user data directory on disk.
  2. Launch a persistent context with the user data directory and login the MFA account.
  3. Reuse user data directory to run automation scenarios.