RemoteWebDriver BiDirectional API

Page being translated from English to Portuguese. Do you speak Portuguese? Help us to translate it by sending us pull requests!

The following examples demonstrate how to leverage BiDi APIs with Remote WebDriver.

Register Basic Auth

Some applications make use of browser authentication to secure pages. With Selenium, you can automate the input of basic auth credentials whenever they arise.


  @Test
  public void testBasicAuth() {
    AtomicReference<DevTools> devToolsAtomicReference = new AtomicReference<>();

    driver = new Augmenter().addDriverAugmentation("chrome",
                                                   HasAuthentication.class,
                                                   (caps, exec) -> (whenThisMatches, useTheseCredentials) -> {
                                                     devToolsAtomicReference.get()
                                                       .createSessionIfThereIsNotOne();
                                                     devToolsAtomicReference.get().getDomains()
                                                       .network()
                                                       .addAuthHandler(whenThisMatches,
                                                                       useTheseCredentials);

                                                   }).augment(driver);

Mutation Observation

Mutation Observation is the ability to capture events via WebDriver BiDi when there are DOM mutations on a specific element in the DOM.

    AtomicReference<WebDriver> augmentedDriver = new AtomicReference<>();
    CountDownLatch latch = new CountDownLatch(1);

    Augmenter augmenter = new Augmenter();

    driver = augmenter.
      addDriverAugmentation("chrome", HasLogEvents.class, (caps, exec) -> new HasLogEvents() {
        @Override
        public <X> void onLogEvent(EventType<X> kind) {
          kind.initializeListener(augmentedDriver.get());
        }
      }).augment(driver);

    DevTools devTools = ((HasDevTools) driver).getDevTools();
    devTools.createSession();

    if (driver instanceof HasLogEvents) {
      augmentedDriver.set(driver);
    } else {
      throw new Exception("Not an instance of HasLogEvents");
    }

    ((HasLogEvents) driver).onLogEvent(domMutation(mutation -> {

Listen to console.log events

Listen to the console.log events and register callbacks to process the event.

  }

  @Test
  public void testConsoleLogListener() throws InterruptedException {
    CountDownLatch latch = new CountDownLatch(4);
    driver = new Augmenter().augment(driver);
    DevTools devTools = ((HasDevTools) driver).getDevTools();
    devTools.createSession();

    // Use as per Devtools version
    devTools.send(org.openqa.selenium.devtools.v85.runtime.Runtime.enable());
    devTools.send(Log.enable());

    // https://chromedevtools.github.io/devtools-protocol/tot/Console/ states that post deprecation either Runtime or Log domain is to be used
    // Depending on the implementation, events from either of the domains can be fired for console logs.

    devTools.addListener(Log.entryAdded(),
                         logEntry -> {
                           System.out.println("log: " + logEntry.getText());
                           System.out.println("level: " + logEntry.getLevel());
                           latch.countDown();
                         });

Actions causing JS exceptions

  }

  @Test
  public void testJsExceptionListener() throws Exception {
    driver = new Augmenter().augment(driver);
    DevTools devTools = ((HasDevTools) driver).getDevTools();
    devTools.createSession();

Network Interception

If you want to capture network events coming into the browser and you want manipulate them you are able to do it with the following examples.

    futureJsExc.get(5, TimeUnit.SECONDS);
    Assertions.assertEquals(1, jsExceptionsList.size());
  }

  @Test
  public void testNetworkInterceptor() {
    driver = new Augmenter().augment(driver);
    DevTools devTools = ((HasDevTools) driver).getDevTools();
    devTools.createSession();

    // Intercept and change response if the request uri contains "google"
    try (NetworkInterceptor interceptor = new NetworkInterceptor(
      driver,
      Route.matching(req -> req.getUri().contains("google"))