How to Configure Connection Timeouts and Retries in Zendriver

Configure connection timeouts and retries in Zendriver by setting browser_connection_timeout and browser_connection_max_tries in the Config class for initial CDP connection polling, and modify the PING_TIMEOUT constant in the connection module for WebSocket keep-alive behavior.

Zendriver, the open-source Python library maintained at cdpdriver/zendriver, provides granular control over Chrome DevTools Protocol (CDP) connection resilience. Understanding how to configure connection timeouts and retries in Zendriver ensures stable browser automation across varying network conditions, from local development to resource-constrained CI pipelines.

Understanding Zendriver's Two-Layer Connection Architecture

Zendriver manages connection stability at two distinct architectural layers. The initial connection layer handles the HTTP polling loop that waits for the CDP WebSocket endpoint to become available immediately after launching the browser process. The WebSocket layer maintains the persistent CDP connection via the websockets library, governed by low-level ping timeouts that detect stale or dropped connections.

Configuring Initial Connection Timeouts and Retries

The Config class in zendriver/core/config.py exposes two critical parameters that control the initial connection polling behavior during browser startup.

Setting browser_connection_timeout

The browser_connection_timeout parameter, defined in Config.__init__ at line 46 of zendriver/core/config.py, specifies the delay in seconds between polling attempts when waiting for the CDP WebSocket URL to become reachable. According to the source code in zendriver/core/browser.py (lines 77-81), the Browser.start method implements a retry loop that sleeps for this duration between each connection test.

Setting browser_connection_max_tries

The browser_connection_max_tries parameter, defined at line 47 of zendriver/core/config.py, sets the maximum number of retry attempts before Zendriver raises an exception and initiates browser process teardown. As implemented in the retry loop at zendriver/core/browser.py (lines 77-81), the code attempts to call test_connection() up to this limit, breaking only on success.


# example_01.py – adjust timeout & retry count via Config

import asyncio
from zendriver.core.browser import Browser
from zendriver.core.config import Config

async def main():
    # 0.5 s between attempts, give up after 5 tries

    cfg = Config(
        browser_connection_timeout=0.5,   # seconds to sleep between retries

        browser_connection_max_tries=5,   # maximum retry attempts

    )
    async with await Browser.create(cfg) as browser:
        await browser.get("https://example.com")
        print("Page loaded!")

asyncio.run(main())

Tuning WebSocket Ping Timeouts

Beyond the initial handshake, the persistent CDP WebSocket connection uses a separate timeout mechanism defined at the module level in zendriver/core/connection.py.

Modifying PING_TIMEOUT

At line 39 of zendriver/core/connection.py, the module-level constant PING_TIMEOUT defines the low-level WebSocket ping timeout in seconds passed to websockets.connect (lines 23-27). The default value is 900 seconds (15 minutes), which controls how long the underlying websockets library waits for ping responses before considering the connection dead.

To override this value, import the module and assign a new value to PING_TIMEOUT before calling Browser.create(), as the constant is read at connection establishment time.


# example_02.py – change the low‑level WebSocket ping timeout

import asyncio
from zendriver.core.connection import PING_TIMEOUT
from zendriver.core.browser import Browser

async def main():
    # Reduce ping timeout to 30 seconds (instead of the default 900 s)

    global PING_TIMEOUT
    PING_TIMEOUT = 30

    async with await Browser.create() as browser:
        await browser.get("https://example.org")
        print("Connected with shortened ping timeout.")

asyncio.run(main())

Optimizing for CI and Resource-Constrained Environments

For continuous integration pipelines where containers may start slower or network latency varies, combine both configuration strategies to minimize startup delays while maintaining connection stability.


# example_03.py – combine both settings for a fast start‑up in CI environments

import asyncio
from zendriver.core.browser import Browser
from zendriver.core.config import Config
from zendriver.core.connection import PING_TIMEOUT

async def main():
    # Faster retries + shorter ping timeout

    PING_TIMEOUT = 10          # seconds

    cfg = Config(browser_connection_timeout=0.2, browser_connection_max_tries=3)

    async with await Browser.create(cfg) as browser:
        await browser.get("https://httpbin.org/get")
        print("Done in CI!")

asyncio.run(main())

Summary

  • Configure initial connection resilience via Config.browser_connection_timeout and Config.browser_connection_max_tries in zendriver/core/config.py to control polling behavior during browser startup.
  • Adjust WebSocket health monitoring by modifying the PING_TIMEOUT constant in zendriver/core/connection.py (line 39) before instantiating any Browser objects.
  • The retry loop in zendriver/core/browser.py (lines 77-81) implements the polling logic that respects your Config settings, sleeping between attempts and raising an exception only after exhausting browser_connection_max_tries.

Frequently Asked Questions

What is the default value for PING_TIMEOUT in Zendriver?

According to the source code in zendriver/core/connection.py (line 39), the default PING_TIMEOUT is 900 seconds (15 minutes). This value is passed directly to the websockets.connect call to determine how long the underlying library waits for ping responses before considering the CDP connection dead.

How does Zendriver handle connection failures after exhausting the maximum retry attempts?

When the number of connection attempts exceeds browser_connection_max_tries, Zendriver raises an exception and initiates browser process teardown. As implemented in the retry loop at zendriver/core/browser.py (lines 77-81), the code repeatedly calls test_connection() until success; if the final attempt fails, the exception propagates and the browser process is terminated to prevent resource leaks.

Can I change the WebSocket ping timeout after creating a Browser instance?

No, you cannot change PING_TIMEOUT after instantiating a Browser because the value is read at module import time and passed to websockets.connect during the initial connection establishment in zendriver/core/connection.py (lines 23-27). To use a custom timeout, you must assign a new value to zendriver.core.connection.PING_TIMEOUT before calling Browser.create().

Where are the connection retry settings defined in the Zendriver source code?

The connection retry settings are defined in the Config class within zendriver/core/config.py. Specifically, browser_connection_timeout is defined at line 46 and browser_connection_max_tries at line 47 in the Config.__init__ method. These values are consumed by the Browser.start method in zendriver/core/browser.py (lines 77-81), which implements the polling loop that establishes the initial CDP connection.

Have a question about this repo?

These articles cover the highlights, but your codebase questions are specific. Give your agent direct access to the source. Share this with your agent to get started:

Share the following with your agent to get started:
curl -s "https://instagit.com/install.md"

Works with
Claude Codex Cursor VS Code OpenClaw Any MCP Client

Maintain an open-source project? Get it listed too →