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 →iTechGuides is reader-supported. When you buy through links on our site, we may earn an affiliate commission. As an Amazon Associate I earn from qualifying purchases. Learn more
The efficient approach is to log in once, save the browser’s authentication state to a file, and load that file into every test. Each test still gets its own fresh browser context, so cookies and local storage do not leak between tests. The one decision that changes the setup is whether your tests modify server-side data. If they can run side by side against the same account without interfering, share one account through a setup project. If they change shared records, give each parallel worker its own account and authenticate per worker.
Choose the pattern before you write code
Playwright’s authentication documentation describes three ways to supply a logged-in state. Pick one based on what your tests do to the application, not on how convenient the login helper is to write.
| Pattern | Choose it when | Efficiency and isolation notes |
|---|---|---|
| One shared account with a setup project | Tests can run concurrently without conflicting server-side changes, and the login is not specific to one browser. | Log in once before the dependent projects start, then apply the saved state to each test’s new context. |
| One account per worker with a worker-scoped fixture | Tests create, edit, or delete shared server-side data, or otherwise interfere when they use the same account. | Each worker logs in once and reuses its own state file. Accounts must be distinct across workers. |
| Authentication through the application’s API | The application exposes a login API that is simpler or faster than driving the sign-in form. | The login request is made with an API request context, and that context’s storage state is saved for reuse. |
Option 1: a shared account with a setup project
This is the default pattern for most suites. It removes the login step from every test while keeping tests independent at the browser level.
- Write an authentication setup test. Place it in a file such as
tests/auth.setup.ts. It signs in and then waits for a signal that proves the login finished. Waiting for a final URL or a signed-in element is the reliable choice, because it confirms the cookies were set after any redirects.import { test as setup } from '@playwright/test'; const authFile = 'playwright/.auth/user.json'; setup('authenticate', async ({ page }) => { await page.goto('/login'); await page.getByLabel('Email').fill(process.env.TEST_USER!); await page.getByLabel('Password').fill(process.env.TEST_PASSWORD!); await page.getByRole('button', { name: 'Sign in' }).click(); await page.waitForURL('**/dashboard'); await page.context().storageState({ path: authFile }); }); - Register a
setupproject inplaywright.config.tsthat matches the setup file.import { defineConfig, devices } from '@playwright/test'; export default defineConfig({ projects: [ { name: 'setup', testMatch: /.*.setup.ts/ }, { name: 'chromium', use: { ...devices['Desktop Chrome'], storageState: 'playwright/.auth/user.json', }, dependencies: ['setup'], }, ], }); - Run the suite. Playwright runs the setup project first, then the dependent project. Each test starts with the saved cookies and local storage, in its own browser context.
- Keep the state file out of version control. If the state only needs to last for one run, store it under the project’s output directory, which Playwright clears before each run.
Option 2: one account per worker
Use this pattern when tests change shared server-side state. Sharing a browser context does not isolate application data, so two workers writing to the same account can still break each other’s assertions even though their browser sessions are separate.
#1 Best Overall
- Provision one account per worker. Your test environment must be able to create or allocate as many accounts as you run workers, including when several CI pipelines run at once. Use names unique enough that concurrent runs do not collide.
- Define a worker-scoped fixture. The fixture derives the account from
test.info().parallelIndex, which Playwright documents as the index that distinguishes parallel workers. It authenticates from a clean context that inherits no state, saves the result to a file named for that worker, and passes the path to the tests in that worker. - Reuse the file across the worker’s tests. The login runs once per worker rather than once per test. Fixture reuse can extend across multiple test files, provided the worker fixtures match and the environments are identical.
Playwright’s documentation states that using unique accounts is important when tests interfere with each other, and the same caution applies to concurrent CI runs sharing one pool of accounts.
Option 3: authenticate through the API
If your application has a login endpoint, you can skip the sign-in form entirely. Playwright’s guide shows creating an APIRequestContext, posting the credentials, and saving that context’s storage state to a file. The same approach can sit inside a worker-scoped fixture. The endpoint and payload in the documentation are illustrative, so adapt the request to your application’s real mechanism, including any CSRF token, MFA step, or cookie domain.
Rank #2
The API route is faster only if the endpoint is simpler than the UI flow. Measure both before standardising on it, because a login that bypasses the form can miss cookies the browser would normally receive.
Do these 3 things before closing this tab:
1Scan for outdated or missing drivers - takes under a minute2Repair Windows errors before they cause bigger problems3Fix the driver behind crashes, sound loss and screen glitchesHandling multiple roles
There are two common cases, and they call for different setups.
- One role per file or group of tests. Create a state file for each role during setup, then select it with
test.use({ storageState: 'playwright/.auth/admin.json' })at the top of a file or inside adescribeblock. - Several roles inside one test. When a single scenario needs two signed-in users at once, such as a buyer and a seller, create a separate
BrowserContextandPagefor each role, initialise each context with that role’s state file, and close both contexts at the end of the test.
What saved state includes, and what it misses
The saved state covers cookies, local storage, IndexedDB, and virtual WebAuthn credentials when you have configured them. It does not include sessionStorage. Many single-page applications keep their token there, so a state file alone can produce a user who appears logged out.
For those applications, the authentication guide describes a separate pattern. After login, read the relevant sessionStorage values and write them to a file. In each new context, register an initialisation script with context.addInitScript that restores those values before the page loads. Treat that file with the same care as the cookie state.
Rank #4
Isolation, retries, and the performance trade-off
Playwright creates a new browser context for every test. Reusing the saved authentication state keeps that isolation and removes only the repeated login. Playwright describes contexts as fast and cheap to create, so the state file is the part you should share, not a context or page.
Playwright’s documentation notes that a page can be reused across tests with beforeAll and afterAll. It recommends against this for most suites, because independently retried tests cannot depend on a page left in a prior state. Reserve page reuse for a specific case where the setup cost is high and the tests are written to tolerate shared state.
On speed, Playwright’s guidance is qualitative. It says loading saved state removes the login from each test and speeds up execution, but it does not publish a measured reduction. The saving depends on how long your login takes, how many tests you run, how many workers you use, and how your accounts are provisioned. Measure your own suite with and without the setup before you report a figure.
Independent reader supportYour contribution helps us test, update, and keep practical guides available for everyone.Security and operational cautions
- Treat state files as credentials. Playwright warns that saved state can contain cookies and headers that let someone impersonate the account. Never commit these files.
- Do not rely on separate contexts to isolate data. Contexts isolate browser storage only. If tests write to the same server-side records, use separate accounts.
- Expect state to expire. Session lifetimes end, and a stale file will make tests fail with redirects to the login page.
- Check the UI mode setting. According to the authentication guide, the setup project does not run by default in UI mode. Run the setup manually when the saved state has expired.
- Revisit the shared-account choice for browser-specific logins. If authentication depends on one browser’s behaviour, the shared-account pattern may not apply to every browser project.
Troubleshooting a failing shared state
- Tests start on the login page. The state file is missing, empty, or stale. Delete it, run the setup project alone, and confirm the file contains cookies for your application’s domain.
- Login works in setup but the app still shows signed out. Check whether the session lives in
sessionStorage. If it does, add the initialisation-script step described above. - Tests pass alone and fail in parallel. Two workers are probably sharing an account that mutates server-side data. Move to one account per worker.
- Setup runs on every test run. Confirm the consumer projects list
dependencies: ['setup']. Without that declaration, the setup project may not run before the tests that need it.
Playwright’s authentication guidance is the primary reference for these patterns. The pattern names, file paths, and fixture details above follow that documentation, and the sample endpoints and credentials it uses should be replaced with your own.
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.

