browser-use/browser-use · error · ValueError

llm_screenshot_size dimensions must be at least 100 pixels

Error message

llm_screenshot_size dimensions must be at least 100 pixels

What it means

Final stage of `llm_screenshot_size` validation: both dimensions must be at least 100 pixels. Screenshots smaller than 100x100 are useless for vision models, so the beta agent rejects them at construction time rather than producing degraded runs.

Source

Thrown at browser_use/beta/service.py:4312

		planning_replan_on_stall: int = 3,
		planning_exploration_limit: int = 5,
		loop_detection_window: int = 20,
		loop_detection_enabled: bool = True,
		llm_screenshot_size: tuple[int, int] | None = None,
		message_compaction: MessageCompactionSettings | bool | None = True,
		max_clickable_elements_length: int = 40000,
		_url_shortening_limit: int = 25,
		enable_signal_handler: bool = True,
		**kwargs,
	):
		if llm_screenshot_size is not None:
			if not isinstance(llm_screenshot_size, tuple) or len(llm_screenshot_size) != 2:
				raise ValueError('llm_screenshot_size must be a tuple of (width, height)')
			width, height = llm_screenshot_size
			if not isinstance(width, int) or not isinstance(height, int):
				raise ValueError('llm_screenshot_size dimensions must be integers')
			if width < 100 or height < 100:
				raise ValueError('llm_screenshot_size dimensions must be at least 100 pixels')
		llm = _resolve_default_llm(llm)
		use_vision = True
		if browser and browser_session:
			raise ValueError('Cannot specify both "browser" and "browser_session" parameters. Use "browser" for the cleaner API.')
		if getattr(llm, 'provider', None) == 'browser-use':
			flash_mode = True
		if flash_mode:
			enable_planning = False
		if llm_screenshot_size is None:
			model_name = getattr(llm, 'model', '')
			# rsplit drops the provider prefix so gateway ids like 'anthropic/claude-sonnet-4-6'
			# get the same screenshot auto-config as direct Claude Sonnet models.
			if isinstance(model_name, str) and model_name.rsplit('/', 1)[-1].startswith('claude-sonnet'):
				llm_screenshot_size = (1400, 850)
		if page_extraction_llm is None:
			page_extraction_llm = llm
		if judge_llm is None:
			judge_llm = llm

View on GitHub (pinned to 6c73fced2f)

Solutions

  1. Use real pixel dimensions ≥ 100 in both axes, e.g. `(1280, 720)`.
  2. Clamp derived sizes: `(max(100, w), max(100, h))`.
  3. If you wanted a scale factor, multiply the viewport instead of passing the fraction directly.

Example fix

# before
agent = BetaAgent(task=t, llm_screenshot_size=(0.8, 0.8))  # meant as scale, fails 100px floor

# after
agent = BetaAgent(task=t, llm_screenshot_size=(1280, 720))
Defensive patterns

Strategy: validation

Validate before calling

MIN = 100
size = (max(MIN, w), max(MIN, h)) if isinstance(w, int) and isinstance(h, int) else None

Type guard

def meets_min_size(v) -> bool:
    return v is None or (isinstance(v, tuple) and len(v) == 2 and all(isinstance(d, int) and d >= 100 for d in v))

Prevention

When it happens

Trigger: Passing values below 100 in either dimension, e.g. `(80, 600)`, `(1400, 50)`, or a scaling computation that rounds a dimension under 100. Booleans (True == 1) also land here.

Common situations: Derived sizes (crop regions, thumbnail scales) accidentally below the floor; typos like (14, 85) for (1400, 850); unit confusion treating the tuple as a fraction/scale factor.

Related errors


AI-assisted analysis of browser-use/browser-use@6c73fced2f (2026-08-14). Data as JSON: /api/errors/033b1061d2f619af. Report an issue: GitHub.