How Selenium WebDriver works: client, protocol, driver, browser
Selenium WebDriver is an API for driving a browser the way a user would: open a page, find an element, click, type text, read a result. The test (Java code) never touches the browser directly; it goes through a chain:
- the client library (selenium-java) turns calls like
driver.get(...) and element.click() into commands;
- the W3C WebDriver protocol is the standard by which commands travel as HTTP requests with JSON (request and response);
- the browser driver (chromedriver, geckodriver, msedgedriver) is a separate process that receives those HTTP requests and controls the browser;
- the browser performs the action and returns the result the other way.
All of this is a session: new ChromeDriver() creates it, driver.quit() ends it, closes the windows and stops the driver process. close() only closes the current window.
WebDriver driver = new ChromeDriver();
try {
driver.get("https://example.com");
String title = driver.getTitle();
} finally {
driver.quit();
}
Because the protocol is standardised, the same test can run on Chrome, Firefox, Edge or Safari by changing only the driver class or the options. Selenium 4 speaks only the W3C dialect: the old JSON Wire Protocol and Selenium RC are history, not options.
A limit of the classic model: it is request-response. The browser cannot tell the test by itself "a console error just appeared"; events need a two-way protocol (WebDriver BiDi, a separate article).
Selenium Manager, browser options and RemoteWebDriver
Drivers used to be downloaded by hand and pointed to via System.setProperty("webdriver.chrome.driver", ...), or pulled in with WebDriverManager. Now Selenium Manager does it; it is built into Selenium since 4.6:
- it detects the installed browser version, picks and downloads the matching driver, and caches it (by default
~/.cache/selenium);
- since 4.11 (Chrome), 4.12 (Firefox) and 4.14 (Edge) it can also download the browser itself when it is missing;
- it is configured by environment variables (
SE_CACHE_PATH, SE_OFFLINE) or an se-config.toml file; in Java, the cache and offline mode cannot be set through browser options.
So the typical code is just new ChromeDriver(). If CI has no network, the driver and browser must be prepared in advance (an image, a cache, an explicit driver path); otherwise the session will not be created.
Browser options. In Selenium 4 settings are passed with the classes ChromeOptions, FirefoxOptions, EdgeOptions; DesiredCapabilities as the recommended way is a Selenium 3 legacy.
ChromeOptions options = new ChromeOptions();
options.addArguments("--headless=new", "--window-size=1920,1080");
options.setPageLoadStrategy(PageLoadStrategy.EAGER);
WebDriver driver = new ChromeDriver(options);
Useful options: window size (in headless mode it is small otherwise and breaks responsive layouts), pageLoadStrategy (normal waits for the full load, eager for DOMContentLoaded, none does not wait), a proxy, acceptInsecureCerts, a profile and file download settings.
RemoteWebDriver connects to a remote node (Selenium Grid, a Docker container, a cloud platform) by URL with the same options:
WebDriver driver = new RemoteWebDriver(URI.create("http://localhost:4444").toURL(), options);
The rest of the test does not change: that is the point of the shared WebDriver interface.