[Claude in Chrome] window.print() dialog freezes renderer; need silent "save page as PDF" tool

Resolved 💬 3 comments Opened Apr 29, 2026 by garricklouie-svg Closed May 31, 2026

Preflight Checklist

  • [x] I have searched existing issues and this hasn't been reported yet
  • [x] This is a single bug report (please file separate reports for different bugs)
  • [x] I am using the latest version of Claude Code

What's Wrong?

When using Claude in Chrome via the Cowork desktop app to retrieve PDFs from government / financial portals, the workflow breaks at the final "download bill PDF" step on any site that calls window.print() rather than exposing an <a download> link.

Observed during a tax-prep workflow today (looking up county property tax bills):

  • SF Treasurer (county-taxes.net) — WORKS. Site uses <a> elements with href pointing to a server-rendered PDF endpoint. JS-triggered .click() downloads silently to the user's Downloads folder.
  • San Mateo County (county-taxes.net) — Mostly works (same platform), but uses an extra modal that fires window.print() after submit, which sometimes hangs.
  • Alameda County (propertytax.alamedacountyca.gov) — BREAKS. The "Print Copy of Bill" button calls window.print(), which opens the native OS print dialog. From Claude in Chrome's perspective, the renderer becomes unresponsive — subsequent CDP Runtime.evaluate calls time out at 45s. The agent cannot programmatically dismiss the dialog or select "Save as PDF".

Result: a huge category of useful agentic workflows — tax document retrieval, medical records, bank statements, government forms — depend on PDFs that are only reachable via "Print" buttons. Today these workflows always require user intervention at the last step, which significantly degrades the automation value.

What Should Happen?

Claude in Chrome should expose a built-in "save current page as PDF" tool that uses Chrome DevTools Protocol's Page.printToPDF method. This generates a PDF without opening any OS dialog and can write directly to a known location (Downloads folder, sandbox-accessible path, or returned as base64 in the tool result).

Ideally the tool would have parameters like:

  • tabId
  • paperSize (Letter / A4 / etc.)
  • landscape (boolean)
  • printBackground (boolean)
  • marginTop/Right/Bottom/Left
  • outputPath (where to save)

This would unblock the entire class of "site has a print button but no download link" workflows.

Error Messages/Logs

Failed to execute JavaScript: CDP sendCommand "Runtime.evaluate" timed out after 45000ms on tab <tabId>. The renderer may be frozen or unresponsive.

Steps to Reproduce

  1. Open Claude in Chrome via Cowork desktop app
  2. Have agent navigate to https://propertytax.alamedacountyca.gov/search
  3. Search for any address (e.g., a public commercial address), click "View Bill" on a result
  4. Have agent click "Print Copy of Bill" button — this triggers window.print()
  5. Subsequent JS execution / page interactions hang until the print dialog is manually dismissed by the user

Reproduces consistently on macOS Sequoia, Chrome stable.

Claude Model

None

Is this a regression?

No, this never worked

Last Working Version

_No response_

Claude Code Version

N/A — bug is in Claude in Chrome / Cowork desktop app, not Claude Code CLI (no claude --version to run; user is on the latest Cowork desktop)

Platform

Other

Operating System

macOS

Terminal/Shell

Terminal.app (macOS)

Additional Information

Workaround used today: programmatic anchor injection with a custom download attribute pointing to the PDF endpoint URL. Works for sites that expose a direct PDF URL (SF), doesn't work where there's no exposed URL (Alameda — print is the only path).

For reference, the SF county-taxes.net pattern that works:

const a = iframeDoc.createElement('a');
a.href = printUrl;
a.download = 'filename.pdf';
iframeDoc.body.appendChild(a);
a.click();
a.remove();

This works silently. Same approach fails on Alameda because the underlying URL returns HTML, not a PDF — only the print dialog produces the PDF.

Related: an additional safety filter on JS return values currently blocks data:application/pdf;base64,... strings from being returned to the agent, which prevents the alternative workaround of fetching the PDF bytes via JS fetch() and returning them. So even when a PDF endpoint exists, the agent cannot exfiltrate the bytes to save them via Python — the only option is browser-side download to user's Downloads folder.

View original on GitHub ↗

This issue has 3 comments on GitHub. Read the full discussion on GitHub ↗