D4Vinci/Scrapling · error · ValueError

'quality' is only valid when 'image_type' is 'jpeg'.

Error message

'quality' is only valid when 'image_type' is 'jpeg'.

What it means

capture_screenshot accepts a quality parameter (JPEG quality 0-100) but Playwright only supports quality for JPEG output. If quality is passed while image_type is 'png' (the default), the server rejects the combination before touching the browser. This mirrors Playwright's own constraint, raised early for a clear message.

Source

Thrown at scrapling/core/ai.py:345

        network_idle: bool = False,
        timeout: int | float = 30000,
    ) -> List[ImageContent | TextContent]:
        """Capture a screenshot of a web page using an existing browser session and return it as an image.
        A browser session must be opened first with `open_session` (either `dynamic` or `stealthy`); the session ID is then passed here.

        :param url: The URL to navigate to and capture.
        :param session_id: ID of an open browser session created with `open_session`.
        :param image_type: Image format. Defaults to "png". Use "jpeg" for smaller file sizes.
        :param full_page: When True, captures the full scrollable page instead of just the viewport. Defaults to False.
        :param quality: Image quality (0-100) for JPEG only. Raises if passed with `image_type="png"`.
        :param wait: Time in milliseconds to wait after page load before capturing. Defaults to 0.
        :param wait_selector: Optional CSS selector to wait for before capturing.
        :param wait_selector_state: State to wait for the selector. Defaults to "attached".
        :param network_idle: Wait for the page until there are no network connections for at least 500 ms.
        :param timeout: Timeout in milliseconds for page operations. Defaults to 30,000.
        """
        if quality is not None and image_type != "jpeg":
            raise ValueError("'quality' is only valid when 'image_type' is 'jpeg'.")

        entry = self._get_session(session_id, expected_type=None)

        screenshot_kwargs: Dict[str, Any] = {"type": image_type, "full_page": full_page}
        if quality is not None:
            screenshot_kwargs["quality"] = quality

        captured: Dict[str, Any] = {}

        async def _capture(page: Any) -> None:
            try:
                captured["bytes"] = await page.screenshot(**screenshot_kwargs)
                captured["url"] = page.url
            except Exception as exc:
                captured["error"] = exc

        await entry.session.fetch(
            url,

View on GitHub (pinned to 5d213a2d47)

Solutions

  1. Use quality only with image_type='jpeg': screenshot(url, image_type='jpeg', quality=80)
  2. Or drop quality entirely for png output

Example fix

# before
await capture_screenshot(session_id=sid, url=url, image_type='png', quality=80)

# after
await capture_screenshot(session_id=sid, url=url, image_type='jpeg', quality=80)
Defensive patterns

Strategy: validation

Validate before calling

if quality is not None:
    assert image_type == 'jpeg', 'quality requires image_type="jpeg"'

Type guard

from typing import Optional

def screenshot_args_ok(image_type: str, quality: Optional[int]) -> bool:
    return quality is None or image_type == 'jpeg'

Prevention

When it happens

Trigger: Calling screenshot with image_type='png' (explicitly or by default) together with quality=80, or setting quality globally in agent config while switching image_type to png for lossless captures.

Common situations: Copy-pasting a full option set from a JPEG example, or LLM agents filling every optional argument with defaults.

Related errors


AI-assisted analysis of D4Vinci/Scrapling@5d213a2d47 (2026-08-14). Data as JSON: /api/errors/9054cd6b9ec4929a. Report an issue: GitHub.