Passkeys changed the shape of authentication testing. A login flow that used to be a sequence of username, password, and maybe a one-time code can now depend on browser APIs, OS-level prompts, authenticator selection, device presence, and state stored outside the browser profile. That makes WebAuthn testing less about “can I click through a form” and more about whether the test stack can model a real authenticator, survive browser constraints, and still fit into a CI pipeline.

This article looks at Playwright, Selenium, Cypress, and newer AI-assisted platforms through a narrow but practical lens: Playwright vs Selenium WebAuthn passkey testing. The question is not which tool is universally best, but which one can validate the parts of a passkey flow that matter for your product, your risk profile, and your maintenance budget.

The hardest part of passkey testing is not scripting the login, it is deciding which layer you are actually validating: browser behavior, authenticator behavior, OS integration, or your own application’s session handling.

What makes WebAuthn passkey testing different

WebAuthn is not just “another login form.” The browser speaks to an authenticator through the Web Authentication API, and the authenticator may be a platform authenticator, a roaming hardware key, or a virtual authenticator supplied by the browser automation stack. The browser may also delegate UI to the OS, which means the automation tool does not always control the final prompt.

For test design, this creates four distinct levels of validation:

  1. Application logic, for example the app renders “Sign in with passkey” and redirects correctly after login.
  2. Browser API integration, for example navigator.credentials.create() and navigator.credentials.get() succeed with the right options.
  3. Authenticator handling, for example discoverable credentials, user verification, resident keys, or cross-platform authenticators behave as expected.
  4. Real device and OS prompt behavior, for example the platform prompt appears, the user can approve or cancel, and the session survives the actual authentication round trip.

A tool can be excellent at one layer and weak at another. The biggest mistake teams make is treating passkey testing as a pure UI automation problem. It is not. It is a browser, authenticator, and platform integration problem wrapped in a UI workflow.

The decision criteria that actually matter

When evaluating test stacks for WebAuthn, use criteria that map to your risk and maintenance costs, not just API familiarity.

1. Can it drive virtual authenticators in a repeatable way?

Virtual authenticators are often the most CI-friendly way to simulate a passkey. They let you exercise WebAuthn without a physical security key or a real phone prompt. This is useful for coverage of happy paths and negative cases, such as invalid credentials or user cancellation.

2. Can it validate real device prompts when needed?

If your product supports device-bound credentials, platform authenticators, or cross-device login, eventually you need real hardware or a managed browser environment that can expose those prompts. Virtual authenticators are necessary, but not sufficient.

3. How much setup does the framework need?

If every flow requires custom DevTools plumbing, local certificates, or hand-built helper utilities, the test may be technically correct but operationally expensive. This is where the total cost of ownership starts to matter: implementation time, CI stability, code review burden, and the number of people who can maintain the suite.

4. How well does it handle authenticated state after login?

Passkey testing is rarely just about the authentication ceremony. Teams usually need to verify sessions, cookies, refresh, logout, and account recovery. A tool that can create the login state but not preserve or restore it cleanly leaves a large gap.

5. How portable is the test across environments?

A test that only works on a single developer laptop, with a specific browser build, is not a sustainable regression check. CI friendliness matters, but so does reproducibility across local runs, containerized runners, and managed browser grids.

Playwright: the strongest fit for browser-level WebAuthn simulation

Playwright is usually the most direct option for testing WebAuthn flows because it exposes browser automation features that align with modern auth testing. Its browser-context model, reliable locator API, and built-in support for Chromium DevTools Protocol scenarios make it easier to work with virtual authenticators and session state than older frameworks.

The official Playwright docs focus on general browser automation, but in practice its architecture is a good fit for auth tests that need strong isolation, predictable profiles, and programmatic control over browser state.

Where Playwright helps

  • Virtual authenticator workflows are easier to integrate when the browser automation layer exposes lower-level control.
  • Context isolation makes it simpler to model fresh login states and separate accounts.
  • Storage state can be used to capture an authenticated session after a passkey flow and reuse it for later tests.
  • Parallel execution is generally easier to reason about than with older, shared-state Selenium suites.

A Playwright test for a passkey flow often looks like this structurally:

import { test, expect } from '@playwright/test';
test('user can sign in with passkey', async ({ page }) => {
  await page.goto('https://example.test/login');
  await page.getByRole('button', { name: 'Sign in with passkey' }).click();

// The exact authenticator setup depends on your browser and test environment. // The important part is that the test drives the flow from the browser side. await expect(page.getByText(‘Welcome back’)).toBeVisible(); });

The example is intentionally simple. Real WebAuthn tests tend to need environment setup, not just page interactions. That setup is where Playwright’s strengths show up, and also where teams can lose time if they do not standardize their harness.

Where Playwright still falls short

Playwright can simulate many browser-side aspects of WebAuthn, but that does not guarantee parity with a real device. Common failure modes include:

  • The virtual authenticator behaves differently from a platform authenticator.
  • A prompt appears only in the browser, not in the OS, so the automation covers the browser event but not the user-facing device interaction.
  • Session logic passes in CI but fails on managed browsers or mobile devices because the authenticator availability differs.
  • The test asserts success at the app level while missing credential enrollment details that only matter in production.

In other words, Playwright is excellent for deterministic coverage of the browser and app layers, but it does not eliminate the need for real-device validation.

Selenium: flexible, but WebAuthn usually needs more plumbing

Selenium remains widely used, especially in teams with an established Java, Python, or C# automation base. Its strength is broad browser support, ecosystem maturity, and a long history in CI infrastructure. For standard login flows, it is still entirely viable.

For WebAuthn, though, the picture is more mixed. Selenium can drive browsers that support passkeys, but if you want clean virtual authenticator control or browser-specific auth plumbing, you often need additional setup and browser-specific capabilities. The test author ends up bridging a gap between Selenium’s generic WebDriver abstraction and the browser features required by WebAuthn.

Where Selenium is a reasonable choice

  • You already have a large Selenium suite and want to add a limited number of auth tests.
  • Your organization values WebDriver compatibility across many browser vendors.
  • You need to keep a shared skill set across a broad QA team.
  • Your auth tests are mostly smoke checks rather than deep protocol validation.

Where Selenium becomes costly

Selenium’s abstraction is useful until you need browser-specific control. Then the following issues often appear:

  • More custom code is needed to reach lower-level browser features.
  • Wait handling becomes more verbose.
  • The test harness may depend on browser or driver versions more tightly than expected.
  • Debugging a flaky auth flow can involve multiple layers, driver, browser, grid, and OS.

A Selenium example for a passkey-based flow can remain straightforward at the UI level:

from selenium import webdriver
from selenium.webdriver.common.by import By
from selenium.webdriver.support.ui import WebDriverWait
from selenium.webdriver.support import expected_conditions as EC

driver = webdriver.Chrome() driver.get(‘https://example.test/login’) driver.find_element(By.CSS_SELECTOR, ‘button[data-testid=”passkey-login”]’).click()

WebDriverWait(driver, 10).until( EC.visibility_of_element_located((By.CSS_SELECTOR, ‘[data-testid=”dashboard”]’)) )

But the challenge is not clicking the button. The challenge is what happens when the login depends on authenticator behavior that Selenium does not model natively. Teams then end up building helper layers, custom driver configuration, or browser-specific workarounds. That can be fine if Selenium is already the company standard, but it is not the lowest-friction option for new WebAuthn coverage.

Cypress: good for app flows, limited for authenticator realism

Cypress is strong for application-level testing, especially where the team wants a tight developer experience and fast feedback in the browser. For ordinary UI flows, it can be productive. For WebAuthn passkeys, the limitations are more visible.

The core issue is that Cypress is not designed as a general-purpose browser and device automation layer in the same way Playwright and Selenium are. Passkey testing often needs deeper control over browser contexts, authenticator state, or cross-origin and device-prompt behavior that falls outside Cypress’s sweet spot.

Cypress is useful when

  • You only need to confirm the app shows the right login entry point.
  • A backend test or API-level fixture can bypass the actual passkey ceremony for some scenarios.
  • The goal is functional coverage around the authentication state, not authenticator realism.

Cypress is less useful when

  • You need to validate WebAuthn registration and assertion flows end to end.
  • You want a realistic simulation of platform or roaming authenticators.
  • You need to test session recovery, multiple accounts, or device-backed credential behavior.

A common pattern is to use Cypress for the surrounding app experience and rely on Playwright or Selenium for the actual passkey ceremony. That division can work, but it creates two automation stacks for one login story, which is a maintenance tradeoff rather than a pure win.

Virtual authenticators versus real devices

The practical question is not whether you should use virtual authenticators or real devices. You probably need both, but for different reasons.

Virtual authenticators are best for

  • CI-friendly regression checks
  • repeated login assertions
  • negative cases, such as denied access or invalid credential metadata
  • deterministic testing of browser-level WebAuthn support
  • fast feedback on app changes that impact the auth journey

Real devices are best for

  • validating platform prompts and user verification behavior
  • verifying that passkeys work as users actually experience them
  • checking platform-specific quirks, including browser versions, OS updates, and device policies
  • proving that your recovery and session logic behaves correctly after a real authentication ceremony

A sensible test strategy uses virtual authenticators for broad coverage and a smaller number of real-device checks for confidence. The mistake is expecting one layer to substitute for the other.

If your release gate only uses virtual authenticators, you are testing implementation details of the browser automation setup as much as you are testing your product.

Managed browsers change the equation

Managed browser platforms can make browser provisioning, scaling, and cross-environment reproducibility easier. They are useful when teams need real browser coverage without maintaining their own lab of machines. For WebAuthn, the value depends on whether the managed environment exposes the authenticator behavior you need.

The main decision point is whether the managed browser offers:

  • support for the browser version you care about
  • predictable profiles and session isolation
  • access to platform authenticator prompts or equivalent emulation
  • logging that helps explain auth failures
  • enough control for security-sensitive flows

Managed browsers solve infrastructure problems, but they do not automatically solve authenticator realism. If the provider abstracts away the very prompt or OS integration you need to test, then the test is still incomplete.

What a realistic test matrix looks like

For many teams, a good matrix is smaller than they expect, but better scoped.

Layer 1, smoke checks

  • login page renders
  • passkey option is visible
  • credentials flow starts
  • session lands on the dashboard

These can run frequently and should be stable.

Layer 2, browser-level WebAuthn coverage

  • registration succeeds with a virtual authenticator
  • assertion succeeds after re-login
  • cancel and error paths are handled
  • credential recovery and logout reset state correctly

These tests are more sensitive to browser configuration, but they are still automation friendly.

Layer 3, real device validation

  • platform authenticator login on a real device
  • cross-device or roaming authenticator scenario
  • browser and OS prompt behavior
  • session persistence after real approval

These should be fewer, but they validate the highest-risk integration points.

Layer 4, security and recovery checks

  • account recovery after lost passkey
  • multiple passkeys per account
  • fallback mechanisms for unsupported browsers
  • session invalidation after credential removal

These tests often matter as much as the login ceremony itself because they catch the operational reality of passkeys in production.

CI-friendly coverage has a ceiling

It is tempting to believe that because WebAuthn can be scripted, it can be fully covered in CI. That is only partially true. CI is excellent for repeatability, but the more your login flow depends on browser or device state outside the application, the more carefully you must define what “covered” means.

A CI-friendly suite can verify that:

  • the app initiates WebAuthn correctly
  • the browser accepts the expected options
  • session state is established and persisted
  • the UI reacts properly to success and failure

It cannot always verify that:

  • a user sees the exact device prompt they expect
  • the hardware or OS authenticates the way your support matrix requires
  • mobile, desktop, and managed browsers all behave identically
  • credential sync or device enrollment works under every policy combination

This is why mature teams separate “automated regression” from “device-backed validation.” Both matter, but they answer different questions.

A practical comparison by team profile

Choose Playwright first if

  • you are starting a new browser automation effort
  • WebAuthn coverage is important enough to justify lower-level browser control
  • you want strong test isolation and modern browser APIs
  • your team can support TypeScript or JavaScript-based harnesses

Choose Selenium first if

  • your organization already has a large Selenium estate
  • cross-browser standardization is more important than newer browser APIs
  • you need to preserve existing language and framework investments
  • passkey coverage is a small extension of a broader regression suite

Choose Cypress first if

  • your main need is app-centric functional testing rather than authenticator realism
  • login testing can be partially abstracted through backend fixtures or token seeding
  • your team values simplicity over deep browser control

Add managed browsers if

  • you need reproducible browser versions without local setup burden
  • you want to reduce environment drift in CI
  • your auth tests require broader browser coverage than a single internal grid can provide

Add real-device validation if

  • passkeys are a core product path, not an edge feature
  • security or compliance teams expect validation on actual devices
  • your users rely on platform authenticators, synced passkeys, or roaming keys

Where Endtest can simplify the evaluation

For teams asking whether code-based auth testing is worth the setup and maintenance cost, Endtest is a useful reference point because it takes a different approach: low-code, agentic AI Test automation with editable, human-readable steps. That can be attractive when the real need is not framework mastery, but reliable authentication coverage with less infrastructure overhead.

Endtest is worth evaluating when the team wants to avoid writing and maintaining custom browser harnesses for every auth variation. Its self-healing tests are relevant here because authentication pages often change around the edges, for example button labels, wrappers, or DOM structure, while the real test intent stays the same. Its AI Assertions also matter when the test outcome is better expressed as “the login succeeded and the session is established” than as a brittle selector and string match.

That does not mean Endtest replaces every deep WebAuthn scenario. Rather, it can be a simpler operational choice for teams that want maintainable, human-readable auth flows without owning a substantial code framework. For many organizations, that is exactly the tradeoff to examine alongside Playwright and Selenium.

If you are comparing the maintenance burden of code-first auth testing with a more managed approach, a useful next read is Endtest vs Playwright for testing modern authentication flows and session recovery. The comparison is especially relevant when the authentication story includes session persistence, recovery paths, and UI churn around login screens.

Common failure modes to watch for

1. Testing the wrong layer

A test passes because the page moved forward, but it never verified that the passkey challenge actually completed. Make sure your assertion is tied to a real post-authenticated state.

2. Assuming virtual equals real

Virtual authenticators are valuable, but they do not fully model OS prompts, hardware timing, or device policies.

3. Overfitting to one browser

Passkey support and prompt behavior can vary across browsers and versions. If your product supports multiple browsers, define which one is the release gate and which ones are compatibility checks.

4. Building too much custom plumbing

When a Selenium or Playwright suite accumulates device setup scripts, driver glue, and special wait logic, the team may spend more time maintaining the harness than validating product behavior.

5. Ignoring recovery and revocation

Passkey testing is incomplete if it only covers the first successful login. Removal, backup, fallback, and session invalidation are part of the real security story.

A sensible default recommendation

If your team is starting from scratch and needs serious WebAuthn passkey coverage, Playwright is usually the best first stop because it offers the most practical balance of browser control, isolation, and automation ergonomics.

If you already have a large Selenium investment, do not assume a rewrite is required. Add focused passkey tests where the existing stack can support them, and accept that some device-backed coverage may still need a separate path.

If your goal is mostly to validate application outcomes around authentication, not to build a deeply customized browser-auth harness, a maintained platform such as Endtest may reduce the setup and ongoing maintenance cost enough to be the more practical choice.

The important point is that WebAuthn testing is not a single capability. It is a stack of decisions about realism, repeatability, and ownership. The best tool is the one that matches the level of truth you need, while keeping the test suite understandable enough that your team can still maintain it a year from now.

Closing perspective

Passkeys are good for users because they reduce password risk and simplify login. They are more demanding for testers because they force the automation layer to confront authenticator behavior, browser APIs, and device prompts all at once. That is why browser authentication testing should be evaluated with a narrower lens than generic UI automation.

Use Playwright when you need modern browser control and deterministic WebAuthn simulation. Use Selenium when ecosystem continuity matters and you can tolerate more plumbing. Use Cypress for app-centric flows that do not require deep authenticator realism. Use real devices for the cases that virtual authenticators cannot faithfully represent. And if the maintenance burden of code-based testing keeps rising, seriously evaluate whether a managed, human-readable platform is a better fit for your team’s authentication coverage.