Screenshots

Browserbase enables screen view and full-screen screenshots using your desired browser automation framework with the following configuration:

Screenshot typeDPIFormat
Screen view (default)80jpeg
Full-screen90jpeg

Save a screenshot locally

A screenshot taken with Browserbase can be saved locally as a file:

import { writeFileSync } from "fs";
import { chromium } from "playwright-core";

(async () => {
  console.log("Starting remote browser...")
  const browser = await chromium.connectOverCDP(
      // we connect to a Session created via the API
      `wss://connect.browserbase.com?apiKey=${process.env.BROWSERBASE_API_KEY}&sessionId=${sessionId}`,
  );
  const defaultContext = browser.contexts()[0];
  const page = defaultContext.pages()[0];

  await page.goto("https://www.browserbase.com", {
      // let's make sure the page is fully loaded before taking the screenshot
      waitUntil: "domcontentloaded",
  });

  console.log("Taking a screenshot!")

  const buf = await page.screenshot({ fullPage: true })
  writeFileSync('screenshot.jpeg', buf)

  console.log("Shutting down...")
  await page.close();
  await browser.close();
})().catch((error) => {
  console.error(error)
}

PDFs

In addition to downloading files, you can also download web pages.

For playwright, you can use the page.pdf() method to download a web page as a PDF.

After creating the session, we download the page in the A4 format and save it as webpage.pdf.

Save a PDF locally

Here’s how to generate and save a PDF locally using Playwright:

Playwright
import { chromium } from "playwright-core";

(async () => {
  console.log("Starting remote browser...");
  // we connect to a Session created via the API
  const browser = await chromium.connectOverCDP(
    `wss://connect.browserbase.com?apiKey=${process.env.BROWSERBASE_API_KEY}`,
  );

  const defaultContext = browser.contexts()[0];
  const page = defaultContext.pages()[0];

  await page.goto("https://www.browserbase.com", {
    // let's make sure the page is fully loaded before taking the screenshot
    waitUntil: "domcontentloaded",
  });

  console.log("Generating PDF...");

  await page.pdf({
    path: "webpage.pdf",
    format: "A4",
  });

  console.log("Shutting down...");
  await page.close();
  await browser.close();
})().catch((error) => {
  console.error(error);
});

Downloads

Unlike screenshots and PDFs which are saved locally, files downloaded during browser automation are stored in Browserbase’s cloud storage. These files must be retrieved using our API.

A typical use case for headless browsers is downloading files from web pages. Our browsers are configured to sync any file you download to our storage infrastructure. We add a Unix timestamp onto the end of the file name to avoid naming conflicts when downloading multiple files (e.g., sample.pdf will become sample-1719265797164.pdf).

Follow these steps to download files:

  1. Use the Sessions API to create a new session. You’ll need the session ID for when you connect.
  2. Configure your library’s downloads location.
  3. Perform the download action in your automation script.
  4. Retrieve the downloaded files using the Session Downloads API.
import { chromium } from "playwright-core";
import { writeFileSync } from "node:fs";

async function saveDownloadsOnDisk(sessionId: string, retryForSeconds: number) {
  return new Promise<void>((resolve, reject) => {
    let pooler;
    const timeout = setTimeout(() => {
      if (pooler) {
        clearInterval(pooler);
      }
    }, retryForSeconds);
    async function fetchDownloads() {
      try {
        const response = await fetch(
          `https://api.browserbase.com/v1/sessions/${sessionId}/downloads`,
          {
            method: "GET",
            headers: {
              "x-bb-api-key": process.env.BROWSERBASE_API_KEY!,
            },
          },
        );
        const arrayBuffer = await response.arrayBuffer();
        if (arrayBuffer.byteLength > 0) {
          const buffer = Buffer.from(arrayBuffer);
          writeFileSync("downloads.zip", buffer);
          clearInterval(pooler);
          clearTimeout(timeout);
          resolve();
        }
      } catch (e) {
        clearInterval(pooler);
        clearTimeout(timeout);
        reject(e);
      }
    }
    pooler = setInterval(fetchDownloads, 2000);
  });
}

(async () => {
  // `createSession()` performs a call to the Sessions API
  const { id: sessionId } = await createSession();
  const browser = await chromium.connectOverCDP(
    // we connect to a Session created via the API
    `wss://connect.browserbase.com?apiKey=${process.env.BROWSERBASE_API_KEY}&sessionId=${sessionId}`,
  );
  const defaultContext = browser.contexts()[0];
  const page = defaultContext.pages()[0];

  // Required to avoid playwright overriding location
  const client = await defaultContext.newCDPSession(page);
  await client.send("Browser.setDownloadBehavior", {
    behavior: "allow",
    downloadPath: "downloads",
    eventsEnabled: true,
  });

  await page.goto("https://browser-tests-alpha.vercel.app/api/download-test");

  const [download] = await Promise.all([
    page.waitForEvent("download"),
    page.locator("#download").click(),
  ]);

  let downloadError = await download.failure();
  if (downloadError !== null) {
    console.log("Error happened on download:", downloadError);
    throw new Error(downloadError);
  }

  await page.close();
  await browser.close();

  if (!downloadError) {
    // wait up to 20s to save the downloaded files locally
    await saveDownloadsOnDisk(sessionId, 20000);
  }
})().catch((error) => console.error(error.message));

We sync the files in real-time; the size of your downloads might affect their immediate availability through the /downloads endpoint. The above code provides a snippet to handle that use case.

Session Downloads API

Learn more about the available params and response fields

Uploads

You can easily upload files to websites using Playwright, Puppeteer, or Selenium.

Playwright

For Playwright, you can upload files directly from your local path.

  1. You’ll need your file to be available where you’re running your Playwright code.

  2. In this example, we’re using an image logo.png that’s available locally.

  3. Be sure to specify the path to your file by setting the input file.

import { chromium } from "playwright-core";

(async () => {
  const url = "https://browser-tests-alpha.vercel.app/api/upload-test";
  const browser = await chromium.connectOverCDP(
    `wss://connect.browserbase.com?apiKey=${process.env.BROWSERBASE_API_KEY}`,
  );

  const defaultContext = browser.contexts()[0];
  const page = defaultContext.pages()[0];

  await page.goto(url);

  const fileInput = page.locator("#fileUpload");
  // logo.png is available relative to the current working directory
  await fileInput.setInputFiles("logo.png");

  await browser.close();
})().catch((error) => console.error(error.message));

For Puppeteer and Selenium, you’ll need to upload your files to our browser instance using our Uploads API.

  1. Use the Sessions API to create a new session. You’ll need the session ID when you upload it.

  2. Use the Session Uploads API to upload a file.

  3. Connect to the browser and the file will be available in the /tmp/.uploads directory.

import axios from "axios";
import path from "path";
import puppeteer, { ElementHandle } from "puppeteer-core";
import fs from "fs";
import FormData from "form-data";

async function createUpload(
  sessionId: string,
  filePath: string,
): Promise<void> {
  const apiKey = process.env.BROWSERBASE_API_KEY;
  if (!apiKey) {
    console.error("Browserbase API key is not defined.");
  }

  try {
    const form = new FormData();
    form.append("file", fs.createReadStream(filePath));

    const options = {
      method: "POST",
      url: `https://api.browserbase.com/v1/sessions/${sessionId}/uploads`,
      headers: {
        "x-bb-api-key": apiKey,
        "Content-Type": "multipart/form-data",
      },
      data: form,
    };

    const response = await axios(options);
    console.log(response.data);
  } catch (error) {
    console.error(`Failed to create upload: ${error}`);
    throw error;
  }
}

(async () => {
  const session = await createSession();

  const localFilePath = path.join(process.cwd(), "logo.png");
  const remoteFilePath = "/tmp/.uploads/logo.png";

  await createUpload(session.id, localFilePath);

  const url = "https://browser-tests-alpha.vercel.app/api/upload-test";

  // Launch a browser instance
  const browser = await puppeteer.connect({
    browserWSEndpoint: `wss://connect.browserbase.com?apiKey=${process.env.BROWSERBASE_API_KEY}&sessionId=${session.id}`,
  });

  // Create a new page
  const page = await browser.newPage();

  // Navigate to the page containing the form
  await page.goto(url);

  // Locate the file input element and upload the file
  const input = (await page.$("#fileUpload")) as ElementHandle<any>;
  await input.uploadFile(remoteFilePath);

  await browser.close();
})().catch((error) => console.error(error.message));