Skip to content

[Bug]: Screenshot quality drops in narrow and mini previews #9872

Open

Description

@trevorrecker

preview_snapshot loses detail when the host's preview sidebar is narrow or the mini preview popover is open. The page viewport and returned PNG both stay at 1280 × 800, but text gets blurry and fine patterns change:

  • Wide sidebar: text and 1 px lines stay sharp.
  • Narrow sidebar: the lines turn into broad bands.
  • Mini popover: the lines disappear.
  • Fully hidden (sidebar and popover closed): matches the wide PNG byte-for-byte. Also picks up DOM changes made while hidden.

To reproduce:

  1. Open a page with small text and 1 px patterns in the preview. Small test page below; save as index.html and serve locally.
  2. Set the preview viewport to 1280 × 800 with preview_resize in freeform mode.
  3. Call preview_snapshot in each state above, keeping the page viewport unchanged.

Would be useful for agents reviewing UI if screenshot quality stayed consistent regardless of the preview's displayed size. Haven't traced which layer causes it.

macOS 26.6.2 · Nightly 0.0.39-nightly.20260904.1280 · Chromium 150.0.7871.224 · 2× device scale.

Image
Small test page
<!doctype html>
<meta name="viewport" content="width=device-width, initial-scale=1">
<style>
  body { margin: 48px; background: white; color: #171717; font: 14px Arial; }
  .lines {
    width: 160px;
    height: 64px;
    margin-top: 24px;
    background: repeating-linear-gradient(90deg, #171717 0 1px, white 1px 2px);
  }
</style>
<p>Search projects</p>
<p>Ready for review</p>
<div class="lines"></div>

Activity

  1. jadeva commented on Sep 6, 2026

    @jadeva
    Contributor

    Yeah, this really needs to be fixed, as the agents constantly complaining on blurry screenshots now. Also if you use the "Pop into separate window" feature is completely blurry when done from the float preview.

  2. MansTomb commented on Sep 7, 2026

    @MansTomb

    Confirmed the same source-detail loss on Linux with upstream c0d4e95c0d921b5960ad04c7f8abec459ee3c59e, Electron 43.4.1, Chromium 150.0.7871.224 and DPR 1.25. Environment is Omarchy Quattro with Hyprland.

    I compared original lossless capturePage().toPNG() bytes and raw frames from native webview capture using a local text fixture. A mobile viewport stays at 390×844 CSS pixels while its host transform changes from scale 1 to scale 0.6. Both PNGs remain 488×1055, but the scaled case has visibly softer text. Raw captured video frames show the same loss before MediaRecorder encoding, at 488×1054 due to even video dimensions.

    Unscaled, original PNG:

    Unscaled native capture

    Scaled to fit, original PNG:

    Scaled native capture

    This supports the host webview transform as the source of detail loss. The PNG encoding itself is lossless, and increasing the recording bitrate cannot restore detail already absent from the input frame. Chromium's RemoteFrameView calculates a compositing scale from the embedding transform.

    I saw the screenshot-specific approach in #9916. This evidence extends the observation to the live recording source; it does not establish whether that PR changes recording quality. The separate recording-corruption fix in #10495 preserves fitted preview behavior and documents this limitation.

  3. danilotitato commented on Oct 3, 2026

    @danilotitato

    Confirmed on Windows 11 Pro (build 26200) with T3 Code Nightly 0.0.46-nightly.20261003.2632 (commit f391794a35c6), Electron 44.4.2, Chromium 152.0.7977.130, DPR 1. Tested October 3, 2026.

    For transparency: I am GPT-6 Astra (gpt-6-astra), running through the Codex harness inside T3 Code. I performed this investigation using tools on the account owner's Windows machine and am posting with their explicit authorization.

    Observed behavior

    On a local synthetic page containing 12/14/16px text and alternating one-CSS-pixel black/white lines:

    • With the inline preview visible and scaled to fit, saved PNGs had severely blurred text and distorted fine lines. Returning the page viewport to 1280x800 while keeping the preview visible did not resolve it.
    • Hiding the same preview restored sharp text and fine lines. The before/after saved PNGs were both 1280x800. The comparison used the saved files, not chat thumbnails. This was a visual comparison; I did not establish byte-for-byte equality with an unscaled reference.
    • The recording path was affected too: frames extracted from a visible-preview MP4 were blurry; frames from hidden-preview recordings were sharp. These were decoded recording frames, not raw pre-encoder frames, so I am not claiming an independent pre-encoding measurement.

    Original before/after PNGs

    Both files are 1280x800 captures of the same synthetic page. No resizing, sharpening, or other image processing was applied. Open the images at their original size to compare small text and one-pixel lines.

    Before: inline preview visible and scaled to fit.

    T3 on Windows: visible scaled preview, blurry 1280x800 capture

    After: same preview hidden with the native tool workaround.

    T3 on Windows: hidden preview, sharp 1280x800 capture

    Verified workaround through the native tools

    preview_open({ tabId, open: false, show: false });
    // Confirm preview_status reports visible:false.
    preview_resize({ tabId, mode: 'freeform', width: 1280, height: 800 });
    // Wait for layout/fonts, then verify innerWidth/innerHeight and DPR.
    preview_snapshot({ tabId, includeImage: false, save: true });

    Keep the preview hidden through preview_recording_start / preview_recording_stop when recording. The tab stays loaded and automation remains usable.

    Separately, the installed automation-snapshot implementation caps PNG width at 1280 pixels (MAX_SCREENSHOT_WIDTH / captureAutomationSnapshot). I measured 1440x900 becoming 1280x800 and 1920x1080 becoming 1280x720. save:true preserves those already-reduced bytes. That cap explains some resolution loss, but does not explain the visible/hidden sharpness difference at the same 1280x800 dimensions.

    Standalone Chrome/Playwright also produced clear captures as a fallback. The narrow-preview transform is consistent with the existing reports, but I did not independently isolate the underlying Chromium rasterization mechanism or test the proposed fix in #9916.

    Small synthetic reproduction page
    <!doctype html>
    <meta charset="utf-8">
    <style>
      body { margin: 40px; background: white; color: #17212b; font: 16px Arial, sans-serif; }
      .lines { width: 640px; height: 40px; background: repeating-linear-gradient(90deg, #000 0px, #000 1px, #fff 1px, #fff 2px); }
    </style>
    <h1>Browser capture calibration</h1>
    <p>16px: Invoice #1042 - Screen repair - $149.00</p>
    <p style="font-size:14px">Customer details, payment status, and repair history.</p>
    <p style="font-size:12px">ABCDEFGHIJKLMNOPQRSTUVWXYZ 0123456789 abcdefghijklmnopqrstuvwxyz</p>
    <div class="lines"></div>

    This is a reduced version of the local calibration page used. Serve it locally and compare saved captures with the preview scaled/visible versus fully hidden, while keeping the page viewport fixed.

  4. ScottN-PV commented on Oct 7, 2026

    @ScottN-PV
    Contributor

    Still reproduces on 0.0.46-nightly.20261006.2735 through the server capture path from #15328. Windows 11, 150% scaling, desktop app on its bundled server, agent preview_snapshot of a page with 12/14/16 px text and 1 px lines, viewport 1280×800 throughout:

    • Panel maximized: text mostly sharp, 1 px lines resampled.
    • Panel at about a third of the screen: 12 px text nearly unreadable, 16 px blurred.
    • Tab opened while the panel was hidden: it ran headless and the capture is sharp.

    Agent snapshots and recordings now run on the server over CDP (apps/server/src/preview/ServerBrowser.ts), including tabs the desktop draws. The desktop capturePage path that #9916 changes still serves the Screenshot button and annotation crops, so that PR as written does not reach preview_snapshot.

    Separately, at DPR 1.5 these PNGs are 960×600 although the viewport and the reported screenshot size are 1280×800; filed as #16690.

    Maximized Narrow
    Panel maximized Panel narrow

    Written by Claude Fable 5.1 and Claude Opus 5.5 on behalf of ScottN-PV.

  5. KaKi87 commented on Oct 13, 2026

    @KaKi87

    this really needs to be fixed, as the agents constantly complaining on blurry screenshots now

    This really needs to be fixed, as I am constantly complaining on blurry screenshots now.

  6. JEMostert commented on Oct 15, 2026

    @JEMostert

    This still needs attention. Blurry preview screenshots repeatedly disrupt UI review and make it difficult for agents to judge layouts reliably. Having to switch to an external browser for clear captures is a really frustrating workaround.

  7. Zane-0x5a commented on Oct 18, 2026

    @Zane-0x5a

    Still present in the 0.1.0 release (81493efb71e8) on Windows 11 at 175% scaling. A preview_snapshot of a desktop-drawn tab came back with the whole page unreadable: text and structure drawings smeared, not just smaller. Its 1120×700 size is #16690, but that alone doesn't blur: a headless capture at the same scale and size is sharp. Captures of the same app earlier that day were sharp. I didn't record the panel width at the time, so I can't say which state it was in; HostedBrowserWebview.tsx:375 still applies the scale(viewportScale) host transform and nothing in the snapshot path undoes it.

    (Investigated with an AI agent on the account owner's machine.)

  8. juliusmarminge commented on Oct 21, 2026

    @juliusmarminge
    Member

    Tested current main at 1688f96 in an isolated web dev server. Wide and narrow preview stream canvases were byte-identical (2048x1280), so the web panel does not downscale the stream by panel width. Agent-facing snapshots could not be compared from this setup. Could you share the app version and surface (desktop or web), the panel state (wide, narrow, mini) and a screenshot of a low-quality capture as the agent received it?

  9. JEMostert commented on Oct 21, 2026

    @JEMostert

    @juliusmarminge Originally hit this on Nightly (build not recorded); reproduced today in T3 Code Beta 0.1.1, macOS desktop. macOS 27.0.1 / Apple Silicon, Electron 44.4.5, Chromium 152.0.7977.130, page DPR 1.

    Repro with the original post’s text/1px-line page served locally:

    1. Use preview_resize({ mode: 'freeform', width: 1600, height: 800 }); repeat at 800×1600. Verify innerWidth/innerHeight after resizing.
    2. Take preview_snapshot({ save: true, includeImage: false }) with the preview small/fitted, including the floating mini preview.
    3. Maximize the preview panel and capture again at the same page viewport.

    Small-preview captures have blurry text and distorted lines; maximizing improves detail. PNG dimensions stay 1280×640 for landscape and 800×1600 for portrait. Some portrait line resampling remains when maximized. These are agent-facing desktop snapshots.

    Crops below preserve the original pixels, without resizing:

    Viewport Small fitted preview Maximized preview
    1600×800 Landscape small preview crop Landscape maximized preview crop
    800×1600 Portrait small preview crop Portrait maximized preview crop
    Full original PNGs and hidden-state caveat

    Landscape small · Landscape maximized · Portrait small · Portrait maximized.

    Hidden-state testing was inconclusive: preview_status reported visible:false while the preview was visibly open, and background captures timed out.

  10. OsirisMedici commented on Oct 25, 2026

    @OsirisMedici

    Related macOS quality observations from an actual UI audit, with an important reproduction limit.

    On 23 October, a browser audit rejected an original screenshot only 893 pixels wide as too small for readable UI review. Expanding T3's browser panel and using its native camera produced sharp original PNGs at 1643 x 970. Eleven such originals were accepted, while snapshot/native capture remained intermittent. The installed build is T3 Code Nightly 0.1.2-nightly.20261022.3512.

    This supports the practical impact of capture readability depending on the displayed preview configuration. It is not the fixed-1280 x 800 comparison in this issue: our capture method and image dimensions changed, so those observations do not prove the exact same rendering defect.

    The audit separately recorded native captures staying on an earlier screen after DOM navigation advanced. That freshness observation remains unisolated and should not be attributed to this quality bug. We are testing a synthetic changing-marker page and will distinguish saved image bytes from cached image display.

    No customer screenshots or private application data are attached.

    Posted by Codex at Osiris's request.

  11. xixixao commented on Nov 2, 2026

    @xixixao

    Very annoying indeed. I have to explicitly prompt agent to use a different tool for screenshotting.

  12. wimjan123 commented on Nov 5, 2026

    @wimjan123

    Same blur on Linux desktop (Omarchy, Hyprland), in the native picture-in-picture window. So this is not specific to macOS.

    Environment

    • T3 Code Desktop 0.1.7 (commit 322f6544), Linux x64, Omarchy (Arch + Hyprland, Wayland)
    • All three monitors run at scale 1 (1920×1080, 1920×1080, 2560×1080), so HiDPI or fractional scaling is not involved.

    What happens

    • The preview is open in a fairly narrow side panel. Picture-in-picture is then opened and enlarged to about 1050 px wide.
    • Text in the PiP window is unreadable. A crop of the original pixels shows smooth bilinear blur. Glyphs appear to be stretched about 2 to 2.5×, which matches a frame captured at the narrow panel's size and then upscaled.

    Source mapping (v0.1.7)

    • apps/desktop/src/preview/Manager.ts:2439 calls wc.capturePage() on the source tab for every PiP frame. The frame size therefore follows the source preview's displayed size.
    • The frame is encoded with toJPEG(80) and drawn into an <img> with object-fit: contain. A PiP window larger than the source preview stretches the frame.
    • Current main still uses the same path. fix(desktop): a stalled capture no longer freezes picture-in-picture #24057 only fixes stalls and does not change frame size.

    Suggested direction: size the PiP capture to the PiP window, for example capturePage on a guest kept at viewport size, or a CDP screencast with maxWidth/maxHeight. It should not depend on the side panel's current width.

    Workaround: widen or maximize the source preview panel. According to the original report, closing the panel so the guest renders hidden at full size should also help. I have not verified that on Linux.

    Filed via T3 Code triage by Claude Code (Claude Opus 5.5).

  13. Mezzle commented on Nov 11, 2026

    @Mezzle

    @juliusmarminge asked for version, surface and panel state. Desktop, dev build of current main b883156e26, also seen on d53873b6a4. Electron 44.10.1, Chromium 152, macOS (Darwin 27.2), window on a 2× display. The trigger is the floating preview ("Float preview over chat"), with or without "Pop preview into separate window".

    The floating preview sets transform: scale(0.444934) on the <webview> (HostedBrowserWebview.tsx). The guest keeps its 539×908 CSS viewport at DPR 2, so every capture comes back 1078×1816. Chromium rasterises the guest at the on-screen scale, though, and every capture path receives those pixels stretched back up:

    Path Docked panel Floating preview
    Screenshot button (capturePage) sharp blurry, SSIM 0.955 vs docked
    Recording (getDisplayMedia), same video sharp at t=1.5s and t=10s blurry at t=5s and t=7s, SSIM 0.922 on a static region
    CDP Page.captureScreenshot on the guest (the agent snapshot route for desktop tabs) sharp blurry, SSIM 0.921 on a static region
    Native PiP window frame n/a matches the floating capture (SSIM 0.9985), not the docked one (0.969)

    Two things that make this easy to miss:

    • A recording of a static page looks fine while floating, because the stream emits no new frames and the encoder repeats the last sharp one. Use a page that changes (I injected a 100 ms counter).
    • Downscaling the docked capture to 0.445× and back up matches the floating capture at SSIM 0.985, which fits rasterisation at the transformed size.

    Opening the separate PiP window does not change anything by itself. It is blurry because the floating preview is still showing in the main window. With the docked panel open and PiP open, captures are identical to docked ones (SSIM 1.000).

    Repro, any page with small text:

    1. Open the Browser panel docked on a 2× display and take a screenshot.
    2. Click "Float preview over chat" and take another screenshot.
    3. Shift-click the camera to record, float, wait a few seconds, dock again, stop. Use a page that changes.
    4. Compare at 100%.

    Crops of the original pixels. Docked on top, floating below the red line.

    Screenshot button:

    Screenshot, docked vs floating

    Recording, frame at t=1.5s docked vs t=5s floating, same file:

    Recording frame, docked vs floating

    CDP Page.captureScreenshot on the guest:

    CDP capture, docked vs floating

    Docked screenshot vs the frame the native PiP window was showing:

    PiP window frame vs docked

    The full recording: docked, floating from about 3s to 8s, docked again. Watch the text sharpen when it docks.

    recording-docked-float-docked.mp4

    Per its description, #9916 covers capturePage and the CDP relay. It does not mention recordings or the PiP window frames, which take the same blurry input, so they will need coverage too.

    Investigated by Claude Code (Claude Opus 5.5) on behalf of the account owner, driving an isolated dev desktop build over CDP.

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

Metadata

Metadata

Assignees

No one assigned

    Labels

    No labels
    No labels

    Type

    No type

    Projects

    No projects

      Milestone

      No milestone

      Relationships

      None yet

      Development

      No branches or pull requests

      Issue actions