BrowserContext.setHTTPCredentials method
BrowserContext.setHTTPCredentials() (JavaScript only) sets credentials for HTTP authentication for the browser context. It accepts httpCredentials (null, object, or array of objects) with properties: username (string), password (string), and optional origin (string) to restrict credentials to a specific origin (scheme://host:port). Pass an array to use different credentials for different origins; the first matching entry is used, and entries with no origin match any request.
Credentials class overview and purpose
The Credentials class is a virtual WebAuthn authenticator scoped to a BrowserContext, available since v1.61. It lets tests register passkeys and answer navigator.credentials.create() and navigator.credentials.get() ceremonies in the page without a real authenticator or hardware security key.
Three common usage patterns for Credentials
The Credentials class supports three usage patterns: (1) Seed a known credential by importing a passkey that already exists via Credentials.create() so the app can sign in right away; (2) Capture a credential then reuse it by letting the app register a passkey in a setup test, reading it with Credentials.get(), and seeding it into later tests; (3) Save credentials in the storage state via BrowserContext.storageState.credentials and restore them later.
Credentials.install() method
The async Credentials.install() method, available since v1.61, installs the virtual WebAuthn authenticator into the context, overriding navigator.credentials.create() and navigator.credentials.get() in all current and future pages. This must be called before the page first touches navigator.credentials. Until install() is called, no interception is in place and the page sees the platform's native WebAuthn behaviour. Seeding credentials with Credentials.create() without installing populates the authenticator, but the page will never see those credentials.
Credentials.create() method signature and return type
The async Credentials.create(rpId, options) method, available since v1.61, seeds a virtual WebAuthn credential and returns an object with fields: id (string, base64url-encoded credential id), rpId (string, relying party id), userHandle (string, base64url-encoded user handle), privateKey (string, base64url-encoded PKCS#8 DER private key), publicKey (string, base64url-encoded SPKI DER public key). The rpId parameter is required; all other fields are optional.
Credentials.create() behavior with only rpId
When Credentials.create() is called with only the rpId parameter, it generates a fresh ECDSA P-256 keypair, credential id, and user handle. The seeded credential is discoverable (resident), so the page can resolve it from both username-then-passkey and usernameless passkey flows. The returned object carries the private and public keys for persistence and re-seeding in later tests.
Credentials.create() import a known credential
To import a known credential into Credentials.create(), supply all four parameters together: id, userHandle, privateKey, and publicKey. These must all be provided as base64url-encoded strings (privateKey as PKCS#8 DER, publicKey as SPKI DER). Credentials.install() must be called before navigating to a page that uses WebAuthn.
Credentials.create() option: id
The id option for Credentials.create(), available since v1.61, accepts a base64url-encoded credential id. This parameter is optional; if omitted, a credential id is auto-generated.
Credentials.create() option: userHandle
The userHandle option for Credentials.create(), available since v1.61, accepts a base64url-encoded user handle. This parameter is optional; if omitted, a user handle is auto-generated.
Credentials.create() option: privateKey
The privateKey option for Credentials.create(), available since v1.61, accepts a base64url-encoded PKCS#8 (DER) private key. This parameter is optional; if omitted, a private key is auto-generated.
Credentials.create() option: publicKey
The publicKey option for Credentials.create(), available since v1.61, accepts a base64url-encoded SPKI (DER) public key. This parameter is optional; if omitted, a public key is auto-generated.
Credentials.delete() method
The async Credentials.delete(id) method, available since v1.61, removes a credential from the authenticator by its base64url-encoded id. It works for any credential currently held, both those seeded with Credentials.create() and those the page registered itself by calling navigator.credentials.create().
Credentials.get() method signature and return type
The async Credentials.get(options) method, available since v1.61, returns an array of VirtualCredential objects. Each object contains: id (string), rpId (string), userHandle (string), privateKey (string), publicKey (string). The method returns every credential currently held by the authenticator, optionally filtered by rpId or id options.
Credentials.get() option: rpId filter
The rpId option for Credentials.get(), available since v1.61, filters results to only return credentials for a specific relying party id.
Credentials.get() option: id filter
The id option for Credentials.get(), available since v1.61, filters results to only return the credential with the specified base64url-encoded credential id.
Credentials.get() includes private and public keys
Each credential returned by Credentials.get() includes its private and public keys. This allows a passkey that the app just registered to be saved and re-seeded into a later test with Credentials.create().
Credentials default authenticator properties
By default, the virtual authenticator presents itself as a platform authenticator with authenticatorAttachment set to 'platform', and PublicKeyCredential.isUserVerifyingPlatformAuthenticatorAvailable() resolves to true in the page. Seeded credentials are discoverable (resident), so both username-then-passkey and usernameless passkey flows resolve them. Fresh keys are ECDSA P-256 (COSE algorithm -7). An omitted id or userHandle is filled with 16 random bytes.
JavaScript example: seed a known credential
const context = await browser.newContext();
// A passkey your backend already provisioned for a test user.
await context.credentials.create('example.com', {
id: knownCredentialId, // base64url
userHandle: knownUserHandle, // base64url
privateKey: knownPrivateKey, // base64url PKCS#8 (DER)
publicKey: knownPublicKey, // base64url SPKI (DER)
});
await context.credentials.install();
const page = await context.newPage();
await page.goto('https://example.com/login');
// The page's navigator.credentials.get() is answered with the seeded passkey.
JavaScript example: capture a credential, then reuse it
// setup test: let the app register a passkey, then save the storage state with it.
const context = await browser.newContext();
await context.credentials.install();
const page = await context.newPage();
await page.goto('https://example.com/register');
await page.getByRole('button', { name: 'Create a passkey' }).click();
// Read back the passkey the page registered — it includes the private key.
const [credential] = await context.credentials.get({ rpId: 'example.com' });
fs.writeFileSync('playwright/.auth/passkey.json', JSON.stringify(credential));
JavaScript example: seed captured passkey in later test
// later test: seed the captured passkey so the app starts already enrolled.
const credential = JSON.parse(fs.readFileSync('playwright/.auth/passkey.json', 'utf8'));
const context = await browser.newContext();
await context.credentials.create(credential.rpId, credential);
await context.credentials.install();
const page = await context.newPage();
await page.goto('https://example.com/login');
// navigator.credentials.get() resolves the captured passkey — already signed in.