Appearance
Binary File Handling
If the automation needs to upload or download files — zips, images, documents — page.evaluate() sits between Node.js and the browser, and it can only pass JSON-serializable data. Buffers and file handles don't survive the crossing.
Problem: You Need to Upload a File
The file exists on disk in Node.js, but the upload endpoint expects a request from the browser context (possibly with session cookies).
Solution: base64-encode on the Node side, decode to a Blob in the browser, POST via FormData:
javascript
import { readFileSync } from "fs";
const zipBuffer = readFileSync("data.zip");
const zipBase64 = zipBuffer.toString("base64");
const result = await page.evaluate(
async ({ base64, fileName }) => {
const binary = atob(base64);
const bytes = Uint8Array.from(
binary,
(char) => char.charCodeAt(0),
);
const blob = new Blob(
[bytes],
{ type: "application/zip" },
);
const form = new FormData();
form.append("file", blob, fileName);
const res = await fetch("/api/upload", {
method: "POST",
body: form,
});
return {
status: res.status,
body: await res.json(),
};
},
{ base64: zipBase64, fileName: "data.zip" },
);Auth headers are included automatically because fetch runs in the page context.
Problem: You Need to Download a File
The file is on the server and may be behind authentication. Direct HTTP requests from Node.js would require extracting session tokens.
Solution: fetch in the browser context, base64-encode the response, return to Node:
javascript
const base64 = await page.evaluate(async (url) => {
const res = await fetch(url);
const buffer = await res.arrayBuffer();
const bytes = new Uint8Array(buffer);
let binary = "";
for (const byte of bytes) {
binary += String.fromCharCode(byte);
}
return btoa(binary);
}, "/api/download/file.zip");
const fileBuffer = Buffer.from(base64, "base64");
writeFileSync("downloaded.zip", fileBuffer);Why Base64
page.evaluate() serializes arguments and return values as JSON. Binary data cannot survive JSON serialization — bytes get corrupted or lost. Base64 encodes binary as ASCII text, which JSON handles cleanly. The ~33% size overhead is acceptable for the file sizes typical in automation workflows.