Browser vs. Run Configuration
Where do you put headless mode, and where do you put cache mode? Put them in the wrong object and the API will silently ignore you.
Concept
Think of BrowserConfig as the browser environment you set once per crawler instance: browser type, viewport, user agent mode, and persistent profile. CrawlerRunConfig is the per-crawl instruction: cache behavior, word-count threshold, extraction strategy, and JavaScript to run. Mixing the two is the most common beginner mistake because older examples accepted flat keyword arguments.
Caching lives only on CrawlerRunConfig through the CacheMode enum: ENABLED, DISABLED, READ_ONLY, WRITE_ONLY, and BYPASS. Boolean cache flags were removed; if you pass them, the call will reject the setting.
Use cases
- Run the same browser with different cache modes during development and production.
- Switch from headless to headed only when debugging a stubborn page.
- Reuse a logged-in browser profile across multiple per-crawl configurations.
Video walkthrough
Code example
import asyncio
import os
from crawl4ai import AsyncWebCrawler, BrowserConfig, CrawlerRunConfig, CacheMode
async def main():
# Global browser environment
browser_cfg = BrowserConfig(
headless=True,
viewport_width=1280,
viewport_height=720,
user_agent_mode="random",
)
# Per-crawl configurations
fresh_cfg = CrawlerRunConfig(
cache_mode=CacheMode.BYPASS,
word_count_threshold=20,
)
cached_cfg = CrawlerRunConfig(
cache_mode=CacheMode.ENABLED,
word_count_threshold=20,
)
async with AsyncWebCrawler(config=browser_cfg) as crawler:
fresh = await crawler.arun(url="https://example.com", config=fresh_cfg)
cached = await crawler.arun(url="https://example.com", config=cached_cfg)
for r in (fresh, cached):
print(r.url, r.success, r.status_code)
asyncio.run(main())
Practice lab
Practice lab
Objective: Run the same URL twice with different cache modes and compare timing.
Steps
- Create a
BrowserConfigwithheadless=True. - Create two
CrawlerRunConfigobjects: one withCacheMode.BYPASSand one withCacheMode.ENABLED. - Crawl the same URL with each config and record the elapsed time.
- Print the status code and a 200-character markdown snippet from each run.
Success criteria
Expected output
Hints
- Use
time.perf_counter()around eachawait crawler.arun()call. - Make sure the URL returns 200 before comparing timing.
Solution
import asyncio
import time
from crawl4ai import AsyncWebCrawler, BrowserConfig, CrawlerRunConfig, CacheMode
async def main():
browser_cfg = BrowserConfig(headless=True)
url = "https://example.com"
async with AsyncWebCrawler(config=browser_cfg) as crawler:
for mode in (CacheMode.BYPASS, CacheMode.ENABLED):
run_cfg = CrawlerRunConfig(cache_mode=mode)
start = time.perf_counter()
result = await crawler.arun(url=url, config=run_cfg)
elapsed = time.perf_counter() - start
print(f"{mode.name}: success={result.success} status={result.status_code} time={elapsed:.3f}s")
asyncio.run(main())
Common mistakes
cache_mode on BrowserConfig instead of CrawlerRunConfig.CacheMode enum.BrowserConfig as a per-run tuning knob.