skip to content

Cookie and Storage Scope

A context is an incognito-like profile with its own cookies, storage, permissions and cache, cheap to create next to a browser. Asked because it is why every test can start from nothing.

on this pageshow

explore

questions

6

In Playwright, what state does a fresh browser.newContext() isolate from every other context?

level: juniorimportance: must knowfreq 80%

answer

  1. Think profile, not window
  2. Incognito-like and cheap to create
  3. Cookies, storage, cache, permissions
  4. One browser process, many profiles
  5. Server state is not included

basics

~20 s

A new browser context is an incognito-like profile: its own cookies, localStorage, sessionStorage, IndexedDB, cache, service workers and permission grants. Contexts share only the running browser, so one test cannot leak client state into another.

solid answer

~40 s

`browser.newContext()` creates an incognito-like profile inside a browser that is already running, and the Playwright docs are explicit that it will not share cookies or cache with any other context. Everything a browser normally keeps per profile is fresh: the cookie jar, `localStorage` and `sessionStorage` for every origin, IndexedDB, the HTTP cache, service workers, and permissions granted with `context.grantPermissions()`. Two contexts in the same browser therefore never see each other's session, which is why Playwright Test creates a context per test and gives you a `page` inside it. Creation costs milliseconds because no process starts. What a context does not isolate is anything outside the browser profile: server-side data, files on disk, and settings fixed when the browser was launched.

code

typescript · 12 lines
typescript
import { chromium } from '@playwright/test';

const browser = await chromium.launch();
const guest = await browser.newContext();
const staff = await browser.newContext();

await guest.addCookies([{ name: 'currency', value: 'EUR', url: 'https://hotels.example/' }]);
console.log(await staff.cookies('https://hotels.example/')); // []

await guest.close();
await staff.close();
await browser.close();

go deeper

for a junior

Remember the one-line definition: a context is an incognito-like profile with its own cookies, storage, cache and permissions, and Playwright gives each test one for free.

for a middle

Be able to list what is isolated and what is not, and explain why creating a context is milliseconds while launching a browser is not.

for a senior

Show that you know isolation stops at the browser: talk about the server-side data and shared accounts that still leak between tests, and how you keep those clean.

for a principal

Own the tradeoff between starting from scratch and cleaning up between tests, and how the isolation model shapes parallelism, shared environments and test data ownership across teams.

## What a browser context is A **browser context** is an isolated, incognito-like profile living inside a browser process that is already running. `browser.newContext()` hands you one; the API documentation states plainly that a new context "won't share cookies/cache with other browser contexts". The mental model that matters is that a browser owns *processes*, a context owns a *profile*, and a page owns a *tab*. Almost everything a test can accidentally leak lives on the profile. ## What a fresh context isolates - **Cookies** — every context has its own jar, so a session established in one is invisible in another. - **Web Storage** — `localStorage` and `sessionStorage` start empty for every origin. - **IndexedDB** and other origin-scoped client databases. - **The HTTP cache** and any service worker the site registered. - **Permission grants** — what `context.grantPermissions()` allows applies to that context alone, and `context.clearPermissions()` drops the overrides back to the browser default. - **Context-level network settings** — `extraHTTPHeaders`, `httpCredentials`, `ignoreHTTPSErrors` and `bypassCSP` are chosen per context when it is created. ## What it does not isolate Isolation stops at the browser. A context cannot undo work an earlier test did on the server, so a reservation the first test created against the hotel-booking backend is still in the database when the next context opens; test data hygiene remains your problem. Nor does a context change the machine: files on disk, environment variables and anything fixed when the browser itself was launched are shared by every context in that browser. And two contexts in one browser still share the engine build, so a browser-level crash takes them all down together. ## Why a context per test is the default Creating one takes milliseconds: no process is spawned, no engine boots, no profile directory is written. That price is exactly why Playwright Test opens a context for each test and hands the test a `page` inside it instead of cleaning up between tests. Cleanup is the fragile strategy — it is easy to forget an origin, and some state cannot be cleaned at all — while starting from nothing means a failing test can only have been broken by itself. | Layer | Owns | Shared with siblings | Rough cost to create | |---|---|---|---| | Browser | the OS process and the engine | everything below it | hundreds of milliseconds or more | | Context | cookies, storage, cache, permissions | nothing client-side | milliseconds | | Page | one tab's DOM and JavaScript environment | the context's whole profile | milliseconds | ## Putting state back on purpose Because the profile starts empty, whatever a test needs has to be re-created deliberately: 1. `context.addCookies()` writes cookies into the jar, before the navigation that should send them. 2. `context.addInitScript()` runs before the page's own scripts, which is where a seeded `localStorage` value or a stubbed browser API belongs. 3. `context.grantPermissions()` pre-answers permission-gated features so nothing waits on a decision a test cannot click. ## Where the model bites Two habits follow from it. First, do not reach for cookie clearing between tests — a new context is cheaper and more complete than any reset you can write. Second, remember that pages inside one context *do* share the profile: a second tab opened from a booking confirmation is signed in exactly like the first, which is a feature when you are testing a popup flow and a trap when you assumed a page was as isolated as a context. If two flows must not see each other's session, they need two contexts.

  • If contexts are isolated, why can two pages in the same context still see each other's session?
    Isolation is drawn at the profile, not the tab. Every page in a context reads the same cookie jar and the same `localStorage`, which is what makes popup and multi-tab flows testable. Two identities in one test therefore need two contexts, not two pages.
  • What does a context not clean up that can still make the next test fail?
    Everything outside the browser: rows the previous test wrote to the booking database, files it uploaded, queued emails, rate-limit counters keyed to an account. A fresh context guarantees a clean client, never a clean server, so shared server state needs its own strategy.

A context is a fresh incognito window that opens instantly: same browser, brand-new profile.

saying these in an interview costs you the question

  • Thinks a new context launches a whole new browser process
  • Believes contexts in one browser share a cookie jar
  • Expects a fresh context to reset server-side data too
  • Opens a second page when a second identity is needed
  • Clears cookies by hand between tests instead of using a context
open as a page

In Playwright, why does context.addCookies() reject a cookie that has only a name and a value?

level: middleimportance: must knowfreq 58%

basics

~10 s

Because Playwright cannot place a cookie without knowing where it belongs. Every entry needs a url, or both domain and path, and passing neither throws: Cookie should have a url or a domain/path pair.

open as a page

In Playwright, how do you let a test use a permission-gated feature such as clipboard read?

level: middleimportance: should knowfreq 40%

basics

~10 s

Grant it on the context before the feature is used: context.grantPermissions(['clipboard-read']), or the permissions option on browser.newContext. Add an origin option to limit the grant, and clearPermissions to drop every override again.

open as a page

Why does a Playwright test that writes localStorage after page.goto() fail to change how the app boots?

level: middleimportance: should knowfreq 46%

basics

~10 s

Because the app has already started and read storage by the time the navigation resolves. Seeded values must exist before the document's own scripts run, which is what context.addInitScript() and page.addInitScript() are for.

open as a page

Your Playwright suite tests a staging site behind HTTP Basic auth that also calls a partner API — how do you authenticate without leaking credentials?

level: seniorimportance: should knowfreq 36%

basics

~20 s

Put httpCredentials on the context and pin it with the origin field, so Basic auth is answered only for the staging host. Without an origin, the same username and password answer any 401, including the partner's.

open as a page

How would you decide whether a Playwright suite may run every context with ignoreHTTPSErrors and bypassCSP enabled?

level: principalimportance: should knowfreq 28%

basics

~20 s

Playwright's ignoreHTTPSErrors and bypassCSP are deliberate deviations from a real browser. Default both off, enable them only for the tests or environments that need it, and keep one path running with the real certificate and policy.

open as a page