Playwright's codegen opens a clean browser every run — how do you record a flow behind sign-in?
answer
- Every run starts from empty
- Two runs, not one
- Saved when the browser closes
- Cookies and localStorage only
- The file is a credential
basics
~20 sRecord once with --save-storage to write the session's cookies and localStorage to a file, then relaunch codegen with --load-storage pointing at that file, so recording starts already signed in and captures only the steps you care about.
solid answer
~40 sEach codegen run gets a fresh browser context, so a protected page bounces you to the login screen and the sign-in steps end up polluting every recording. The two-run workflow fixes it: `npx playwright codegen --save-storage=auth.json https://tracker.example.com`, sign in by hand, then close the browser — the storage state is written at the end of the session. Now `npx playwright codegen --load-storage=auth.json https://tracker.example.com/orders/42` starts authenticated and the emitted script contains only the order-tracking steps. The file holds cookies and localStorage for the origins you visited; `sessionStorage` is not part of it, so an app that keeps its token there will still be logged out. Treat `auth.json` as live credentials: keep it out of version control.
code
bash · 5 lines# 1. sign in by hand, then close the browser to write the file
npx playwright codegen --save-storage=auth.json https://tracker.example.com
# 2. record the real flow, already authenticated
npx playwright codegen --load-storage=auth.json https://tracker.example.com/orders/42go deeper
Remember the pair of flags: --save-storage writes the session to a file, --load-storage seeds a later recording from it, so you sign in by hand only once.
Explain that the file is written when the session ends and holds cookies plus localStorage per origin, which is why a token kept in sessionStorage leaves the next recording logged out.
Show the working habit: separate sign-in and feature recordings, a dedicated test account, the file gitignored and deleted afterwards, and a plan for refreshing it when the credential expires.
Own the boundary — a convenience file on one engineer's laptop is not a suite's authentication design, and the two should never converge into a shared committed artefact.
Codegen always starts a fresh browser context. Nothing is inherited from your everyday browser and nothing survives between runs — so anything behind a login is out of reach until you seed the session. ## Why the recorder starts logged out The recording session is a brand-new context: empty cookie jar, empty storage, no profile. That is the right default (recordings are reproducible, and your personal browser is not driven by a tool), but it means the first thing you record against the order tracker is a redirect to the sign-in page. ## The two-run workflow 1. **Capture a session.** `npx playwright codegen --save-storage=auth.json https://tracker.example.com`. Sign in by hand in the recorded browser, get to a signed-in page, then **close the browser**: `--save-storage` writes the context's storage state at the end of the session, not continuously. Throw away the script from this run — it is only the sign-in you were never going to keep. 2. **Record the real flow.** `npx playwright codegen --load-storage=auth.json https://tracker.example.com/orders/42`. The recorder seeds the new context from the file, so the first page you see is the authenticated order tracker and the generated script starts with the step you actually care about. 3. **Refresh when it goes stale.** The file is a snapshot of a session; when the cookie or token in it expires, repeat step 1. ## What the file holds | in the storage state file | not in it | | --- | --- | | cookies for the origins visited during the session | `sessionStorage`, which is per-tab and not part of storage state | | `localStorage` entries per origin | anything the server holds against a session id that has since expired | This is the usual explanation for "I passed `--load-storage` and it still shows the login page": an application that keeps its access token in `sessionStorage` gets nothing back from the file. The other common causes are an expired credential inside the file, and loading state captured on one origin while recording against another. ## Handling the file - It contains live session material. Keep it out of the repository, out of screenshots and out of shared scratch directories; add it to `.gitignore` before the first run, not after. - Use a purpose-made test account, never a personal one. - Delete it when the recording session is over — its whole job is to save you retyping a password. ## What this does and does not set up `--save-storage` and `--load-storage` configure **the recorder**, not the test you are about to write. The generated script contains no reference to `auth.json`; it is a plain list of actions that assumes it is already signed in. How the suite itself obtains a session — as a fixture, a setup project, or per-role state — is a separate design decision made in your test project, and the recorded draft will simply fail with a redirect to the login page until you wire that in. ## The habit to build Keep the sign-in recording and the feature recording as two separate runs, permanently. A draft that starts with fifteen lines of typing a password into a login form is a draft nobody keeps, and deleting those lines by hand every time is the step people quietly skip.
- You pass `--load-storage` and still land on the login page — what do you check first?Whether the application keeps its token in `sessionStorage`, which storage state does not capture; then whether the credential in the file has expired; then whether the origin you are recording against matches the origin the state was captured on, since cookies and localStorage are stored per origin.
- Does the generated script use the storage-state file you recorded with?No. `--load-storage` seeds the recorder's own context; the emitted code is just the actions and assumes it is already signed in. Running it as-is in a suite redirects to the login page until the project provides a session of its own, which is a separate piece of test-project design.
It is a save file: one run to reach the checkpoint and write it out, every later run loaded from the checkpoint so you never replay the opening level.
saying these in an interview costs you the question
- Thinks the state file is written continuously while recording
- Believes storage state captures sessionStorage too
- Assumes the generated script loads the saved state itself
- Commits the storage-state file to the repository
- Thinks codegen can only record public pages