nodriver is a Python async browser automation library using Chrome DevTools Protocol (CDP). It is the official successor to undetected-chromedriver.
- Provide undetectable browser automation
- Bypass anti-bot detection systems
- Offer a clean, async/await-based API
- Support headless and headful operation
-
Browser (
nodriver/core/browser.py)- Manages Chrome/Chromium process lifecycle
- Handles browser-level configuration and settings
- Tracks tabs/targets
- Uses
_update_targets_lockfor thread-safe target list modifications
-
Tab/Connection (
nodriver/core/tab.py,nodriver/core/connection.py)Connection: Base class handling WebSocket communication with CDPTab: Extends Connection, represents a browser tab/page- Event-driven architecture with handler registration
- Async message passing via WebSocket
-
Element (
nodriver/core/element.py)- Represents DOM elements
- Provides interaction methods (click, type, etc.)
- Position calculation and visibility checks
-
Utilities (
nodriver/core/util.py)- ProxyForwarder for SOCKS5 proxy support
- Port management
- Browser instance registry
- Cleanup functions
- Heavily uses
asynciofor all I/O operations - Critical sections protected by locks:
Browser._update_targets_lock- protectsself.targetslistConnection._connection_lock- protects WebSocket connection stateConnection.mapper- protected for concurrent transaction access
Browser -> Connection -> WebSocket -> Chrome DevTools Protocol
|
+-> Transaction (Future-based request/response)
+-> Event Handlers (callback-based events)
None currently known.
-
Bare Exception Handlers (Low Priority)
connection.py:106-has_exception()catches all exceptionsconnection.py:160-EventTransaction.__init__()silently swallows parent init failurestab.py:1747- File cleanup catches all exceptions
These are generally defensive but could hide bugs. Consider catching specific exceptions.
-
Broad Exception Catches
- Several
except (Exception,)clauses that log but continue - Most are intentional for robustness, but review if errors seem hidden
- Several
-
Comment-Indicated Issues
connection.py:430- Intentionally broad exception catch with comment "as broad as possible"- No other TODO/FIXME/HACK comments found
- Handler registration in
Connection._register_handlers()is complex and intentionally permissive - Target updates now use proper locking (previously had race conditions)
- Browser stop() now has proper timeouts (5s for terminate, 3s for kill)
Status: Active (Sep 2025) Quality: Production-grade improvements Key Features:
- Browser context support (
browser_context_id) - Enhanced tab attributes (
.url,.target_id,.browser_context_id) - Click count parameter for double/triple clicks
- Improved
flash_point()accuracy - Race condition fixes in transaction completion
- ProxyForwarder exposed on Tab class
- Session ID support
Applied to This Fork:
- ✅ Race condition fixes (transaction completion, domain removal)
- ✅
click_countparameter - ✅ Improved
flash_point()positioning - ✅
tab.urlproperty - ❌ Browser context support (not needed yet)
- ❌ ProxyForwarder on Tab (not needed yet)
Status: Last updated Aug 2024 Key Features:
mouse_move_random()- random position within element boundssend_keys_random()- variable delay between keystrokes- Anti-detection through human-like behavior
Applied to This Fork:
- ✅ Both randomization methods
Status: Active (Oct 2025) Key Features:
- Shadow root workaround (fallback document retrieval)
- Cookie access edge case handling
Applied to This Fork:
- ❌ Not applied yet (low priority, defensive programming)
Status: Active (Oct 2025) - Feature branch only Key Features:
- HTTP/HTTPS proxy authentication with username/password
- Custom SSL context support
Applied to This Fork:
- ❌ Not needed (only if authenticated proxies required)
Status: Active (Sep 2025) Key Features:
- Selenium-compatible Element methods
box_model(),size(),location(),rect()is_displayed(),is_enabled(),is_selected(),is_clickable()
Applied to This Fork:
- ❌ Not needed (nice-to-have for Selenium migration)
If you need:
- Browser isolation/multi-session: Use isaiah-rps browser context support
- Authenticated proxies: Use tcortega proxy auth branch
- Selenium compatibility: Use boludoz element methods
- Shadow DOM edge cases: Use max32002 workaround
- Connection handler domain removal (concurrent
_register_handlers()calls) - Transaction completion (duplicate replies causing
InvalidStateError) - Target list modifications (proper locking with
_update_targets_lock) - Browser stop() method (concurrent access during shutdown)
browser.stop()simplified with proper timeouts- Registry cleanup to allow garbage collection
- Removed pointless retry loops
- Catch only expected exceptions (fail fast on bugs)
- Background tasks now tracked with
add_done_callback() - Uses
get_running_loop()instead of deprecatedget_event_loop() - Exceptions properly logged instead of silently lost
tab.urlproperty for direct URL accessclick_countparameter for double/triple clicks- Improved
flash_point()accuracy mouse_move_random()andsend_keys_random()for anti-detection
Per user's coding guidelines:
- Fail fast - avoid catching exceptions unless necessary
- Fatal errors - programming/logic errors should crash, not be hidden
- Expected exceptions only - catch specific exceptions, not broad
Exception - No error message wrapping - tracebacks are useful, don't obscure them
- Follow PEP 8 with E305/E306 (blank lines)
- DRY and YAGNI principles
- Comments for clarity, not obvious explanations
- No historical/refactoring notes in comments
- Never include attribution in commit messages
- Use locks for shared state (
self.targets,self.mapper) - Track async tasks with
add_done_callback()for exception handling - Use
asyncio.wait()with proper task management (cancel pending) - Avoid fire-and-forget
create_task()without tracking
- Concurrent tab creation/destruction - Stresses target list locking
- Browser stop during active operations - Tests cleanup robustness
- Handler registration/removal during events - Tests domain management
- Multiple simultaneous CDP commands - Tests transaction handling
- Proxy forwarding under load - Tests socket handling
- Shadow DOM elements may fail document queries (workaround available in max32002 fork)
- Cookie-protected pages may need special handling
- Browser crash during operations may leave orphaned processes
- Proxy connections may fail silently during shutdown (expected, logged at debug level)
- Consider applying max32002's shadow root workaround if users report issues
- Add browser context support if multi-session isolation needed
- Implement proxy authentication if enterprise use case emerges
- Add Selenium-compatible methods if migration users request them
Watch upstream (ultrafunkamsterdam/nodriver) for:
- CDP protocol updates
- New anti-detection techniques
- Browser compatibility changes
- Security fixes
Watch active forks for:
- Bug fixes that haven't been submitted upstream
- Feature additions that gain traction
- Race conditions or stability improvements
- Upstream: https://github.com/ultrafunkamsterdam/nodriver
- Chrome DevTools Protocol: https://chromedevtools.github.io/devtools-protocol/
- Active Forks:
- isaiah-rps: https://github.com/isaiah-rps/nodriver
- Connor9994: https://github.com/Connor9994/nodriver
- max32002: https://github.com/max32002/nodriver
- tcortega: https://github.com/tcortega/nodriver
- boludoz: https://github.com/boludoz/nodriver