D4Vinci/Scrapling · error · RuntimeError

Failed to capture screenshot for {url}

Error message

Failed to capture screenshot for {url}

What it means

After running the capture callback inside the page, the tool raises RuntimeError('Failed to capture screenshot for {url}') when no bytes were produced and no explicit error was captured — the page action completed without delivering a screenshot and without raising anything catchable. It is the sentinel for 'the navigation/wait succeeded but page.screenshot returned nothing'.

Source

Thrown at scrapling/core/ai.py:375

                captured["bytes"] = await page.screenshot(**screenshot_kwargs)
                captured["url"] = page.url
            except Exception as exc:
                captured["error"] = exc

        await entry.session.fetch(
            url,
            wait=wait,
            timeout=timeout,
            network_idle=network_idle,
            wait_selector=wait_selector,
            wait_selector_state=wait_selector_state,
            page_action=_capture,
        )

        if "error" in captured:
            raise captured["error"]
        if "bytes" not in captured:
            raise RuntimeError(f"Failed to capture screenshot for {url}")

        image = Image(data=captured["bytes"], format=image_type).to_image_content()
        return [image, TextContent(type="text", text=captured["url"])]

    @staticmethod
    async def get(
        url: str,
        impersonate: ImpersonateType = "chrome",
        extraction_type: extraction_types = "markdown",
        css_selector: Optional[str] = None,
        main_content_only: bool = True,
        params: Optional[Dict] = None,
        headers: Optional[Mapping[str, Optional[str]]] = None,
        cookies: Optional[Dict[str, str]] = None,
        timeout: Optional[int | float] = 30,
        follow_redirects: FollowRedirects = "safe",
        max_redirects: int = 30,
        retries: Optional[int] = 3,

View on GitHub (pinned to 5d213a2d47)

Solutions

  1. Retry the capture once — transient page-close races are the most common cause
  2. Add wait/wait_selector so the page is settled before capture, and network_idle=True for late-loading pages
  3. Check the page isn't redirecting to about:blank or being closed by the site; try block_webrtc/hide_canvas or a stealthy session for anti-bot targets
  4. Verify Playwright browser binaries are installed and versions match (`playwright install chromium`)

Example fix

# before
imgs = await capture_screenshot(session_id=sid, url=url)

# after
imgs = await capture_screenshot(
    session_id=sid, url=url,
    wait=1500, network_idle=True,  # let page settle
)
Defensive patterns

Strategy: retry

Try / catch

from tenacity import retry, retry_if_exception_type, stop_after_attempt, wait_fixed

@retry(retry=retry_if_exception_type(RuntimeError), stop=stop_after_attempt(2), wait=wait_fixed(1_000), reraise=True)
async def safe_capture(**kw):
    return await capture_screenshot(**kw)

Prevention

When it happens

Trigger: The _capture coroutine never assigning captured['bytes'] — e.g. the page_action short-circuited because navigation was blocked, the page closed mid-flight, or screenshot kwargs were rejected by the Playwright version in use. It follows a successful _navigate_and_act call, so wait/timeout errors usually surface earlier.

Common situations: Pages that destroy/close themselves on load (about:blank redirects, anti-bot tricks), headless environments where screenshot is interrupted, or Playwright/Scrapling version mismatches changing screenshot kwarg behavior.

Related errors


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