unclecode/crawl4ai · error · NotImplementedError
Browser type {self.browser_type} not supported
Error message
Browser type {self.browser_type} not supported What it means
The managed browser launcher builds a subprocess command line per browser type and only knows how to do so for 'chromium' and 'firefox'. Any other browser_type string falls through to NotImplementedError, naming the unsupported value.
Source
Thrown at crawl4ai/browser_manager.py:406:7237
if self.browser_type == "chromium":
args = [
f"--remote-debugging-port={self.debugging_port}",
f"--user-data-dir={self.user_data_dir}",
]
if self.headless:
args.append("--headless=new")
elif self.browser_type == "firefox":
args = [
"--remote-debugging-port",
str(self.debugging_port),
"--profile",
self.user_data_dir,
]
if self.headless:
args.append("--headless")
else:
raise NotImplementedError(f"Browser type {self.browser_type} not supported")
return base_args + args
async def cleanup(self):
"""Cleanup browser process and temporary directory"""
# Set shutting_down flag BEFORE any termination actions
self.shutting_down = True
if self.browser_process:
try:
# For builtin browsers that should persist, we should check if it's a detached process
# Only terminate if we have proper control over the process
if not self.browser_process.poll():
# Process is still running
self.browser_process.terminate()
# Wait for process to end gracefully
for _ in range(10): # 10 attempts, 100ms each
if self.browser_process.poll() is not None:View on GitHub (pinned to 7e80152142)
Solutions
- Use browser_type='chromium' or browser_type='firefox' exactly (lowercase)
- If you named a concrete binary ('chrome', 'edge'), switch to 'chromium' and point the binary/path option at your executable if the config supports it
- For other engines, use Playwright-based crawling instead of the managed native launcher
Example fix
# before BrowserConfig(browser_type="chrome") # after BrowserConfig(browser_type="chromium")
Defensive patterns
Strategy: validation
Validate before calling
SUPPORTED_BROWSERS = {"chromium", "firefox"}
def validate_browser_type(browser_type: str) -> str:
if browser_type not in SUPPORTED_BROWSERS:
raise ValueError(
f"unsupported browser_type {browser_type!r}; use one of {sorted(SUPPORTED_BROWSERS)}"
)
return browser_type Type guard
def is_supported_browser(browser_type) -> bool:
return isinstance(browser_type, str) and browser_type in {"chromium", "firefox"} Try / catch
try:
args = browser._build_args() # or start()
except NotImplementedError:
# reconfigure and retry with a supported engine
browser.browser_type = "chromium"
args = browser._build_args() Prevention
- Use exactly 'chromium' or 'firefox' (lowercase) for browser_type
- Validate browser_type at config load time, not at launch time
- For WebKit/Edge needs, use the Playwright-based path instead of the managed launcher
When it happens
Trigger: Setting browser_type to anything other than 'chromium' or 'firefox' in the managed/native browser config — e.g. 'chrome', 'google-chrome', 'webkit', 'edge', 'safari', or a typo like 'Chromium' (case-sensitive).
Common situations: Users writing browser_type='chrome' because that is the Playwright/Puppeteer spelling; attempting WebKit/Edge support that the launcher does not implement; case mismatches after a config refactor.
Related errors
- Hook '{hook_name}' must be a callable function, got {type(ho
- URL must have a valid hostname
- too many webhook headers
- invalid webhook header name: {name!r}
- webhook header not allowed: {name}
AI-assisted analysis of unclecode/crawl4ai@7e80152142 (2026-08-14).
Data as JSON: /api/errors/d0fe6fb0ca702336.
Report an issue: GitHub.