Docs
Dashboard
Examples / Browser + shellBeta

Screenshots to a PDF report

Screenshot several pages in the session's browser, then combine them into one PDF with Python (Pillow) in the session's shell.

When to use it: You want one PDF of several pages, for a report or a record.

Usesthe actions API (goto, screenshot), files.write, exec (Python, Pillow), files.read
Needsa plan with shell sessions; no model
Sitebooks.toscrape.com, quotes.toscrape.com and httpbin.org
Outputoutput/shot-N.png and output/report.pdf
LanguagesNode and Python

combine.py is the Python script both versions upload and run in the session.

The code

The example as it is in its folder. Both versions do the same job and write the same output/, so one result check covers both.

/** * Screenshots to a PDF report: screenshot several pages in the session's browser, then combine them into one PDF with * Python (Pillow) in the session's shell. * *   npx tsx node/index.ts            (BOXLINE_API_KEY; URLS: comma-separated pages; a plan with shell sessions) * * Writes output/shot-N.png and output/report.pdf. */import { mkdirSync, readFileSync, writeFileSync } from "node:fs";import { join } from "node:path";import { Boxline } from "@boxline/sdk";const out = process.env.OUTPUT_DIR ?? "output";const urls = (process.env.URLS ?? "https://books.toscrape.com/,https://quotes.toscrape.com/,https://httpbin.org/").split(",").map((u) => u.trim()).filter(Boolean);const bx = new Boxline();const session = await bx.sessions.create({ shell: true, timeout: 600, userMetadata: { example: "screenshots-to-pdf" } });console.log(`Session: ${session.id}`);try {  mkdirSync(out, { recursive: true });  const shots: string[] = [];  const pages: { url: string; title: string; file: string }[] = [];  for (const [i, url] of urls.entries()) {    // The actions API: open the page and screenshot it (base64 PNG), then keep it in the workspace for the shell.    const { title } = await session.goto(url);    const shot = await session.screenshot();    const png = Buffer.from(shot.data, "base64");    const file = `output/shot-${i + 1}.png`;    await session.files.write(file, png);    writeFileSync(join(out, `shot-${i + 1}.png`), png);    shots.push(file);    pages.push({ url, title, file });    console.log(`Saved ${file}: ${title}`);  }  await session.files.write("combine.py", readFileSync(new URL("../combine.py", import.meta.url)));  const r = await session.exec(`python3 combine.py ${shots.join(" ")}`);  if (r.exitCode !== 0) throw new Error(`Pillow failed: ${r.stderr.trim()}`);  const pdf = await session.files.read("output/report.pdf");  writeFileSync(join(out, "report.pdf"), pdf);  console.log(`output/report.pdf: ${r.stdout.trim()} pages, ${Math.round(pdf.length / 1024)} KB`);  writeFileSync(join(out, "result.json"), JSON.stringify({ pages, pdfPages: Number(r.stdout.trim()), pdfBytes: pdf.length }, null, 2));} finally {  await session.stop();}
combine.py
"""Runs in the session's shell: combines the screenshots given as arguments into output/report.pdf, one page each,with Pillow (installed in the shell). Prints the number of pages."""import sysfrom PIL import Imagepages = [Image.open(path).convert("RGB") for path in sys.argv[1:]]pages[0].save("output/report.pdf", save_all=True, append_images=pages[1:], resolution=96)print(len(pages))

Inputs

Environment variables the example reads:

  • URLS: the pages, comma-separated (default https://books.toscrape.com/,https://quotes.toscrape.com/,https://httpbin.org/).

Run it

Get the examples with git clone https://github.com/Boxline-dev/examples.git and open this one: cd examples/screenshots-to-pdf. Put your API key in BOXLINE_API_KEY (and BOXLINE_API_URL for another API), then run either version from the example’s folder. Both write to output/ and stop their sessions when they finish.

# Node 18 or newer, in the example's folderexport BOXLINE_API_KEY=…   # your API keynpm install @boxline/sdk tsxnpx tsx node/index.ts

Then check the result, from the same folder: npx tsx check.ts output. It exits with 0 only when the result is right.

What its check proves

check.ts reads what the example wrote and passes only when the result is right, not merely when the example ran.

Report.pdf has one page per screenshot, and every screenshot is a PNG of a loaded page.

Source

github.com/Boxline-dev/examples/screenshots-to-pdf on GitHub, with its README.md, check.ts and .env.example. The examples are open source. See all examples.

These docs describe a beta API. Endpoints, fields and SDK methods may change before general availability; breaking changes will be listed in the changelog.