Skip to content

docs(screenshots): backgrounded tabs pause rAF — screenshots of animated pages can lie#511

Open
zacklavin11 wants to merge 1 commit into
browser-use:mainfrom
zacklavin11:docs/screenshots-raf-pause
Open

docs(screenshots): backgrounded tabs pause rAF — screenshots of animated pages can lie#511
zacklavin11 wants to merge 1 commit into
browser-use:mainfrom
zacklavin11:docs/screenshots-raf-pause

Conversation

@zacklavin11

@zacklavin11 zacklavin11 commented Jul 12, 2026

Copy link
Copy Markdown

Field-tested across many QA runs on an animation-heavy React app: Chrome pauses requestAnimationFrame in backgrounded/occluded tabs, so screenshots of count-ups and reveals silently show blank or stale frames while the page reports loaded. This adds the gotcha and the recovery recipe (visibilityState probe, foreground + nudge, DOM reads over pixels, two-sample rule for animated values) to the screenshots skill.

🤖 Generated with Claude Code

https://claude.ai/code/session_019DKKK5uNG9DzvUGtyGViye


Summary by cubic

Documented that Chrome pauses requestAnimationFrame in backgrounded or occluded tabs, which can make screenshots of animations show blank or stale frames even when the page reports loaded. Added a short checklist to detect and recover: check document.visibilityState, foreground and nudge the tab (Target.activateTarget, small scroll or mousemove), prefer DOM reads (getBoundingClientRect/scrollHeight) over pixels, and confirm animated values with two matching samples a few seconds apart.

Written for commit 9c2075e. Summary will update on new commits.

Review in cubic

…ted pages can lie

Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_019DKKK5uNG9DzvUGtyGViye
@browser-harness-review

Copy link
Copy Markdown

✅ Skill review passed

Reviewed 1 file(s) — no findings.

@cubic-dev-ai cubic-dev-ai Bot left a comment

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

2 issues found across 1 file

Prompt for AI agents (unresolved issues)

Check if these issues are valid — if so, understand the root cause of each and fix them. If appropriate, use sub-agents to investigate and fix each issue separately.


<file name="interaction-skills/screenshots.md">

<violation number="1" location="interaction-skills/screenshots.md:25">
P2: DOM reads avoid screenshot-pixel artifacts, but they are not immune to a paused rAF animation: they return the same frozen intermediate text and geometry that the paused callbacks last wrote. This can make the guidance report a stale count-up or layout as authoritative. Suggest describing DOM reads as an inspection of the current state and requiring visibility plus an animation-completion condition before treating the value as final.</violation>

<violation number="2" location="interaction-skills/screenshots.md:26">
P2: Two matching reads do not establish that an animated value is final; a paused or temporarily held animation yields identical intermediate values. This can recreate the stale-frame false positive the section is meant to prevent. Suggest using matching samples only as a stability check and requiring the page/app's animation completion signal (or another known terminal condition) before calling a value final.</violation>
</file>

Reply with feedback, questions, or to request a fix.

Fix all with cubic | Re-trigger cubic

- Probe `js("document.visibilityState")` — anything but `"visible"` means the screenshot may lie.
- Foreground the tab (`Target.activateTarget` via `cdp(...)`) and nudge it (scroll 1px or dispatch a mousemove) to restart rAF, then re-screenshot.
- For numbers and layout, prefer DOM reads (`js(...)` with `getBoundingClientRect` / `scrollHeight`) over pixels — they are immune to the pause.
- Animated values need two samples a few seconds apart that match before you read them as final.

@cubic-dev-ai cubic-dev-ai Bot Jul 12, 2026

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

P2: Two matching reads do not establish that an animated value is final; a paused or temporarily held animation yields identical intermediate values. This can recreate the stale-frame false positive the section is meant to prevent. Suggest using matching samples only as a stability check and requiring the page/app's animation completion signal (or another known terminal condition) before calling a value final.

Prompt for AI agents
Check if this issue is valid — if so, understand the root cause and fix it. At interaction-skills/screenshots.md, line 26:

<comment>Two matching reads do not establish that an animated value is final; a paused or temporarily held animation yields identical intermediate values. This can recreate the stale-frame false positive the section is meant to prevent. Suggest using matching samples only as a stability check and requiring the page/app's animation completion signal (or another known terminal condition) before calling a value final.</comment>

<file context>
@@ -15,3 +15,12 @@ capture_screenshot("/tmp/shot.png", max_dim=1800)
+- Probe `js("document.visibilityState")` — anything but `"visible"` means the screenshot may lie.
+- Foreground the tab (`Target.activateTarget` via `cdp(...)`) and nudge it (scroll 1px or dispatch a mousemove) to restart rAF, then re-screenshot.
+- For numbers and layout, prefer DOM reads (`js(...)` with `getBoundingClientRect` / `scrollHeight`) over pixels — they are immune to the pause.
+- Animated values need two samples a few seconds apart that match before you read them as final.
</file context>
Suggested change
- Animated values need two samples a few seconds apart that match before you read them as final.
- Treat matching samples only as a stability check; use the app's completion signal (or another known terminal condition) before treating animated values as final.
Fix with cubic


- Probe `js("document.visibilityState")` — anything but `"visible"` means the screenshot may lie.
- Foreground the tab (`Target.activateTarget` via `cdp(...)`) and nudge it (scroll 1px or dispatch a mousemove) to restart rAF, then re-screenshot.
- For numbers and layout, prefer DOM reads (`js(...)` with `getBoundingClientRect` / `scrollHeight`) over pixels — they are immune to the pause.

@cubic-dev-ai cubic-dev-ai Bot Jul 12, 2026

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

P2: DOM reads avoid screenshot-pixel artifacts, but they are not immune to a paused rAF animation: they return the same frozen intermediate text and geometry that the paused callbacks last wrote. This can make the guidance report a stale count-up or layout as authoritative. Suggest describing DOM reads as an inspection of the current state and requiring visibility plus an animation-completion condition before treating the value as final.

Prompt for AI agents
Check if this issue is valid — if so, understand the root cause and fix it. At interaction-skills/screenshots.md, line 25:

<comment>DOM reads avoid screenshot-pixel artifacts, but they are not immune to a paused rAF animation: they return the same frozen intermediate text and geometry that the paused callbacks last wrote. This can make the guidance report a stale count-up or layout as authoritative. Suggest describing DOM reads as an inspection of the current state and requiring visibility plus an animation-completion condition before treating the value as final.</comment>

<file context>
@@ -15,3 +15,12 @@ capture_screenshot("/tmp/shot.png", max_dim=1800)
+
+- Probe `js("document.visibilityState")` — anything but `"visible"` means the screenshot may lie.
+- Foreground the tab (`Target.activateTarget` via `cdp(...)`) and nudge it (scroll 1px or dispatch a mousemove) to restart rAF, then re-screenshot.
+- For numbers and layout, prefer DOM reads (`js(...)` with `getBoundingClientRect` / `scrollHeight`) over pixels — they are immune to the pause.
+- Animated values need two samples a few seconds apart that match before you read them as final.
</file context>
Suggested change
- For numbers and layout, prefer DOM reads (`js(...)` with `getBoundingClientRect` / `scrollHeight`) over pixels — they are immune to the pause.
- For numbers and layout, use DOM reads (`js(...)` with `getBoundingClientRect` / `scrollHeight`) to inspect the current state, but treat them as stale until the page is visible and the animation has completed.
Fix with cubic

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

1 participant