How to Use Selenium 4 Authentication Commands
Use Selenium 4’s virtual authenticator commands to test WebAuthn registration and authentication, manage credentials, and clean up test state.
Selenium 4’s authentication commands are its WebAuthn virtual-authenticator controls. They let a WebDriver test add a simulated authenticator, exercise a website’s WebAuthn registration or authentication flow, inspect or remove credentials, and tear down the authenticator. They do not bypass login or replace the application’s server-side authentication logic.
This guide uses Selenium’s Python binding. The exact code below targets the current Python API documented in the Selenium WebDriver reference; install Selenium 4 and check the API reference for your installed version because bindings and argument names can differ. [Selenium Python API reference]
1. What these commands do
WebAuthn is a browser API through which a relying-party website creates and uses public-key credentials. A virtual authenticator gives an automated test a controllable software implementation of authenticator behavior. The web page still has to initiate WebAuthn registration or authentication, and the application still decides how to validate and authorize the resulting request. A virtual authenticator is not a physical security key and does not prove that production hardware works. [W3C WebAuthn Level 3]
Selenium’s Python API documents these operations:
| Operation | Purpose |
|---|---|
driver.add_virtual_authenticator(options) |
Create and attach a configured virtual authenticator; returns the authenticator object. |
authenticator.add_credential(credential) |
Add a credential to the authenticator. |
authenticator.get_credentials() |
Read credentials currently held by the authenticator. |
authenticator.remove_credential(credential_id) |
Remove one credential by its ID. |
authenticator.remove_all_credentials() |
Clear the authenticator’s credential store. |
authenticator.remove() |
Remove the virtual authenticator from the session. |
After removal, the authenticator is no longer valid; do not call its methods after teardown. Consult the installed binding’s reference for exact class and method details. [Selenium Python API reference]
2. Choose options that match the scenario
The options describe the authenticator you want to simulate. Select them from the relying party’s requirements rather than assuming one setup is best for every test.
| Setting | What it controls | Test question |
|---|---|---|
| Protocol | ctap2 or ctap1/u2f |
Which authenticator protocol should this scenario exercise? |
| Transport | For example, USB or internal | Which transport does the application or browser flow expect? |
| Resident-key support | Whether discoverable credentials can be stored | Does the relying party request a resident/discoverable credential? |
| User-verification support | Whether the simulated authenticator supports user verification | Does the test cover a flow that requests verification? |
| User-consent behavior | Whether consent is simulated | Does the test need consent behavior enabled or disabled? |
| User-verified state | Whether the authenticator reports the user as verified | Which verified/unverified outcome should the assertion cover? |
Credential data includes properties such as credential ID, relying-party ID, resident status, user handle, private key, and signature count. Use the credential model from the Selenium version installed in your project rather than guessing constructor parameters. [Python virtual authenticator API]
3. Install Selenium and prepare a WebDriver session
Install Selenium in the same Python environment that runs the tests:
python -m pip install "selenium>=4,<5"
The following example shows the lifecycle and uses Chrome. Provide a test page that actually implements WebAuthn registration, with a button whose ID is register-passkey and a page element with ID registration-status that becomes success after the application completes registration. Replace the example URL and selectors with those in your application. This is runnable once those application-specific values match your page.
from selenium import webdriver
from selenium.webdriver.common.by import By
from selenium.webdriver.support import expected_conditions as EC
from selenium.webdriver.support.ui import WebDriverWait
from selenium.webdriver.common.virtual_authenticator import (
VirtualAuthenticatorOptions,
)
TEST_URL = "https://your-test-app.example/webauthn/register"
options = webdriver.ChromeOptions()
# Add headless mode only if it is supported by your browser/test setup.
# options.add_argument("--headless=new")
driver = webdriver.Chrome(options=options)
authenticator = None
try:
virtual_options = VirtualAuthenticatorOptions()
# Set protocol, transport, resident-key, and verification options here
# using the names supported by your installed Selenium version.
authenticator = driver.add_virtual_authenticator(virtual_options)
driver.get(TEST_URL)
driver.find_element(By.ID, "register-passkey").click()
status = WebDriverWait(driver, 15).until(
EC.text_to_be_present_in_element((By.ID, "registration-status"), "success")
)
assert status, "The application did not report successful registration"
credentials = authenticator.get_credentials()
assert credentials, "Registration completed but no credential was stored"
print(f"Registered credentials: {len(credentials)}")
finally:
if authenticator is not None:
authenticator.remove()
driver.quit()
The scenario-specific options and credential creation API are version-sensitive. To keep code aligned, inspect the Python API reference for VirtualAuthenticatorOptions and Credential in your installed version before adding explicit credentials or setting less common options. The test above lets the page’s WebAuthn registration request create the credential, then checks the resulting authenticator store.
4. Run the full registration and authentication lifecycle
- Start the browser session. Use the browser and driver configuration already supported by your Selenium environment.
- Create options for the scenario. Match protocol, transport, resident-key and user-verification behavior to the relying party’s request.
- Add the authenticator. Call
driver.add_virtual_authenticator(options)before triggering the page flow. - Navigate and use the application. Trigger registration or sign-in through the application UI. The page invokes WebAuthn; Selenium provides the test authenticator.
- Assert both sides of the behavior. Check the application’s visible or testable result, and inspect credentials when the test needs to confirm authenticator state.
- Clean up. Remove selected credentials or all credentials when appropriate, then remove the authenticator during teardown.
For an authentication test, register a credential through the application first, then invoke the application’s WebAuthn sign-in flow and assert that the server accepts the resulting assertion for the expected test user. A credential appearing in the authenticator alone does not prove that server-side verification or account authorization is correct.
5. Manage credentials
Use the authenticator methods to inspect or reset credential state. The following operations assume authenticator is the object returned by add_virtual_authenticator and that the installed binding accepts the shown credential-ID representation:
# Inspect credentials created by a page's WebAuthn registration flow
credentials = authenticator.get_credentials()
for credential in credentials:
print(credential)
# Remove every stored credential before another isolated scenario
authenticator.remove_all_credentials()
# Or remove one credential using its ID
# authenticator.remove_credential(credential_id)
For tests that need a preloaded credential, create the credential object using the exact constructor and binary encoding documented for your Selenium version, then pass it to add_credential. Credential IDs and user handles are byte data in the API model; do not assume that a displayed hex or base64 string can be passed unchanged. [Credential and authenticator API]
6. Teardown and test isolation
Use finally or your test framework’s teardown hook so failures do not leave browser processes running or authenticator state attached to a session. Remove the authenticator only after assertions and any credential inspection are complete. Once removed, do not use its object again.
- Create a fresh driver/authenticator per isolated test when state sharing could affect results.
- Clear credentials between scenarios that intentionally share a browser session.
- Keep registration and authentication assertions separate so a registration success cannot mask a failed sign-in check.
- Use test accounts and a test relying party; never treat a virtual authenticator as a way to access accounts without their normal authorization.
7. Troubleshooting
| Symptom | Likely cause | Fix |
|---|---|---|
| The virtual authenticator import or class is missing | The Selenium package version or import path differs from the example. | Check selenium.__version__ and the API reference for that installed release; upgrade within Selenium 4 if needed. |
add_virtual_authenticator is unavailable or fails |
The binding, browser, or driver does not support the command in the current combination. | Confirm the method in the installed binding docs and verify the chosen browser/driver support. The references do not establish universal compatibility across every browser/version pair. |
| Registration times out waiting for success | The page selector or expected status is wrong, the app rejected the request, or the WebAuthn flow did not start. | Confirm the test URL and selector against the page, inspect browser console/application logs, and ensure the click reaches the registration handler. |
| The app reports registration but the credential list is empty | The flow may have used a different browser/session, failed before authenticator storage, or the test asserted too early. | Ensure the authenticator was added to the same driver before registration; wait for the app’s completion state and inspect the returned credential list. |
| Resident/discoverable credential scenario fails | The options do not enable the required resident-key behavior, or the relying party requests capabilities the test authenticator lacks. | Match resident-key and protocol options to the request and verify option names for the Selenium version in use. |
| Verification-required flow fails | User-verification support or verified state does not match the relying party’s request. | Configure support and state deliberately, then test both accepted and rejected cases as required by the application. |
| Credential removal raises an error | The ID is in a different byte/string representation, the credential is already absent, or the authenticator was removed. | Use the credential ID object/value returned by the API, check current credentials, and perform credential operations before authenticator teardown. |
| Later test behaves differently from the first | Credentials or browser state leaked across scenarios. | Clear credentials or create a fresh authenticator/session, and keep cleanup in a guaranteed teardown path. |
8. Performance, reliability, and cost
Virtual-authenticator setup is local to the WebDriver test flow and avoids requiring a physical security key for these simulated scenarios. Overall test time still depends on browser startup, page loading, application services, and explicit waits. Prefer waiting for a meaningful page state over arbitrary sleeps, and use a bounded timeout so a broken flow fails with a useful signal.
Reliability depends on matching the Selenium binding, browser, driver, and authenticator options to the test. Keep a small compatibility check in the test environment and avoid assuming that a result from a virtual authenticator establishes behavior on real hardware. No universal compatibility matrix or benchmark is established by the cited references.
There is no per-command Selenium authentication fee described in these references; the operational costs are your browser/test infrastructure and the application environment being exercised. For repeated page evidence or screenshot capture in a separate workflow, ScreenshotNeo offers a website screenshot API. It is not a WebAuthn authenticator and does not replace this test lifecycle.
9. Or skip the browser setup
If you need a page screenshot for documentation or review rather than a WebAuthn test, ScreenshotNeo returns an image or PDF with one GET request. It does not exercise Selenium’s virtual-authenticator commands.
curl -G "https://api.screenshotneo.com/v1/shot" -d access_key=YOUR_API_KEY --data-urlencode url=https://stripe.com -o shot.webp
See the ScreenshotNeo API documentation for parameters and output options. Cookie banners, popups, and chat widgets are removed before the shot; bot checks, blank pages, and failed loads are never billed; an MCP server lets AI agents use screenshot tools; and 1,000 screenshots a month are free with no card, with paid plans starting at $5 for 3,000. Sign up for 1,000 free screenshots a month, with no card required.
10. FAQ
Are Selenium authentication commands generic login bypass commands?
No. They control a virtual WebAuthn authenticator for test automation. The application’s normal login and server-side validation still apply.
Does a virtual authenticator test a physical security key?
No. It simulates authenticator behavior in a controlled browser test. Hardware testing is a separate activity.
Can I use these commands with every Selenium 4 language binding?
Do not assume exact parity. The examples here use Python; check the API documentation for your binding and installed version.
Can I use Chrome DevTools to understand the same workflow?
Chrome DevTools has a comparable manual virtual-authenticator workflow for inspecting credentials and sign counts. Its controls are separate from Selenium’s API. [Chrome DevTools WebAuthn]


