# How to Pass Custom Arguments to the Browser Executable in Zendriver

> Learn how to pass custom arguments to the browser executable in zendriver using browser_args. Explore multiple methods for efficient browser control and customization.

- Repository: [CDP Driver/zendriver](https://github.com/cdpdriver/zendriver)
- Tags: how-to-guide
- Published: 2026-02-27

---

**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`](https://github.com/cdpdriver/zendriver/blob/main/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`](https://github.com/cdpdriver/zendriver/blob/main/zendriver/core/browser.py), the `Browser.create()` method accepts a `browser_args` parameter that gets forwarded to the `Config` constructor.

```python
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`.

```python
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`](https://github.com/cdpdriver/zendriver/blob/main/zendriver/core/config.py) allows appending single flags while enforcing validation rules. This method rejects arguments that conflict with dedicated `Config` attributes.

```python
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:

```python

# 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`](https://github.com/cdpdriver/zendriver/blob/main/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

```python
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

```python
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

```python
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`](https://github.com/cdpdriver/zendriver/blob/main/zendriver/core/browser.py)).
- **Advanced configuration**: Instantiate `Config` from [`zendriver/core/config.py`](https://github.com/cdpdriver/zendriver/blob/main/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`](https://github.com/cdpdriver/zendriver/blob/main/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`](https://github.com/cdpdriver/zendriver/blob/main/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`](https://github.com/cdpdriver/zendriver/blob/main/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.