From 1b444a5ed0c02f159f43918c8ae4b1001ad49159 Mon Sep 17 00:00:00 2001 From: Derek Meegan Date: Sun, 29 Mar 2026 14:22:23 -0700 Subject: [PATCH 1/4] Add `browse pdf` command to save pages as PDF Uses CDP Page.printToPDF to generate PDFs with configurable paper format (letter, legal, a4, a3), orientation, scale, and background printing. Saves to file when path given, returns base64 otherwise. Usage: browse pdf ./page.pdf # save as PDF browse pdf ./page.pdf --landscape # landscape orientation browse pdf ./page.pdf --format a4 # A4 paper size browse pdf # returns base64 Co-Authored-By: Claude Opus 4.6 (1M context) --- .changeset/add-pdf-command.md | 5 +++ packages/cli/src/index.ts | 71 +++++++++++++++++++++++++++++++++++ 2 files changed, 76 insertions(+) create mode 100644 .changeset/add-pdf-command.md diff --git a/.changeset/add-pdf-command.md b/.changeset/add-pdf-command.md new file mode 100644 index 000000000..7f31d3191 --- /dev/null +++ b/.changeset/add-pdf-command.md @@ -0,0 +1,5 @@ +--- +"@browserbasehq/browse-cli": minor +--- + +Add `browse pdf [path]` command to save the current page as a PDF. Supports `--landscape`, `--format` (letter, legal, a4, a3), `--scale`, and `--no-background` options. Returns base64-encoded PDF when no path is given. diff --git a/packages/cli/src/index.ts b/packages/cli/src/index.ts index be6081fb0..56a44819c 100644 --- a/packages/cli/src/index.ts +++ b/packages/cli/src/index.ts @@ -1582,6 +1582,49 @@ async function executeCommand( } } + // PDF + case "pdf": { + const [opts] = args as [ + { + path?: string; + landscape?: boolean; + printBackground?: boolean; + scale?: number; + format?: string; + }?, + ]; + const cdpSession = page!.mainFrame().session; + const paperSizes: Record = { + letter: { width: 8.5, height: 11 }, + legal: { width: 8.5, height: 14 }, + a4: { width: 8.27, height: 11.69 }, + a3: { width: 11.69, height: 16.54 }, + }; + const paper = + paperSizes[(opts?.format ?? "letter").toLowerCase()] ?? + paperSizes.letter; + const result = await cdpSession.send<{ data: string }>( + "Page.printToPDF", + { + landscape: opts?.landscape ?? false, + printBackground: opts?.printBackground ?? true, + scale: opts?.scale ?? 1, + paperWidth: paper.width, + paperHeight: paper.height, + marginTop: 0.4, + marginBottom: 0.4, + marginLeft: 0.4, + marginRight: 0.4, + preferCSSPageSize: true, + }, + ); + if (opts?.path) { + await fs.writeFile(opts.path, Buffer.from(result.data, "base64")); + return { saved: opts.path }; + } + return { base64: result.data }; + } + // Daemon control case "stop": { process.nextTick(() => { @@ -2756,6 +2799,34 @@ networkCmd } }); +// ==================== PDF ==================== + +program + .command("pdf [path]") + .description("Save page as PDF") + .option("--landscape", "Landscape orientation") + .option("--no-background", "Omit background graphics") + .option("--scale ", "Scale factor (0.1-2)", "1") + .option("--format ", "Paper format: letter, legal, a4, a3", "letter") + .action(async (filePath: string | undefined, cmdOpts) => { + const opts = program.opts(); + try { + const result = await runCommand("pdf", [ + { + path: filePath, + landscape: cmdOpts.landscape, + printBackground: cmdOpts.background !== false, + scale: parseFloat(cmdOpts.scale), + format: cmdOpts.format, + }, + ]); + output(result, opts.json ?? false); + } catch (e) { + console.error("Error:", e instanceof Error ? e.message : e); + process.exit(1); + } + }); + // ==================== RUN ==================== program.parse(); From 716a487b097e0060e391fec10b6395ae56947994 Mon Sep 17 00:00:00 2001 From: Derek Meegan Date: Sun, 29 Mar 2026 14:34:37 -0700 Subject: [PATCH 2/4] fix: validate --scale and --format for pdf command Reject invalid scale values (must be 0.1-2) and unknown format values (must be letter, legal, a4, or a3) with clear error messages instead of silently falling back. Co-Authored-By: Claude Opus 4.6 (1M context) --- packages/cli/src/index.ts | 14 +++++++++++++- 1 file changed, 13 insertions(+), 1 deletion(-) diff --git a/packages/cli/src/index.ts b/packages/cli/src/index.ts index 56a44819c..2f5fb2597 100644 --- a/packages/cli/src/index.ts +++ b/packages/cli/src/index.ts @@ -2811,12 +2811,24 @@ program .action(async (filePath: string | undefined, cmdOpts) => { const opts = program.opts(); try { + const scale = parseFloat(cmdOpts.scale); + if (isNaN(scale) || scale < 0.1 || scale > 2) { + console.error("Error: --scale must be a number between 0.1 and 2"); + process.exit(1); + } + const validFormats = ["letter", "legal", "a4", "a3"]; + if (!validFormats.includes(cmdOpts.format.toLowerCase())) { + console.error( + `Error: --format must be one of: ${validFormats.join(", ")}`, + ); + process.exit(1); + } const result = await runCommand("pdf", [ { path: filePath, landscape: cmdOpts.landscape, printBackground: cmdOpts.background !== false, - scale: parseFloat(cmdOpts.scale), + scale, format: cmdOpts.format, }, ]); From 57ab187ce012b9397325fb3784db109ed66ae9a4 Mon Sep 17 00:00:00 2001 From: Derek Meegan Date: Sun, 29 Mar 2026 16:07:46 -0700 Subject: [PATCH 3/4] fix: add page null guard in pdf command Co-Authored-By: Claude Opus 4.6 (1M context) --- packages/cli/src/index.ts | 5 ++++- 1 file changed, 4 insertions(+), 1 deletion(-) diff --git a/packages/cli/src/index.ts b/packages/cli/src/index.ts index 2f5fb2597..5de244291 100644 --- a/packages/cli/src/index.ts +++ b/packages/cli/src/index.ts @@ -1584,6 +1584,9 @@ async function executeCommand( // PDF case "pdf": { + if (!page) { + return { error: "No page open. Navigate to a URL first." }; + } const [opts] = args as [ { path?: string; @@ -1593,7 +1596,7 @@ async function executeCommand( format?: string; }?, ]; - const cdpSession = page!.mainFrame().session; + const cdpSession = page.mainFrame().session; const paperSizes: Record = { letter: { width: 8.5, height: 11 }, legal: { width: 8.5, height: 14 }, From e8457cb6c1c352b74e32150ef81a0dcc45193360 Mon Sep 17 00:00:00 2001 From: Derek Meegan Date: Tue, 31 Mar 2026 13:11:15 -0700 Subject: [PATCH 4/4] Downgrade changeset to patch per review feedback Co-Authored-By: Claude Opus 4.6 (1M context) --- .changeset/add-pdf-command.md | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/.changeset/add-pdf-command.md b/.changeset/add-pdf-command.md index 7f31d3191..186ca836a 100644 --- a/.changeset/add-pdf-command.md +++ b/.changeset/add-pdf-command.md @@ -1,5 +1,5 @@ --- -"@browserbasehq/browse-cli": minor +"@browserbasehq/browse-cli": patch --- Add `browse pdf [path]` command to save the current page as a PDF. Supports `--landscape`, `--format` (letter, legal, a4, a3), `--scale`, and `--no-background` options. Returns base64-encoded PDF when no path is given.