nodriver is an open-source, asynchronous Python library that automates Chrome and other Chromium-based browsers by talking to them directly over the Chrome DevTools Protocol (CDP). It does not use Selenium or the chromedriver binary, and its maintainer presents it as the successor to undetected-chromedriver.
How nodriver controls the browser
Most Python browser automation has gone through Selenium. Selenium sends WebDriver commands to a driver program such as chromedriver, which then controls the browser. The nodriver README removes that middle layer: its feature list opens with "No chromedriver binary or Selenium dependency" and the tagline "No more webdriver, no more selenium."
Instead, nodriver launches a locally installed browser and connects to its DevTools endpoint. The CDP documentation describes that endpoint: a browser started with remote debugging enabled exposes a WebSocket URL at /json/version, and a client sends protocol commands over it. The nodriver source reads that WebSocket URL and holds the connection itself. The README says the project works with Chromium, Chrome, Edge, and Brave, and lets users call any CDP domain, method, or event directly.
A few other design choices are documented:
- Async API. The README calls the library "fully asynchronous," unlike undetected-chromedriver. Scripts are written with
asyncandawait. - Fresh profiles. By default each run creates a temporary profile directory and removes it on exit, unless the user points it at an existing profile.
- Launch defaults. The same config file passes a fixed set of Chrome command-line flags, such as skipping the first-run screen, and adds
--headless=newwhen headless mode is requested. - Convenience helpers. Element lookup by CSS selector, XPath, or visible text, including inside iframes, plus cookie saving and loading so a login does not have to be repeated.
The package is published on PyPI as nodriver, requires Python 3.9 or later, and is licensed under the GNU Affero General Public License v3.0. The current release at the time of writing is 0.50.3.
What its documentation claims
The nodriver documentation is open about the goal. It says the package is optimized "to stay undetected for most anti-bot solutions" and that talking to the browser directly gives better resistance against web application firewalls. Those are the maintainer's own claims. The project does not publish a test method or results that would let a reader check them.
The README also documents where its own features raise the risk of detection. An optional expert mode disables web security and origin trials and forces shadow roots open, and the README warns that this "makes you more detectable." It also documents a helper built to find and click a verification checkbox. That tells a defender the tool is designed to interact with challenge pages, not only to read public content.
nodriver and undetected-chromedriver
undetected-chromedriver is the same author's earlier project. Its README describes it as an "optimized Selenium Chromedriver patch": it downloads chromedriver, patches it, and keeps the Selenium programming model. A 3.4.0 changelog entry says the anti-detection approach moved from removing and renaming variables to stopping them from being injected in the first place. That project is licensed under GPL-3.0.
nodriver goes a step further. Instead of patching the WebDriver path, it drops it. The README calls nodriver "the official successor" and includes a utility to convert a running undetected-chromedriver instance into a nodriver browser, so existing scripts can move over gradually.
The older README contains a limit that applies to both tools. In bold, it says the package "DOES NOT hide your IP address," and that a script run from a datacenter or from a home connection with a poor reputation is unlikely to pass. Changing how a browser is driven does nothing to the network it runs on.
The patched Chromium guide covers how driver-level, framework-level, and binary-level changes differ.
What removing WebDriver does and does not change
The WebDriver specification defines navigator.webdriver as a report that the browser is under WebDriver remote control. nodriver does not start a WebDriver session, so a check that looks only for WebDriver or chromedriver artifacts is looking for a control path this library does not use. That is the same weakness a single-property rule has against Playwright Stealth.
Other evidence is still there:
- CDP-driven automation. The browser is still controlled through a debugging protocol. The client, the commands it sends, and the order it sends them in can leave traces that depend on the Chromium version and the kind of observation.
- Environment consistency. A stock browser on a server, a headless session, or a fresh profile with no history still has to agree with its claimed platform, screen, fonts, and graphics. nodriver does not generate fingerprints the way an antidetect browser does.
- Network consistency. IP reputation, connection properties, and whether the request headers match the browser's claims are unchanged by the automation library, as the undetected-chromedriver README itself admits.
- Behavior. Navigation order, timing, form completion, and repetition across sessions reflect the script, not the transport.
None of these is proof on its own. Legitimate tools use CDP too, including test runners and monitoring systems. The browser automation detection guide explains how to combine evidence from layers that fail in different ways.
What to do with it as a defender
Treat nodriver as a test case, not a signature. Add a pinned nodriver version to your automation regression cohort next to stock Selenium and Playwright, and record which evidence changes between them. If your detection only works because chromedriver was present, nodriver will show it.
Decide the response by route and action. A nodriver session reading a public page and one repeatedly submitting a signup form carry different risk. Keep an allow path for your own and your partners' approved automation, and log the evidence behind each decision so a false positive can be reversed and the test rerun when nodriver or Chrome changes.
