Skip to main content

/download API

The /download API runs your Puppeteer code in a browser and returns files Chrome downloaded, with appropriate Content-Type and Content-Disposition headers. You can load external libraries via import and use ESM modules that run inside the browser context. If your download request doesn't result in a file being downloaded, Browserless will time out the function.

You can check the full Open API schema here.

Quick Start

curl -X POST \\  
https://production-sfo.browserless.io/download?token=YOUR_API_TOKEN_HERE \\
-H 'Content-Type: application/javascript' \\
-d 'export default async function ({ page }) {
await page.evaluate(() => {
const json = { ping: "pong", rnd: [...Array(5)].map(() => Math.random()) };
const jsonContent = `data:application/json,${JSON.stringify(json)}`;
const encodedUri = encodeURI(jsonContent);
const link = document.createElement("a");
link.setAttribute("href", encodedUri);
link.setAttribute("download", "data.json");
document.body.appendChild(link);
link.click();
});
await new Promise(r => setTimeout(r, 1000));
};'

Response

The API returns the downloaded file with appropriate headers:

HTTP/1.1 200 OK
Content-Type: application/json
Content-Disposition: attachment; filename="data.json"

{"ping":"pong","rnd":[854246,114512,212580,482122,107878]}

Additional Examples and Configuration

Local Puppeteer Example (Reference)

Here's an example of downloading a file using local Puppeteer:

import puppeteer from "puppeteer";

async function run() {
const browser = await puppeteer.launch();
const page = await browser.newPage();

// Here we generate a json file and have the browser download it
await page.evaluate(() => {
const json = {
ping: "pong",
rnd: [...Array(5)].map(() => Math.random()),
};
const jsonContent = `data:application/json,${JSON.stringify(json)}`;
const encodedUri = encodeURI(jsonContent);
const link = document.createElement("a");

link.setAttribute("href", encodedUri);
link.setAttribute("download", "data.json");
document.body.appendChild(link);
return link.click();
});
await browser.close();
}

run();

Limitations of Local Puppeteer Setup

  • Downloads go to your local Downloads folder
  • No easy way to programmatically access downloaded files
  • Requires complex file system monitoring
  • High resource usage (runs full Chrome locally)

Importing Libraries

Both the /function and /download API environments support ECMAScript modules, allowing you to use import syntax to load modules directly from HTTP URLs. For example, let's import the Faker.js library:

JS Code

import { faker } from "https://esm.sh/@faker-js/faker";

export default async function ({ page }) {
const rndName = faker.person.fullName();
const rndEmail = faker.internet.email();

await page.evaluate(
(name, email) => {
const jsonStr = JSON.stringify({ name, email });
const jsonContent = `data:application/json,${jsonStr}`;
const encodedUri = encodeURI(jsonContent);
const link = document.createElement("a");

link.setAttribute("href", encodedUri);
link.setAttribute("download", "data.json");
document.body.appendChild(link);
return link.click();
},
rndName,
rndEmail
);
}
curl -X POST \
"https://production-sfo.browserless.io/download?token=YOUR_API_TOKEN_HERE" \
-H 'Content-Type: application/javascript' \
-d 'import { faker } from '\''https://esm.sh/@faker-js/faker'\'';

export default async function ({ page }) {
const rndName = faker.person.fullName();
const rndEmail = faker.internet.email();

await page.evaluate((name, email) => {
const jsonStr = JSON.stringify({name, email});
const jsonContent = `data:application/json,${jsonStr}`;
const encodedUri = encodeURI(jsonContent);
const link = document.createElement("a");

link.setAttribute("href", encodedUri);
link.setAttribute("download", "data.json");
document.body.appendChild(link);
return link.click();
}, rndName, rndEmail);
}'

Example response

{
"name": "Jasmine Littel",
"email": "Giovanna26@hotmail.com"
}

JSON API

You can also use the /download API sending a JSON payload. You must send an object with the following values:

  • code: String, required — custom download code.
  • context: Object, optional — value used to pass context values and arguments to the code

Example

JS Code

export default async function ({ page, context }) {
await page.evaluate((context) => {
const json = {
url: context.url,
ping: "pong",
rnd: [...Array(context.arrayLen)].map(() => Math.random()),
};
const jsonContent = `data:application/json,${JSON.stringify(json)}`;
const encodedUri = encodeURI(jsonContent);
const link = document.createElement("a");

link.setAttribute("href", encodedUri);
link.setAttribute("download", "data.json");
document.body.appendChild(link);
return link.click();
}, context);
}
curl --request POST \
--url 'https://production-sfo.browserless.io/download?token=YOUR_API_TOKEN_HERE' \
--header 'Content-Type: application/json' \
# Minified code
--data '{
"code": "export default async function({page:t,context:a}){await t.evaluate(t=>{let a={url:t.url,ping:`pong`,rnd:[...Array(t.arrayLen)].map(()=>Math.random())},e=`data:application/json,${JSON.stringify(a)}`,n=encodeURI(e),r=document.createElement(`a`);return r.setAttribute(`href`,n),r.setAttribute(`download`,`data.json`),document.body.appendChild(r),r.click()},a)};",
"context": {
"url": "https://browserless.io/",
"arrayLen": 10
}
}''