How to Pass Custom Arguments to the Browser Executable in Zendriver

You can pass custom arguments to the Chromium browser executable in zendriver using the browser_args parameter in Browser.create(), setting the browser_args attribute on a Config instance, or calling the add_argument() method for incremental additions.

The zendriver library automates Chromium-based browsers by constructing command-line flags through a centralized configuration system. When you need to enable specific Chrome features, disable security restrictions, or tune performance settings, you must inject custom flags into the browser launch sequence.

Understanding the Config Class Architecture

The Config class in zendriver/core/config.py serves as the command-line builder for the browser process. When Browser.start() launches the executable, it invokes the Config instance as a callable (Config.__call__), which returns a list of strings representing the final command-line arguments.

The __call__ method (lines 190–235) constructs the argument list by:

  1. Copying default browser arguments
  2. Appending managed flags (user data directory, headless mode, user agent, etc.)
  3. Extending with custom arguments from self._browser_args while filtering duplicates

Three Methods to Pass Custom Browser Arguments

Using the browser_args Parameter in Browser.create

The simplest approach passes a list of strings directly to the factory method. In zendriver/core/browser.py, the Browser.create() method accepts a browser_args parameter that gets forwarded to the Config constructor.

import zendriver

# Enable remote debugging and disable GPU acceleration

custom_flags = ["--remote-debugging-port=9222", "--disable-gpu"]

browser = await zendriver.Browser.create(
    headless=False,
    browser_args=custom_flags
)

Setting Config.browser_args Directly

For advanced scenarios requiring explicit Config manipulation, instantiate Config separately and populate its browser_args attribute before passing it to Browser.create.

from zendriver.core.config import Config
import zendriver

cfg = Config()
cfg.browser_args = ["--disable-features=AudioServiceOutOfProcess", "--disable-extensions"]

browser = await zendriver.Browser.create(config=cfg)

Adding Arguments Incrementally with Config.add_argument

The Config.add_argument() method in zendriver/core/config.py allows appending single flags while enforcing validation rules. This method rejects arguments that conflict with dedicated Config attributes.

from zendriver.core.config import Config

cfg = Config()
cfg.add_argument("--disable-background-networking")
cfg.add_argument("--disable-popup-blocking")

# These would raise ValueError because they have dedicated Config fields:

# cfg.add_argument("--headless")  # Use cfg.headless = True instead

# cfg.add_argument("--user-data-dir=/tmp")  # Use cfg.user_data_dir instead

How Custom Arguments Are Merged with Defaults

When Browser.start() invokes the Config callable, the following merge logic executes:


# From zendriver/core/config.py

def __call__(self) -> list[str]:
    args = self._default_browser_args.copy()
    args += ["--user-data-dir=%s" % self.user_data_dir]
    # ... other managed flags ...

    
    if self._browser_args:
        # Custom args extend the list, duplicates filtered

        args.extend([arg for arg in self._browser_args if arg not in args])
    return args

Custom arguments always appear after the default set in the final command list. The implementation filters exact duplicates to prevent conflicting flags, but note that flags with different values (e.g., --window-size=800,600 vs --window-size=1200,800) are treated as distinct strings and both would be included.

Important Restrictions on Custom Arguments

The add_argument() method specifically blocks flags that have dedicated Config attributes to prevent configuration conflicts. According to the source in zendriver/core/config.py, you cannot use add_argument() for:

  • --headless (use cfg.headless)
  • --user-data-dir (use cfg.user_data_dir)
  • --no-sandbox (use cfg.no_sandbox)
  • --lang (use cfg.lang)
  • --user-agent (use cfg.user_agent)
  • --window-size (use cfg.window_size)
  • --proxy-server (use cfg.proxy)

Attempting to add these via add_argument() raises a ValueError with instructions to use the corresponding attribute instead.

Complete Code Examples

Passing a List of Custom Flags

import zendriver
import asyncio

async def main():
    # Configure performance and security flags

    browser_args = [
        "--disable-gpu",
        "--disable-dev-shm-usage",
        "--disable-setuid-sandbox",
        "--remote-debugging-port=9222"
    ]
    
    browser = await zendriver.Browser.create(
        headless=True,
        browser_args=browser_args
    )
    
    page = await browser.get("https://example.com")
    await browser.stop()

asyncio.run(main())

Adding Arguments After Config Initialization

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

async def main():
    cfg = Config()
    cfg.headless = False
    cfg.window_size = (1920, 1080)
    
    # Incrementally add experimental flags

    cfg.add_argument("--enable-experimental-web-platform-features")
    cfg.add_argument("--disable-background-timer-throttling")
    
    browser = await zendriver.Browser.create(config=cfg)
    page = await browser.get("https://example.com")
    await browser.stop()

asyncio.run(main())

Combining Both Approaches

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

async def main():
    # Base configuration with specific overrides

    cfg = Config()
    cfg.add_argument("--disable-extensions")
    cfg.add_argument("--disable-background-networking")
    
    # Additional runtime flags passed via browser_args

    extra_args = ["--disable-popup-blocking", "--disable-translate"]
    
    browser = await zendriver.Browser.create(
        config=cfg,
        browser_args=extra_args
    )
    
    page = await browser.get("https://example.com")
    await browser.stop()

asyncio.run(main())

Summary

  • Primary mechanism: Pass a list of strings to the browser_args parameter in Browser.create() (defined in zendriver/core/browser.py).
  • Advanced configuration: Instantiate Config from zendriver/core/config.py and set cfg.browser_args directly or use cfg.add_argument() for incremental additions.
  • Merge behavior: Custom arguments are appended after default flags in Config.__call__(), with exact duplicates filtered to prevent conflicts.
  • Validation: add_argument() blocks flags that have dedicated Config attributes (e.g., --headless, --user-data-dir) to ensure consistent configuration management.

Frequently Asked Questions

Can I override default browser arguments like --headless using browser_args?

No, you should use the dedicated Config attributes instead. According to the source code in zendriver/core/config.py, flags like --headless, --user-data-dir, --no-sandbox, and --window-size are managed through specific properties (cfg.headless, cfg.user_data_dir, etc.). The add_argument() method explicitly rejects these flags with a ValueError to prevent configuration conflicts.

What happens if I pass duplicate arguments in browser_args?

The Config.__call__ method filters out exact duplicates when building the final command line. In zendriver/core/config.py, the implementation extends the argument list with [arg for arg in self._browser_args if arg not in args], ensuring that if a flag already exists in the default set, your custom version is ignored. However, flags with different values (like different window sizes) are treated as distinct strings and both would appear in the final command.

Can I modify browser arguments after creating the Config object but before launching the browser?

Yes, you can incrementally add arguments using the add_argument() method or by modifying the browser_args list directly. As shown in zendriver/core/config.py, the add_argument() method appends to self._browser_args, and since Config is not frozen, you can modify this list until you pass the config to Browser.create(). This is useful for conditionally adding flags based on runtime logic before launching the browser process.

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 →