openclaw - ✅(Solved) Fix Browser screenshot fails on Chrome 146+ with managed browser (fromSurface: false) [1 pull requests, 1 comments, 2 participants]

Official PRs (…)
ON THIS PAGE

Recommended Tools

×6

Utilities matched from this issue’s tags and category — try them while you read without losing context.

GitHub issue graph ai analysis

Paste a GitHub issue URL. We fetch that issue, discover linked issues from bodies/comments/timeline, collect linked pull requests, and produce a structured English report.

The report is written in English Markdown for sharing and archival.

Helpful · Quick feedback

Loading…
GitHub stats
openclaw/openclaw#60540Fetched 2026-04-08 02:49:53
View on GitHub
Comments
1
Participants
2
Timeline
4
Reactions
0
Author
Participants
Timeline (top)
closed ×1commented ×1cross-referenced ×1locked ×1

Root Cause

In routes-GmL6Gsmc.js, the captureScreenshot function (line ~4959) uses:

const base64 = (await send('Page.captureScreenshot', {
    format,
    fromSurface: false,  // <-- THIS
    captureBeyondViewport: true
}))?.data;

fromSurface: false tells Chrome to capture from the compositor surface rather than the rendered surface. On Chrome 146+ with a managed/headful browser that isn't in the foreground, the compositor doesn't have rendered content available, so the screenshot returns empty/null data.

Fix Action

Workaround

Use browser snapshot instead of browser screenshot for all automation tasks. Snapshots provide the DOM tree which is sufficient for click/type/navigate automation.

PR fix notes

PR #60682: fix(browser): remove fromSurface: false for Chrome 146+ screenshot compat

Description (problem / solution / changelog)

Summary

Describe the problem and fix in 2-5 bullets:

  • Problem: Page.captureScreenshot passes fromSurface: false, which Chrome 146+ rejects for managed/headful browsers, returning "Unable to capture screenshot"
  • Why it matters: browser screenshot is broken on Chrome 146+ while browser snapshot (DOM-based) still works
  • What changed: Removed fromSurface: false from the CDP call in extensions/browser/src/browser/cdp.ts:124. Updated the comment to explain the Chromium bug (40760789) was fixed around Chrome 130 and fromSurface: false now fails on 146+. Updated test assertion.
  • What did NOT change (scope boundary): captureBeyondViewport: true remains. No other screenshot parameters touched.

Change Type (select all)

  • Bug fix
  • Feature
  • Refactor required for the fix
  • Docs
  • Security hardening
  • Chore/infra

Scope (select all touched areas)

  • Gateway / orchestration
  • Skills / tool execution
  • Auth / tokens
  • Memory / storage
  • Integrations
  • API / contracts
  • UI / DX
  • CI/CD / infra

Linked Issue/PR

  • Closes #60540
  • This PR fixes a bug or regression

Root Cause (if applicable)

  • Root cause: Chromium behavior change in Chrome 146+. fromSurface: false tells Chrome to capture from the compositor surface rather than the rendered surface. Chrome 146+ managed/headful browsers reject this parameter, returning empty screenshot data. The original workaround was for Chromium bug 40760789 (cross-origin image textures lost with fromSurface: true + captureBeyondViewport: true), which was fixed around Chrome 130.
  • Missing detection / guardrail: No Chrome version detection around the fromSurface parameter
  • Contributing context (if known): The Chromium bug was reported and fixed upstream. The workaround outlived the bug.

Regression Test Plan (if applicable)

  • Coverage level that should have caught this:
    • Unit test
    • Seam / integration test
    • End-to-end test
    • Existing coverage already sufficient
  • Target test or file: extensions/browser/src/browser/cdp.screenshot-params.test.ts
  • Scenario: Updated existing test to assert fromSurface is omitted from CDP params rather than set to false

This contribution was developed with AI assistance (Codex).

Changed files

  • CHANGELOG.md (modified, +1/-0)
  • extensions/browser/src/browser/cdp.screenshot-params.test.ts (modified, +2/-2)
  • extensions/browser/src/browser/cdp.ts (modified, +4/-4)

Code Example

const base64 = (await send('Page.captureScreenshot', {
    format,
    fromSurface: false,  // <-- THIS
    captureBeyondViewport: true
}))?.data;
RAW_BUFFERClick to expand / collapse

Bug Report

OpenClaw version: Latest (installed via homebrew) Chrome version: 146.0.7680.178 macOS: Darwin 25.3.0 (arm64)

Problem

browser screenshot consistently returns Unable to capture screenshot for the managed browser (openclaw profile), while browser snapshot works perfectly. All other browser actions (click, type, navigate, open) work fine.

Root Cause

In routes-GmL6Gsmc.js, the captureScreenshot function (line ~4959) uses:

const base64 = (await send('Page.captureScreenshot', {
    format,
    fromSurface: false,  // <-- THIS
    captureBeyondViewport: true
}))?.data;

fromSurface: false tells Chrome to capture from the compositor surface rather than the rendered surface. On Chrome 146+ with a managed/headful browser that isn't in the foreground, the compositor doesn't have rendered content available, so the screenshot returns empty/null data.

Evidence

  • Direct Playwright page.screenshot() (which defaults to fromSurface: true) works perfectly on the same page/target
  • CDP Page.captureScreenshot with fromSurface: true (or omitted) succeeds
  • The issue reproduces consistently regardless of which page is loaded
  • Snapshots (DOM accessibility tree) always work since they don't depend on rendering

Suggested Fix

Change fromSurface: false to fromSurface: true (or remove the parameter entirely to use Chrome's default of true).

Workaround

Use browser snapshot instead of browser screenshot for all automation tasks. Snapshots provide the DOM tree which is sufficient for click/type/navigate automation.

extent analysis

TL;DR

Change the fromSurface parameter to true in the captureScreenshot function to fix the screenshot issue.

Guidance

  • Verify that the issue is specific to Chrome version 146+ and managed/headful browsers not in the foreground.
  • Check the captureScreenshot function in routes-GmL6Gsmc.js to confirm the fromSurface parameter is set to false.
  • Update the captureScreenshot function to use fromSurface: true or remove the parameter to use Chrome's default.
  • Test the fix by running the browser screenshot command with the updated captureScreenshot function.

Example

const base64 = (await send('Page.captureScreenshot', {
    format,
    fromSurface: true,  // Update this line
    captureBeyondViewport: true
}))?.data;

Notes

This fix assumes that the issue is caused by the fromSurface parameter being set to false in the captureScreenshot function. If the issue persists after updating the function, further investigation may be needed.

Recommendation

Apply the suggested fix by updating the fromSurface parameter to true to resolve the screenshot issue, as this change is specific to the identified root cause and does not introduce additional dependencies or version upgrades.

Vote matrix · Quick signals

Works
Did the solution work? Tap to confirm.
Easy Fix
Was it a quick fix?
Time Saver
Did it save you time?
Blocking
Was it severely blocking?
Common Issue
Are others likely hitting this too?
Flaky / Intermittent
Is it intermittent?
Verified / Reproducible
Can you reproduce it reliably?
Loading…

Still need to ship something?

×6

Another batch ranked right after the header list — different links, same matching logic.

Back to top recommendations

TRENDING