Playwright Authentication
This chapter introduces how to handle authentication in Playwright, avoiding repeated logins for each test while maintaining test isolation.
The Core Problem of Authentication
Most web application tests require user login.
If every test performs the login flow from scratch, it will significantly slow down test execution.
Playwright's solution is:Authenticate once, save the state, and have all tests reuse it.。
Preparation: .auth Directory
Example
mkdir -p playwright/.auth
# Add to .gitignore (authentication state contains sensitive information)
echo 'playwright/.auth' >> .gitignore
.authThe file contains sensitive cookies and authentication tokens,and must never be committed to the code repository.。
Basic Approach: Shared Account + Setup Project
This is Playwright's recommended authentication approach, suitable for scenarios where all tests share the same test account.
Step 1: Create Authentication Setup
Example
import { test as setup } from '@playwright/test';
// Specify the authentication state save path
const authFile = 'playwright/.auth/user.json';
setup('authenticate', async ({ page }) => {
// Perform login operation
await page.goto('https://www.example.com/login');
await page.getByLabel('username').fill('testuser');
await page.getByLabel('password').fill('password123');
await page.getByRole('button', { name: 'Login' }).click();
// Wait for login to complete (confirm page navigation or user info appears)
await page.waitForURL(/dashboard/);
// Save the current authentication state (cookies, localStorage) to a file
await page.context().storageState({ path: authFile });
});
Step 2: Configure Setup Project
Example
import { defineConfig } from '@playwright/test';
export default defineConfig({
projects: [
// Setup project — runs only once, generates the authentication state file
{
name: 'setup',
testMatch: /auth\.setup\.ts/,
},
// Actual test project — reuses the authentication state
{
name: 'chromium',
use: {
storageState: 'playwright/.auth/user.json',
},
dependencies: ['setup'], // Depends on the setup project, ensuring setup runs first
},
],
});
Step 3: Tests Directly Use Authentication State
Example
import { test, expect } from '@playwright/test';
test('View dashboard', async ({ page }) => {
// Directly access a page that requires login; the page already carries the authentication state
await page.goto('/dashboard');
await expect(page.getByText('Welcome back, testuser')).toBeVisible();
});
Multiple Account Scenario
If different tests need to use different accounts, you can create multiple authentication state files.
Example
test.describe('Admin features', () => {
test.use({ storageState: 'playwright/.auth/admin.json' });
test('Manage users', async ({ page }) => {
// Perform actions as an administrator
});
});
// Regular user test
test.describe('Regular user features', () => {
test.use({ storageState: 'playwright/.auth/user.json' });
test('Browse content', async ({ page }) => {
// Perform actions as a regular user
});
});
Authentication via API Request (Recommended)
Performing the login flow through the UI is slow; a more efficient way is to call the login API directly.
Example
import { test as setup } from '@playwright/test';
const authFile = 'playwright/.auth/user.json';
setup('Authenticate via API', async ({ request }) => {
// Call the login API directly, not through the browser UI
const response = await request.post('https://www.example.com/api/login', {
data: {
username: 'testuser',
password: 'password123',
},
});
// Confirm login success
const json = await response.json();
console.log('Login successful, Token:', json.token);
// Save the token as a cookie (simulating browser authentication state)
// Note: storageState needs to be saved in the browser context
});
API authentication is faster and more reliable than UI authentication, and is recommended for priority use in real projects.
Summary of Applicable Scenarios for Authentication Approaches
| Scenario | Recommended Approach |
|---|---|
| All tests use the same test account | Setup project + storageState |
| Different types of tests need different accounts | Multiple storageState + test.use |
| Each test needs an independent account | Create account and log in via API within each test |
| Limited account resources | Authenticate once in the Setup project, reuse for all |