Playwright Interview Questions (with Sample Answers)
20+ Playwright interview questions with sample answers for 2026 QA and SDET loops, plus the scaling question most candidates never think about.
Playwright now shows up in QA and SDET loops at roughly the same frequency Selenium did in 2020: table-stakes vocabulary, and the specific technical questions have become predictable. This piece is 20+ of them with sample answers, plus the one scaling question most candidates never think about. That last question is the one I use to separate people who have shipped a Playwright suite in production from people who have finished a tutorial.
If you’re preparing for a broader loop, this is one spoke of the 2026 QA & SDET interview questions guide. If your loop is Playwright-specific, everything you need is below.
Fundamentals
What is Playwright and how does it differ from Selenium?
Playwright is a browser automation library built by Microsoft (open-source, MIT license). It drives Chromium, Firefox, and WebKit through a single API. The differences from Selenium that matter in an interview:
- Architecture. Playwright talks to browsers over the Chrome DevTools Protocol (or its WebKit/Firefox equivalents), not through WebDriver’s HTTP wire protocol. Fewer network round-trips per action, meaningfully faster in practice.
- Auto-waits. Playwright waits for elements to be visible, stable, enabled, and receiving events before acting. Selenium waits for element presence only, which is why Selenium suites accumulate
time.sleep()calls and Playwright suites (mostly) don’t. - Multi-context. A single browser instance can host multiple isolated contexts (cookies, storage, cache — each context is essentially a fresh incognito window). Selenium requires a new browser instance per isolation boundary.
What a great answer includes:
- A version-year fact (Playwright first shipped 2020; Selenium 2004). Interviewers like grounded timelines.
- Recognition that Selenium’s WebDriver spec is a W3C standard and Playwright’s protocol is not. That matters for cross-vendor tooling and less for day-to-day work.
- A caveat: Playwright’s cross-browser support is real but WebKit is not Safari. If your users are hitting Safari-specific bugs, you’re still testing against a WebKit build that lags a version or two.
Explain the difference between browser, browserContext, and page.
- Browser: an instance of Chromium, Firefox, or WebKit. Expensive to create (roughly 500 ms cold start). Reuse it across tests.
- BrowserContext: an isolated session within a browser. Cheap to create (roughly 50 ms). One context per test is the recommended pattern. You get clean cookies, storage, and cache without paying the browser startup cost.
- Page: a tab within a context. A test can spawn multiple pages when the workflow requires it, for example verifying a link opens in a new tab.
What a great answer includes: naming the cost gradient and recommending the “one context per test” pattern by default, with browser reuse across tests via a fixture.
How do Playwright locators work? Why prefer getByRole over CSS?
Locators are lazy references to elements. They don’t run until a Playwright action or assertion executes against them. That’s what enables auto-wait: the locator re-queries the DOM on every retry until the condition is met.
getByRole, getByText, and getByLabel are recommended because they test what the user actually experiences. A getByRole('button', { name: 'Submit' }) test still passes after a designer changes the button’s CSS class name, and it fails if the button loses its accessible name. Failing there is often the point.
What a great answer includes: the accessibility angle (role-based locators enforce accessible markup), and the pragmatic caveat that legacy apps with poor accessibility markup will still need data-testid locators as a bridge.
What do Playwright’s auto-waits cover, and what do they NOT cover?
Auto-waits cover: element visible, element stable (not animating), element enabled, element receiving events (not covered by another element), and for input actions, element editable. Playwright will retry the action for up to the action timeout (default 30 s) while any of those are unmet.
What auto-waits do NOT cover:
- Data assertions. If you assert that a value in the DOM equals
$42.00, auto-wait does not retry the assertion. Useexpect(locator).toHaveText('$42.00'). Theexpectversion retries; a rawexpect(await locator.textContent()).toBe('...')does not. - Network idle. Auto-waits do not wait for XHR or fetch requests to complete. If your app updates a value asynchronously, you need
waitForResponseor a network-assertion pattern. - State outside the DOM. Cookies, localStorage, backend eventual consistency. Playwright doesn’t know about them.
How does Playwright handle async operations?
Everything is Promise-based. Every action returns a Promise; you await each one. The test runner handles the async orchestration for you. You don’t manage event loops or .then() chains directly. Assertions are also async when you use the retrying expect() API.
What a great answer includes: recognition that page.locator() is synchronous (it returns a Locator object without hitting the browser) but every action on that locator (click, fill, textContent) is async. Confusing that boundary is the source of most “why does my Playwright test hang” bugs.
How do you handle multiple tabs or popups?
context.waitForEvent('page') returns the new page as soon as the context opens it. Common pattern:
const pagePromise = context.waitForEvent('page');
await page.getByRole('link', { name: 'Open in new tab' }).click();
const newPage = await pagePromise;
await newPage.waitForLoadState();
What a great answer includes: setting the waitForEvent promise before the click, not after. This is the same pattern as file downloads and network responses. Getting it wrong is the single most common Playwright bug I see in code review.
Practical scenarios
How do you handle authentication state across tests?
Two patterns:
storageStatefixture. Sign in once in a setup script, save cookies and localStorage to a JSON file (storageState: 'auth.json'), and load that state at the start of every test that needs to be signed in. This is the recommended pattern for most apps: one login round-trip amortized across the whole suite. Seetests/fixtures/auth.tsin the companion starter for a worker-scoped implementation.- Per-worker state. For tests that need different user roles, produce one auth state per role and load the right one per test via a fixture.
The anti-pattern to avoid: signing in through the UI at the top of every test. On a 500-test suite that’s 500 sign-in requests worth of flake and test time.
How would you test a file download?
Playwright has a first-class page.waitForEvent('download') API:
const downloadPromise = page.waitForEvent('download');
await page.getByRole('link', { name: 'Export CSV' }).click();
const download = await downloadPromise;
expect(download.suggestedFilename()).toBe('report.csv');
const path = await download.path();
// Read the file at `path` and assert on its contents.
What a great answer includes: setting the waitForEvent promise before the click, and reading the downloaded file to assert on its actual contents, not just its filename. Working example: tests/downloads.spec.ts in the companion starter.
How do you handle network mocking?
page.route() intercepts requests matching a URL pattern, and you fulfill them with mock responses. Use it for: making external service failures deterministic, testing error-state UI without depending on the real service, testing rate-limit behavior, and speeding up tests that don’t care about the network layer.
Don’t use it for tests that are supposed to validate the real integration. Mocking a payment gateway with page.route means you’re not testing the payment gateway integration, which is often the highest-risk area of the app.
How do you handle iframes?
page.frameLocator('selector') returns a locator scoped to the iframe. Chain further locators off it. If the iframe URL is stable, page.frame({ url: /.../ }) also works. Cross-origin iframes work fine in Playwright as long as you address them by locator, not by DOM traversal.
What’s your fixture strategy for shared test setup?
Playwright’s test.extend() creates custom fixtures that behave like arguments to your test functions. Common patterns: a loggedInPage fixture that reuses storageState, a seededDatabase fixture that inserts and cleans up test data, and a mockedApi fixture that installs page.route() handlers. The companion starter ships all three plus a per-test uniqueEmail helper, each in its own file so you can copy one into an existing suite without taking the rest.
What a great answer includes: recognition that fixtures need their own teardown logic (the use() pattern) so a failed test doesn’t leak state to the next one.
Advanced / senior
How would you scale a Playwright test suite to 10,000+ tests?
This is the question most candidates have not thought about. Playwright is faster per-test than Selenium, and its browser contexts let you run isolated sessions inside one browser process. Both real advantages. But scaling to a suite that runs in acceptable wall-clock time still requires solving three problems:
- Compute. Every parallel worker runs a browser process. Twenty workers on a laptop is a heat problem; two hundred workers in CI is a bin-packing problem. You need either a horizontally-scalable CI (GitHub Actions runners, Buildkite agents, self-hosted Kubernetes) or a hosted browser cloud (BrowserStack, LambdaTest, Sauce Labs) that abstracts the fleet.
- Sharding. Playwright’s
--shard=k/nsplits the test list across n machines. Combine with test grouping (fast tests on one shard, slow on another) so no shard dominates wall-clock time. Theblobreporter plus themerge-reportscommand consolidates the output across shards. - Test data isolation. At ten thousand tests running in parallel, hard-coded fixtures collide. Every test needs unique data (UUID-suffixed emails, per-worker database schemas, per-context storage). This is where suites that worked at 500 tests break.
What a great answer includes: naming the compute constraint explicitly. Most candidates focus on Playwright’s speed and miss that the bottleneck at scale isn’t Playwright. It’s the fleet of browsers you need to run in parallel.
When would you NOT use Playwright?
- Native mobile apps. Playwright is web-only. Use Appium or the platform-specific tools (XCUITest, Espresso).
- Component testing where the framework’s own tools are better. React Testing Library, Vue Test Utils, and Angular’s component harness give you finer-grained control at the component level.
- Legacy Selenium fleets you’re not migrating from. If your org has a 5,000-test Selenium suite that works, “rewrite it in Playwright” is not a strategy. It’s a two-year project. Migrate incrementally by domain.
- Non-browser API testing. Playwright has a request-only mode, but if you’re only testing APIs, use
supertest,httpx, or a dedicated API tool.
Trace viewer: real debug tool or crutch?
Real debug tool. The trace file captures the DOM state, network activity, console logs, and screenshots at every action, viewable in a local UI. It compresses a “I can’t reproduce this on my machine” investigation from an hour to a few minutes. Enable it selectively in CI (trace: 'retain-on-failure'). Capturing traces on every test explodes storage and slows CI.
How do you handle flakiness in an established Playwright suite?
Same triage as any suite: instrument first, quarantine at a pass-rate threshold, fix weekly. Playwright-specific checks:
- Assertions use the retrying
expect(locator)API, notexpect(await locator.textContent()). waitForEventpromises are set before the triggering action, not after.- Tests don’t assert on network-dependent state without a
waitForResponsegate. - Fixtures clean up after themselves so a failed test doesn’t leak state.
The instrumentation half of that workflow — distinguishing “flaked” (passed on retry) from “failed” (never passed), and emitting per-test outcome data for a rolling-window aggregator — is exactly what the flake reporter in the companion starter ships. The docs/flakiness.md page walks through the GitHub Actions cache-based aggregation pattern for the 98% pass-rate rule.
Codegen: production tool or starting point?
Starting point. npx playwright codegen records interactions and emits Playwright code. It’s useful for scaffolding a test’s selectors and skeleton, but the generated code needs cleanup before it lands in the suite: brittle selectors get replaced with role-based ones, hard-coded values get parameterized, and repeated blocks get extracted into fixtures. Candidates who present codegen output as final-form work signal they haven’t maintained a test suite for more than a quarter.
How to prepare
If you’re interviewing on Playwright in 2026, the highest-value prep is:
- Build one small suite against a real public app. Not a toy. Hit a real API, handle real auth, deal with real flakiness. This is what interviewers listen for: the specifics of what tripped you up.
- Read the official docs on fixtures and network mocking end-to-end. These are the two topics where the docs are better than any third-party tutorial, and where interview questions cluster.
- Practice the scaling answer. Even if your day job doesn’t involve 10k-test suites, know how sharding, workers, and browser clouds compose. The scaling question is common at staff-and-above interviews.
- Have an opinion on trace viewer and codegen. Interviewers ask; a candidate who has used them in anger has a stronger answer than one who has only seen them in videos.
Practical structured prep on the framework itself: Udemy’s Playwright courses cover the fixtures and parallelization surface faster than assembling it from official docs alone.
Related reading
- qarepo-playwright-starter. Open-source starter demonstrating the scaling patterns above as working code: bundled Express + SQLite demo, four fixture modules, sharded GitHub Actions workflow, three browser-cloud configs, flake reporter with 90-day artifact aggregation. Scaffold with
npm create qarepo-playwright my-suite. v0.3.0. - QA & SDET Interview Questions for 2026. The full pillar; this piece is one spoke of a six-round guide.
- Playwright vs. Cypress vs. Selenium. Framework comparison with 2026 adoption numbers and benchmark data.
- Using AI Agents for Testing. Playwright shows up throughout the operational workflow.
- Testing in the Age of AI. The strategic frame for why real end-to-end browser tests are getting more important, not less.
- What Is an SDET in 2026?. Framework work belongs to the “test tooling engineer” of the three SDET roles.
- How to Write a Bug Report. Adjacent to the behavioral-round questions in the pillar.