Introducing Playwright Fixtures: browser, context, and page
- Anuradha Agarwal
- Feb 23
- 3 min read
When we write our first Playwright test, we usually see this structure:
import { test, expect } from "@playwright/test";
test("Open homepage", async ({ page }) =>
{
await page.goto("https://qa-cart.com/");
}
);Here, the page object is not something we created manually. Playwright automatically provides it using a concept called fixtures.
A fixture is a ready-to-use object that Playwright provides to your test, so you don’t have to manually launch the browser, create sessions, or open pages.
Why do we use curly braces { page }?
You will notice that fixtures are passed inside curly braces:
async ({ page })This means Playwright is passing an object that contains multiple fixtures, and we are extracting the page fixture from it.
If we do not use curly braces, the value will not be treated as a Playwright fixture. It will just be treated as a normal variable, and Playwright will not inject the browser page correctly.
So curly braces tell Playwright:
“Provide the page fixture for this test.”
Understanding browser, context, and page relationships
Playwright works in this hierarchy:
Browser → Context → Page
Let’s understand each step.
Browser fixture
The browser fixture represents the browser instance itself (Chromium, Firefox, or WebKit).
This browser is launched using settings defined in the Playwright configuration file (playwright.config.ts), such as:
which browser to use
headless or headed mode
base URL
viewport
tracing and retries
So browser setup is controlled by config, and Playwright provides it automatically.
Context fixture (browser session)
When a browser opens, it already contains session information like:
cookies
local storage
cache
login session
plugins and permissions
This session container is called a BrowserContext.
Think of context as a separate browser profile.
If you want a completely fresh instance with no cookies or login information, you can create a new context:
test("fresh session example", async ({ browser }) =>
{ const context = await browser.newContext();
const page = await context.newPage();
await page.goto("https://qa-cart.com/");
}
);Notice the use of async and await. These operations are asynchronous. If you forget await, Playwright may try to use the page before it is fully created, which can cause failures.
This new context gives you:
fresh cookies
fresh session
no login state
Storing cookies and login state
One powerful use of context is storing authentication state.
When cookies are stored in a context, the next time you reuse that stored state, the login page will not appear because the browser already recognises the user as logged in.
This is commonly used in automation frameworks to avoid repeated login steps.
We will learn this in detail later when building the framework.
Page fixture (most commonly used)
From a context, we open a page:
const page = await context.newPage();The page represents a browser tab where automation actions happen.
If we are not doing anything special, like:
injecting cookies
setting proxy
creating custom sessions
Then Playwright already provides a ready-to-use page fixture.
So we can use:
test("simple test", async ({ page }) =>
{ await page.goto("https://qa-cart.com/");
}
);Playwright automatically creates the browser and context internally and gives you the page.
Summary: What is a fixture and why is it important
A fixture is a pre-created object provided by Playwright to simplify test setup.
Instead of manually writing code to:
launch browser
create context
open page
Playwright provides these using fixtures like:
browser
context
page
request
You can see the full list of built-in fixtures on the official Playwright documentation.
What’s next
For now, we will use the built-in page fixture to write our tests.
In later lessons, as part of building a real automation framework, we will create custom fixtures to handle things like login, reusable setup, and test data management efficiently.




Comments