Resource library

QA How-To

Add a Selenium BiDi Authentication Handler in Java

Follow this selenium bidi authentication handler java tutorial to answer Basic Auth challenges securely now with runnable WebDriver BiDi code and tests.

18 min read | 2,587 words

TL;DR

Enable BiDi, create a Network module, subscribe to onAuthRequired before navigation, and answer an approved challenge with continueWithAuth. Filter by scheme, host, and path, then assert protected page content and the received challenge count.

Key Takeaways

  • Enable the webSocketUrl capability before constructing Selenium's BiDi Network module.
  • Register onAuthRequired before navigation so the first authentication challenge is not missed.
  • Call continueWithAuth with the challenged request ID and UsernameAndPassword credentials.
  • Filter the challenge URL before releasing credentials to prevent accidental credential disclosure.
  • Keep the Network object open for the entire navigation and close it during test cleanup.
  • Verify both valid and invalid credential paths instead of treating page load completion as proof.

A Selenium BiDi authentication handler Java tutorial should do more than hide a browser prompt. It should catch the protocol-level authentication challenge, decide whether the target is trusted, provide credentials, and prove that the protected page loaded. This guide builds that flow with Selenium's W3C WebDriver BiDi Java API.

If you need the protocol setup, browser support, and event model around this example, read the Selenium BiDi automation complete guide. Here you will focus on one production-shaped job: handling HTTP Basic authentication without embedding a username and password in a URL.

You will build a Maven and JUnit test that enables BiDi, listens for network.authRequired, restricts credential use to one origin, and answers the challenge with continueWithAuth. The same mechanics apply to supported HTTP authentication schemes when the browser exposes the challenge through WebDriver BiDi. They do not automate an HTML login form, OAuth redirect, passkey dialog, or operating-system credential window.

What You Will Build

By the end, you will have:

  • A Java 17 Maven test project using Selenium 4.38.0 and JUnit Jupiter.
  • A Chrome session with the webSocketUrl capability enabled.
  • A BiDi Network listener registered before navigation.
  • A host and path allowlist that prevents credentials from reaching an unexpected server.
  • Assertions for the authenticated page, challenge URL, and handler count.
  • A negative test that deliberately supplies the wrong password.

The core flow is short: the server replies with an authentication challenge, the browser emits network.authRequired, Selenium gives your consumer a ResponseDetails object, and your code continues that request with UsernameAndPassword. The surrounding setup and assertions make the flow dependable in a real suite.

Approach Handles the native HTTP challenge Credential scope Cross-browser direction Recommended use
WebDriver BiDi Network Yes Your handler logic Standards-based BiDi New protocol-level tests
HasAuthentication Yes on supported drivers Predicate over URI Driver-specific support Existing Chromium-oriented suites
https://user:pass@host URL Inconsistently Encoded in navigation URL Often restricted Avoid
Type into an HTML form No Page DOM Broad Application login forms only

Prerequisites

Install these exact baseline tools for the tutorial:

  • Java Development Kit 17 or newer.
  • Apache Maven 3.9.6 or newer.
  • Google Chrome with a matching Selenium-supported driver. Selenium Manager resolves the driver automatically in a normal local setup.
  • Selenium Java 4.38.0.
  • JUnit Jupiter 5.11.4.

Confirm Java and Maven first:

java -version
mvn -version

Use an isolated test account. Export credentials rather than committing them:

export BASIC_AUTH_USER=admin
export BASIC_AUTH_PASSWORD=admin

The public demonstration endpoint used below is https://the-internet.herokuapp.com/basic_auth, whose documented demo credentials are admin and admin. Replace it with a controlled environment for continuous integration. Do not aim automated credentials at an arbitrary third-party host.

Verification: java -version should report 17 or later, mvn -version should resolve Maven, and both environment variables should print as nonempty if you inspect them locally. Do not print secrets in shared CI logs.

Step 1: Create the Maven Project

Create this layout:

selenium-bidi-auth/
├── pom.xml
└── src/
    └── test/
        └── java/
            └── example/
                └── BidiAuthenticationTest.java

Add the following pom.xml:

<?xml version="1.0" encoding="UTF-8"?>
<project xmlns="http://maven.apache.org/POM/4.0.0"
         xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
         xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 https://maven.apache.org/xsd/maven-4.0.0.xsd">
  <modelVersion>4.0.0</modelVersion>
  <groupId>example</groupId>
  <artifactId>selenium-bidi-auth</artifactId>
  <version>1.0-SNAPSHOT</version>

  <properties>
    <maven.compiler.release>17</maven.compiler.release>
    <project.build.sourceEncoding>UTF-8</project.build.sourceEncoding>
    <selenium.version>4.38.0</selenium.version>
    <junit.version>5.11.4</junit.version>
  </properties>

  <dependencies>
    <dependency>
      <groupId>org.seleniumhq.selenium</groupId>
      <artifactId>selenium-java</artifactId>
      <version>${selenium.version}</version>
      <scope>test</scope>
    </dependency>
    <dependency>
      <groupId>org.junit.jupiter</groupId>
      <artifactId>junit-jupiter</artifactId>
      <version>${junit.version}</version>
      <scope>test</scope>
    </dependency>
  </dependencies>

  <build>
    <plugins>
      <plugin>
        <groupId>org.apache.maven.plugins</groupId>
        <artifactId>maven-surefire-plugin</artifactId>
        <version>3.5.2</version>
        <configuration>
          <useModulePath>false</useModulePath>
        </configuration>
      </plugin>
    </plugins>
  </build>
</project>

Selenium Manager is included in Selenium, so the project does not need a WebDriver manager dependency. Keeping Selenium and JUnit versions in properties also makes upgrades explicit.

Verification: Run mvn -q -DskipTests test. Maven should resolve the dependencies and finish with exit code 0. If Java compilation reports an unsupported release, point JAVA_HOME to JDK 17 or newer.

Step 2: Enable WebDriver BiDi in Chrome

Create the test class with session setup and cleanup:

package example;

import org.junit.jupiter.api.AfterEach;
import org.junit.jupiter.api.BeforeEach;
import org.openqa.selenium.WebDriver;
import org.openqa.selenium.chrome.ChromeDriver;
import org.openqa.selenium.chrome.ChromeOptions;

class BidiAuthenticationTest {
  private WebDriver driver;

  @BeforeEach
  void startBrowser() {
    ChromeOptions options = new ChromeOptions();
    options.setCapability("webSocketUrl", true);
    driver = new ChromeDriver(options);
  }

  @AfterEach
  void stopBrowser() {
    if (driver != null) {
      driver.quit();
    }
  }
}

The webSocketUrl capability asks the driver to expose the WebDriver BiDi connection when the session starts. Set it before new ChromeDriver(options). Adding it after session creation cannot retrofit BiDi into that session.

Use the standard WebDriver type for normal navigation and DOM assertions. Selenium's BiDi module accepts that driver and obtains the BiDi-capable session underneath. ChromeDriver implements Selenium's HasBiDi contract when the capability is available.

If you run headless in CI, add options.addArguments("--headless=new"). Avoid adding CI-only flags to local code unless your environment needs them.

Verification: Temporarily add driver.get("https://example.com"); at the end of startBrowser, then run mvn test. A browser should open and close without a session creation error. Remove the temporary navigation before the next step.

Step 3: selenium bidi authentication handler java tutorial core code

Add the test imports and the first complete authentication test:

import static org.junit.jupiter.api.Assertions.assertEquals;
import static org.junit.jupiter.api.Assertions.assertTrue;

import java.util.concurrent.CompletableFuture;
import java.util.concurrent.TimeUnit;
import java.util.concurrent.atomic.AtomicInteger;
import org.junit.jupiter.api.Test;
import org.openqa.selenium.By;
import org.openqa.selenium.UsernameAndPassword;
import org.openqa.selenium.bidi.module.Network;
import org.openqa.selenium.bidi.network.ResponseDetails;

@Test
void authenticatesWithWebDriverBiDi() throws Exception {
  String user = System.getenv().getOrDefault("BASIC_AUTH_USER", "admin");
  String password = System.getenv().getOrDefault("BASIC_AUTH_PASSWORD", "admin");
  AtomicInteger challengeCount = new AtomicInteger();
  CompletableFuture<String> challengedUrl = new CompletableFuture<>();

  try (Network network = new Network(driver)) {
    network.onAuthRequired(details -> {
      challengeCount.incrementAndGet();
      challengedUrl.complete(details.getRequest().getUrl());
      network.continueWithAuth(
          details.getRequest().getRequestId(),
          new UsernameAndPassword(user, password));
    });

    driver.get("https://the-internet.herokuapp.com/basic_auth");

    assertEquals("Basic Auth", driver.findElement(By.tagName("h3")).getText());
    assertTrue(driver.findElement(By.tagName("p")).getText()
        .contains("Congratulations"));
    assertTrue(challengedUrl.get(5, TimeUnit.SECONDS).endsWith("/basic_auth"));
    assertEquals(1, challengeCount.get());
  }
}

Register the listener before driver.get. Authentication is part of navigation, so a listener attached afterward is too late. onAuthRequired receives ResponseDetails. Its request contains both the challenged URL and the request ID that must be passed back to continueWithAuth.

The try-with-resources block matters. Network implements AutoCloseable; closing it removes its subscriptions and intercepts. Keep it alive until navigation and assertions finish.

Verification: Run mvn -Dtest=BidiAuthenticationTest#authenticatesWithWebDriverBiDi test. The test should pass, the heading should equal Basic Auth, the paragraph should contain Congratulations, and exactly one challenge should be counted.

Step 4: Restrict Credentials to the Trusted Origin

The basic example answers every authentication challenge during its lifetime. That is too broad for a suite that loads third-party resources or moves across environments. Add a strict allowlist before providing credentials:

import java.net.URI;

private static boolean isApprovedChallenge(String rawUrl) {
  URI uri = URI.create(rawUrl);
  return "https".equalsIgnoreCase(uri.getScheme())
      && "the-internet.herokuapp.com".equalsIgnoreCase(uri.getHost())
      && "/basic_auth".equals(uri.getPath());
}

Now replace the callback body with this guarded version:

network.onAuthRequired(details -> {
  String url = details.getRequest().getUrl();
  String requestId = details.getRequest().getRequestId();

  if (isApprovedChallenge(url)) {
    challengeCount.incrementAndGet();
    challengedUrl.complete(url);
    network.continueWithAuth(
        requestId, new UsernameAndPassword(user, password));
  } else {
    network.cancelAuth(requestId);
  }
});

Compare parsed URI components, not url.contains("trusted-host"). A malicious host can place trusted-looking text in its subdomain, path, or query. Require HTTPS, compare the normalized host exactly, and restrict the path when one account should unlock only one protected area.

Use continueWithAuthNoCredentials(requestId) only when you deliberately want the browser's normal credential behavior to proceed. Use cancelAuth(requestId) when the challenge is outside policy. Every blocked authentication request needs a decision, or the navigation can remain suspended.

Authentication may also be requested by a proxy. A proxy challenge and an origin challenge are not interchangeable, even when they appear during the same navigation. Scope proxy credentials separately, and never let a broad fallback send an application password to infrastructure. If your organization uses several test hosts, build an immutable mapping from exact origin to a dedicated credential object instead of a single default credential.

Treat redirects as new trust decisions. The initial target can redirect to a different origin before the authentication event occurs. Validate the URL supplied by the event, not merely the URL that the test originally passed to driver.get. This distinction is why event-level filtering is stronger than checking the test input once.

Verification: Change the approved host temporarily to example.com. The success assertion must fail and challengeCount must remain zero. Restore the-internet.herokuapp.com and confirm the test passes. This controlled failure proves the policy is active.

Step 5: selenium bidi authentication handler java tutorial reusable design

A reusable helper keeps security policy and protocol calls out of individual tests. Add this nested class or move it to your test-support package:

import java.net.URI;
import java.util.Objects;
import java.util.concurrent.atomic.AtomicInteger;
import java.util.function.Predicate;
import org.openqa.selenium.UsernameAndPassword;
import org.openqa.selenium.bidi.module.Network;
import org.openqa.selenium.bidi.network.ResponseDetails;

final class AuthenticationHandler {
  private final Network network;
  private final Predicate<URI> allowlist;
  private final UsernameAndPassword credentials;
  private final AtomicInteger handled = new AtomicInteger();

  AuthenticationHandler(
      Network network,
      Predicate<URI> allowlist,
      UsernameAndPassword credentials) {
    this.network = Objects.requireNonNull(network);
    this.allowlist = Objects.requireNonNull(allowlist);
    this.credentials = Objects.requireNonNull(credentials);
  }

  void register() {
    network.onAuthRequired(this::handle);
  }

  int handledCount() {
    return handled.get();
  }

  private void handle(ResponseDetails details) {
    URI uri = URI.create(details.getRequest().getUrl());
    String requestId = details.getRequest().getRequestId();

    if (allowlist.test(uri)) {
      handled.incrementAndGet();
      network.continueWithAuth(requestId, credentials);
    } else {
      network.cancelAuth(requestId);
    }
  }
}

Create and register it inside the open Network scope:

Predicate<URI> protectedPage = uri ->
    "https".equalsIgnoreCase(uri.getScheme())
        && "the-internet.herokuapp.com".equalsIgnoreCase(uri.getHost())
        && "/basic_auth".equals(uri.getPath());

AuthenticationHandler auth = new AuthenticationHandler(
    network, protectedPage, new UsernameAndPassword(user, password));
auth.register();

The handler owns neither the browser nor the Network lifecycle. The test fixture keeps that ownership visible. AtomicInteger is used because event callbacks are asynchronous, and it safely records observations across callback and test threads.

Keep callback work fast and deterministic. Do not call a slow secret service from the event consumer because the network request remains blocked while the callback decides. Fetch credentials during fixture setup, construct the handler, and then register it. If lookup must be dynamic, enforce a short timeout and cancel authentication on lookup failure.

Avoid a static handler shared by parallel tests. Each browser session has its own BiDi connection, request identifiers, and lifecycle. A test-local handler makes it impossible for one session's challenge to consume another session's credentials or counters. If you expose diagnostics, record only safe values such as host, path, request ID, and decision. Never log passwords or an entire credential object.

Verification: Replace the inline callback with the helper, navigate, and assert assertEquals(1, auth.handledCount()). The original page assertions must still pass.

Step 6: Verify Rejected Credentials

A success-only test can pass even if a previous browser state, proxy, or environment masks the challenge. Add an explicit wrong-password test:

@Test
void rejectsInvalidCredentials() {
  AtomicInteger challenges = new AtomicInteger();

  try (Network network = new Network(driver)) {
    network.onAuthRequired(details -> {
      int attempt = challenges.incrementAndGet();
      String requestId = details.getRequest().getRequestId();

      if (attempt == 1) {
        network.continueWithAuth(
            requestId, new UsernameAndPassword("admin", "wrong-password"));
      } else {
        network.cancelAuth(requestId);
      }
    });

    driver.get("https://the-internet.herokuapp.com/basic_auth");

    assertTrue(challenges.get() >= 1);
    assertTrue(driver.findElements(By.xpath("//p[contains(.,'Congratulations')]")).isEmpty());
  }
}

The attempt limit prevents an authentication loop. Some servers or browsers may emit another challenge after bad credentials. On the first event, provide the deliberately invalid pair. On a later event, cancel instead of resending the same secret forever.

Do not assert a browser-generated error page's exact wording. That text can vary by browser and version. Assert the stable business outcome: at least one challenge occurred and protected content was not displayed.

Verification: Run mvn -Dtest=BidiAuthenticationTest#rejectsInvalidCredentials test. It should pass without hanging. If it times out, confirm that every callback branch calls continueWithAuth, continueWithAuthNoCredentials, or cancelAuth.

Step 7: Make the Test CI-Ready

Move target and credentials into system properties with environment fallbacks. This makes local and CI invocation predictable:

private static String setting(String property, String environment, String fallback) {
  String value = System.getProperty(property);
  if (value == null || value.isBlank()) {
    value = System.getenv(environment);
  }
  return value == null || value.isBlank() ? fallback : value;
}

String target = setting(
    "basicAuthUrl", "BASIC_AUTH_URL",
    "https://the-internet.herokuapp.com/basic_auth");
String user = setting("basicAuthUser", "BASIC_AUTH_USER", "admin");
String password = setting("basicAuthPassword", "BASIC_AUTH_PASSWORD", "admin");

Invoke the test without placing the password in source:

mvn test \
  -DbasicAuthUrl="$BASIC_AUTH_URL" \
  -DbasicAuthUser="$BASIC_AUTH_USER" \
  -DbasicAuthPassword="$BASIC_AUTH_PASSWORD"

In a real repository, remove credential fallbacks and fail fast when a required secret is missing. The public demo defaults are convenient only for this tutorial. Mask secrets in CI, avoid printing the credential object, and use a dedicated account with the smallest possible permissions.

For remote execution, the Grid or cloud provider must return a usable webSocketUrl and proxy the BiDi WebSocket. Capability negotiation can succeed while the event channel is unavailable because of an older node or provider limitation. Test the same small authentication case before migrating a large suite.

Parallel CI needs one driver and one Network module per test worker. Do not reuse a mutable counter, future, or credential policy across sessions. Give the authentication test a realistic navigation timeout, but do not use a longer timeout to conceal a callback that failed to resolve a challenge. Capture safe diagnostics such as browser version, target host, challenge count, and whether the policy approved or canceled the request.

Run the protocol test early in an environment smoke stage. A failure then distinguishes BiDi transport or secret configuration problems from later application assertions. Once it passes, the rest of the authenticated UI suite can rely on the environment with much clearer failure ownership.

Verification: Run once with correct environment values and once with BASIC_AUTH_PASSWORD=wrong. The first run should reach protected content. The second should fail the positive test or pass the negative test, proving the secret source affects behavior.

Troubleshooting

Network construction fails or says the driver does not support BiDi -> Set webSocketUrl to true on ChromeOptions before creating the session. Upgrade Selenium, the browser, and the remote node together. Confirm your Grid vendor proxies the BiDi WebSocket.

The native authentication prompt appears and the callback never runs -> Register onAuthRequired before driver.get. Keep the Network instance open. Confirm the challenge is HTTP authentication, not an HTML login form or an operating-system dialog.

Navigation hangs after the event fires -> Resolve every intercepted challenge. Call continueWithAuth, continueWithAuthNoCredentials, or cancelAuth with details.getRequest().getRequestId(). Do not use a navigation ID or intercept ID as the request ID.

Valid credentials are rejected repeatedly -> Check whitespace in injected secrets, account realm, proxy authentication, and the target environment. Cap retries and cancel the second challenge while diagnosing. Never create an unbounded callback loop.

The handler works locally but not on Grid -> Inspect returned capabilities for webSocketUrl, align Selenium client and server versions, and verify WebSocket routing through load balancers. Run a single browser and single test before enabling parallel execution.

Credentials are offered to an unexpected request -> Parse the URI and require the intended HTTPS scheme, exact host, port if nonstandard, and protected path. Do not approve with a substring comparison. Create one Network instance per driver and keep handler state test-local.

Where To Go Next

You now have the authentication slice of the complete Selenium BiDi automation guide. Build outward from the same event-driven model:

Treat authentication, interception, logs, and network conditions as composable capabilities. Keep each listener narrowly scoped and close each module after the test so parallel sessions do not share state.

Interview Questions and Answers

Q: Why must an authentication handler be registered before navigation?

The server issues the authentication challenge during the navigation request. If the listener is registered after get, the relevant network.authRequired event may already have occurred and the request may be waiting for a response. Register first, navigate second, and keep the subscription alive through verification.

Q: What data connects onAuthRequired to continueWithAuth?

The callback receives ResponseDetails, whose RequestData contains the request ID. Pass details.getRequest().getRequestId() to continueWithAuth along with UsernameAndPassword. The request ID identifies the blocked network request that the browser must resume.

Q: Why filter the challenged URL?

A session can encounter authentication challenges from redirects, proxies, frames, or third-party resources. An unfiltered handler could release credentials to the wrong origin. Parse the URI and compare scheme, host, port, and path according to a deliberate allowlist.

Q: Is WebDriver BiDi authentication the same as filling a login form?

No. BiDi authentication handling answers protocol-level HTTP challenges such as Basic or Digest authentication when supported. A login form is regular DOM content and should be automated with locators, input actions, and application-level assertions.

Q: How do you prevent invalid credentials from causing an infinite loop?

Count challenges per test or request. Provide credentials only for the allowed attempt, then cancel later challenges and fail with useful diagnostics. A bounded policy prevents a server that keeps returning 401 from trapping the test.

Q: Why use try-with-resources for Network?

The BiDi Network module implements AutoCloseable. Closing it cleans up subscriptions and intercepts, which reduces leaked listeners and surprising behavior in later tests. Its lifetime should cover listener registration, navigation, and assertions.

Best Practices

  • Register listeners before the action that produces their events.
  • Parse and allowlist the challenged URI before supplying any credential.
  • Read secrets from a protected runtime store, not source control or test reports.
  • Use a dedicated low-privilege test identity and rotate it like any other secret.
  • Bound authentication attempts, then cancel and fail clearly.
  • Assert protected application content plus event evidence. Page load completion alone is weak proof.
  • Keep Network, counters, and futures local to one driver session.
  • Close the BiDi module and quit the driver even when assertions fail.
  • Pin compatible client and server versions, then test upgrades in a small protocol suite.
  • Keep protocol authentication separate from form login helpers because they fail in different ways.

Conclusion

This selenium bidi authentication handler java tutorial uses the standards-based network event path: enable webSocketUrl, create Network, subscribe to onAuthRequired, inspect the challenged URI, and resume the exact request with continueWithAuth. The important production details are registration order, strict credential scope, bounded retries, stable assertions, and cleanup.

Run the positive and negative tests against a controlled environment, then add error capture or request interception from the linked BiDi series. You will have a small authentication component that is easier to audit, diagnose, and reuse than URL-embedded credentials or fragile prompt workarounds.

Interview Questions and Answers

Explain the Selenium BiDi authentication flow in Java.

Enable BiDi during session creation and construct the Network module. Register an onAuthRequired consumer before navigation. The consumer validates the challenged URL and calls continueWithAuth with the request ID and UsernameAndPassword, after which the browser resumes the blocked request.

Why is the request ID important in continueWithAuth?

The authentication event can occur for any of several concurrent requests. The request ID identifies the exact blocked request to resume. Passing another identifier cannot correctly resolve that challenge and may leave navigation suspended.

How would you prevent credential leakage from an authentication handler?

Parse the challenged URL as a URI and enforce an allowlist for HTTPS scheme, exact host, expected port, and permitted path. Cancel challenges outside that policy. Keep secrets outside source control and scope the handler to one driver session.

What is the difference between continueWithAuthNoCredentials and cancelAuth?

continueWithAuthNoCredentials lets the request proceed without programmatically supplied credentials, leaving normal browser behavior available. cancelAuth explicitly cancels the authentication attempt. Choose based on policy, but always resolve the blocked challenge.

How would you test invalid credentials without creating a loop?

Count authentication events and supply the invalid credentials only on the first challenge. Cancel any later challenge, then assert that protected content is absent and at least one challenge occurred. Avoid exact assertions against browser-generated error text.

Why should Network be closed after the test?

Network owns BiDi subscriptions and intercepts and implements AutoCloseable. Closing it prevents listeners from leaking into later activity and makes the test lifecycle explicit. Use try-with-resources around registration, navigation, and verification.

Frequently Asked Questions

How do I handle Basic Auth with Selenium BiDi in Java?

Enable the webSocketUrl capability, create org.openqa.selenium.bidi.module.Network, and register onAuthRequired before navigation. In the callback, pass the challenged request ID and a UsernameAndPassword object to continueWithAuth.

Do I need to put the username and password in the URL?

No. A BiDi authentication handler supplies credentials in response to the browser's protocol-level challenge. This avoids unreliable userinfo URLs and lets you restrict which origin may receive the credentials.

Why does onAuthRequired not fire in my Selenium test?

The session may not have BiDi enabled, the listener may have been registered after navigation, or the UI may be an HTML form rather than an HTTP authentication challenge. Also confirm that a remote Grid returns and proxies the BiDi webSocketUrl.

Can the Selenium BiDi handler automate an HTML login form?

No. Use WebDriver locators and element interactions for an HTML form. The Network authentication handler is for browser-level HTTP authentication challenges exposed through WebDriver BiDi.

How should I protect credentials in CI?

Store them in the CI platform's secret manager, inject them as masked environment variables, and never print them. Use a dedicated low-privilege account and restrict the handler to the exact HTTPS origin and path.

How do I stop repeated authentication challenges?

Track attempts and provide credentials only for the allowed attempt. Cancel a later challenge with cancelAuth and fail the test with a clear diagnostic instead of resending invalid credentials indefinitely.

Does Selenium BiDi authentication work on Grid?

It can work when the Grid node supports WebDriver BiDi and the infrastructure proxies the returned WebSocket endpoint. Verify webSocketUrl negotiation with one small test before moving the full suite.

Related Guides