unclecode/crawl4ai · error · RuntimeError

Unsupported browser type: {browser_type}

Error message

Unsupported browser type: {browser_type}

What it means

RuntimeError from get_browser_executable_path (utils.py) when browser_type is not one of chromium/firefox/webkit. The dict lookup reassigns browser_type to None for unknown keys and the falsy check raises. Note the message interpolates the already-overwritten variable, so it prints 'Unsupported browser type: None' — the original input is lost.

Source

Thrown at crawl4ai/utils.py:654

    
    Uses playwright's built-in browser management to get the correct browser executable
    path regardless of platform. This ensures we're using the same browser version
    that playwright is tested with.
    
    Returns:
        str: Path to browser executable
    Raises:
        RuntimeError: If browser executable cannot be found
    """        
    browser_types = {
        "chromium": "chromium",
        "firefox": "firefox",
        "webkit": "webkit"
    }
    
    browser_type = browser_types.get(browser_type)
    if not browser_type:
        raise RuntimeError(f"Unsupported browser type: {browser_type}")

    # Check if a path has already been saved for this browser type
    home_folder = get_home_folder()
    path_file = os.path.join(home_folder, f"{browser_type.lower()}.path")
    if os.path.exists(path_file):
        with open(path_file, "r") as f:
            return f.read()

    from playwright.async_api import async_playwright
    async with async_playwright() as p:
        browsers = {
            'chromium': p.chromium,
            'firefox': p.firefox, 
            'webkit': p.webkit
        }
        
        if browser_type.lower() not in browsers:
            raise ValueError(

View on GitHub (pinned to 7e80152142)

Solutions

  1. Use exactly 'chromium', 'firefox', or 'webkit' (Playwright's browser names, not vendor names).
  2. Normalize user input at your boundary: {'chrome': 'chromium', 'msedge': 'chromium'}.get(name.lower(), name.lower()).
  3. Also note this legacy helper predates the dict-based check just below (which lowercases input) — prefer passing already-lowercased canonical names.

Example fix

# before
path = await get_browser_executable_path("chrome")  # RuntimeError: Unsupported browser type: None

# after
alias = {"chrome": "chromium", "edge": "chromium"}.get(name.lower(), name.lower())
path = await get_browser_executable_path("chromium")
Defensive patterns

Strategy: validation

Validate before calling

VALID_BROWSERS = {"chromium", "firefox", "webkit"}

def canonical_browser(name: str) -> str:
    aliases = {"chrome": "chromium", "edge": "chromium", "msedge": "chromium", "brave": "chromium"}
    n = name.strip().lower()
    return aliases.get(n, n)

# assert canonical_browser(user_input) in VALID_BROWSERS before calling

Type guard

def is_valid_browser_type(name: str) -> bool:
    return isinstance(name, str) and name.lower() in {"chromium", "firefox", "webkit"}

Try / catch

try:
    path = await get_browser_executable_path(browser)
except (RuntimeError, ValueError) as e:
    if 'browser type' in str(e):
        raise ValueError(f"Use chromium/firefox/webkit, got {browser!r}") from e

Prevention

When it happens

Trigger: Passing browser_type values like 'chrome', 'msedge', 'brave', or any casing/typo variant that doesn't exactly match the three Playwright browser keys before the lookup.

Common situations: Users naturally writing 'chrome' instead of 'chromium', passing headless-shell or channel names, or forwarding a user-configured browser name unchecked into the setup helper.

Related errors


AI-assisted analysis of unclecode/crawl4ai@7e80152142 (2026-08-14). Data as JSON: /api/errors/3ddf79072b150e1c. Report an issue: GitHub.