Skip to main content
Libretto provides two ways to make HTTP requests from within a workflow: pageRequest() for API calls, and the download helpers for file downloads.

pageRequest()

Executes a fetch() call inside the browser context via page.evaluate(). Because the request runs inside the real browser process, it uses the browser’s TLS fingerprint, cookies, and session — the same as what the site’s own JavaScript would send. This avoids bot-detection issues that arise when making the same request from Node.js directly.
async function pageRequest<T extends z.ZodType | undefined = undefined>(
  page: Page,
  config: RequestConfig,
  options?: PageRequestOptions<T>
): Promise<PageRequestResult<T>>
The return type is z.infer<T> when a schema is provided, or any otherwise.
Non-2xx responses cause pageRequest to throw an error. The error message includes the HTTP method, URL, and status code.

RequestConfig

url
string
required
The URL to fetch. Relative URLs are resolved in the browser context.
method
"GET" | "POST" | "PUT" | "DELETE" | "PATCH"
HTTP method. Defaults to "GET".
headers
Record<string, string>
Additional request headers to merge with any that bodyType adds automatically.
body
Record<string, any> | string
Request body. When bodyType is "json" (the default), objects are serialized with JSON.stringify. When bodyType is "form", objects are encoded as application/x-www-form-urlencoded.
bodyType
"json" | "form"
How to serialize the body. Defaults to "json". Setting this to "form" also sets Content-Type: application/x-www-form-urlencoded automatically.
responseType
"json" | "text" | "xml"
How to parse the response. Defaults to "json". Both "text" and "xml" return the raw response text.

PageRequestOptions<T>

logger
MinimalLogger
Optional logger. When provided, request details (method, URL, status, duration) are logged at info level, and failures at warn.
schema
T extends z.ZodType
Optional Zod schema. When provided, the parsed response body is validated with schema.parse() before being returned. The return type of pageRequest becomes z.infer<T>.

Example

import { pageRequest } from "libretto";
import { z } from "zod";

const ResultSchema = z.object({
  items: z.array(z.object({ id: z.string(), name: z.string() })),
  total: z.number(),
});

const data = await pageRequest(
  page,
  {
    url: "/api/search",
    method: "POST",
    body: { query: "example", page: 1 },
  },
  { schema: ResultSchema }
);
// data is typed as { items: Array<{ id: string; name: string }>; total: number }

downloadViaClick()

Triggers a file download by clicking a DOM element and intercepts the resulting download using Playwright’s download event. The download promise is registered before the click so the event is never missed.
async function downloadViaClick(
  page: Page,
  selector: string,
  options?: DownloadViaClickOptions
): Promise<DownloadResult>

Parameters

page
Page
required
The Playwright Page to operate on.
selector
string
required
CSS selector for the element that triggers the download when clicked.
options
DownloadViaClickOptions

DownloadResult

buffer
Buffer
The raw file contents.
filename
string
The filename suggested by the server via the Content-Disposition header or the URL.

Example

import { downloadViaClick } from "libretto";

const { buffer, filename } = await downloadViaClick(page, "#export-btn", {
  logger,
  timeout: 60_000,
});

console.log(`Downloaded ${filename} (${buffer.length} bytes)`);

downloadAndSave()

Convenience wrapper around downloadViaClick() that also writes the downloaded file to disk.
async function downloadAndSave(
  page: Page,
  selector: string,
  options?: SaveDownloadOptions
): Promise<DownloadResult & { savedTo: string }>

Parameters

page
Page
required
The Playwright Page to operate on.
selector
string
required
CSS selector for the element that triggers the download when clicked.
options
SaveDownloadOptions

Return value

Returns DownloadResult & { savedTo: string } — the same buffer and filename as downloadViaClick, plus:
savedTo
string
The absolute path the file was written to.

Example

import { downloadAndSave } from "libretto";

const { filename, savedTo } = await downloadAndSave(
  page,
  "#export-btn",
  { savePath: "/tmp/report.csv", logger }
);

console.log(`Saved ${filename} to ${savedTo}`);

Build docs developers (and LLMs) love