/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.
The /download API supports two request formats:
- Raw JavaScript (
Content-Type: application/javascript) - Simple and supports ESM imports directly. Best for straightforward use cases. - JSON Payload (
Content-Type: application/json) - Easier for sending long or minified code and passing context variables. Best when you need to parameterize your code.
Method 1: Send JavaScript Code (application/javascript)
This method sends your JavaScript code directly as the request body with Content-Type: application/javascript.
Basic Example
- cURL
- JavaScript
- Python
- Java
- C#
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));
};'
import { writeFile } from 'fs/promises';
const TOKEN = "YOUR_API_TOKEN_HERE";
const url = `https://production-sfo.browserless.io/download?token=${TOKEN}`;
const headers = {
"Content-Type": "application/javascript"
};
const data = `
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));
};
`;
const downloadFile = async () => {
const response = await fetch(url, {
method: 'POST',
headers: headers,
body: data
});
if (response.ok) {
const buffer = await response.arrayBuffer();
await writeFile("data.json", Buffer.from(buffer));
console.log("File saved as data.json");
} else {
console.error("Request failed:", response.status, response.statusText);
}
};
downloadFile();
import requests
TOKEN = "YOUR_API_TOKEN_HERE"
url = f"https://production-sfo.browserless.io/download?token={TOKEN}"
headers = {
"Content-Type": "application/javascript"
}
data = """
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 = requests.post(url, headers=headers, data=data)
if response.ok:
with open("data.json", "wb") as file:
file.write(response.content)
print("File saved as data.json")
else:
print(f"Request failed: {response.status_code} {response.reason}")
import java.io.*;
import java.net.*;
import java.net.http.*;
import java.time.Duration;
public class DownloadJsonFile {
public static void main(String[] args) {
String TOKEN = "YOUR_API_TOKEN_HERE";
String url = "https://production-sfo.browserless.io/download?token=" + TOKEN;
String javascriptCode = """
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));
};
""";
HttpClient client = HttpClient.newBuilder()
.connectTimeout(Duration.ofSeconds(30))
.build();
HttpRequest request = HttpRequest.newBuilder()
.uri(URI.create(url))
.header("Content-Type", "application/javascript")
.timeout(Duration.ofSeconds(60))
.POST(HttpRequest.BodyPublishers.ofString(javascriptCode))
.build();
try {
HttpResponse<String> response = client.send(request, HttpResponse.BodyHandlers.ofString());
if (response.statusCode() == 200) {
try (FileWriter writer = new FileWriter("data.json")) {
writer.write(response.body());
System.out.println("File saved as data.json");
}
} else {
System.out.println("Request failed: " + response.statusCode());
}
} catch (Exception e) {
System.out.println("Error: " + e.getMessage());
}
}
}
using System;
using System.IO;
using System.Net.Http;
using System.Text;
using System.Threading.Tasks;
class Program
{
static async Task Main(string[] args)
{
string TOKEN = "YOUR_API_TOKEN_HERE";
string url = $"https://production-sfo.browserless.io/download?token={TOKEN}";
string javascriptCode = @"
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));
};";
using var client = new HttpClient();
client.Timeout = TimeSpan.FromSeconds(60);
var content = new StringContent(javascriptCode, Encoding.UTF8, "application/javascript");
try
{
var response = await client.PostAsync(url, content);
if (response.IsSuccessStatusCode)
{
var responseContent = await response.Content.ReadAsStringAsync();
await File.WriteAllTextAsync("data.json", responseContent);
Console.WriteLine("File saved as data.json");
}
else
{
Console.WriteLine($"Request failed: {(int)response.StatusCode} {response.ReasonPhrase}");
}
}
catch (Exception ex)
{
Console.WriteLine($"Error: {ex.Message}");
}
}
}
Response
HTTP/1.1 200 OK
Content-Type: application/json
Content-Disposition: attachment; filename="data.json"
{"ping":"pong","rnd":[0.854246,0.114512,0.212580,0.482122,0.107878]}
Using External Libraries
The /download API supports 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
- JavaScript
- Python
- Java
- C#
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);
}'
import { writeFile } from 'fs/promises';
const TOKEN = "YOUR_API_TOKEN_HERE";
const url = `https://production-sfo.browserless.io/download?token=${TOKEN}`;
const headers = {
"Content-Type": "application/javascript"
};
const data = `
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);
link.click();
}, rndName, rndEmail);
};
`;
const downloadFile = async () => {
const response = await fetch(url, {
method: 'POST',
headers: headers,
body: data
});
const buffer = await response.arrayBuffer();
await writeFile("data.json", Buffer.from(buffer));
console.log("File saved as data.json");
};
downloadFile();
import requests
TOKEN = "YOUR_API_TOKEN_HERE"
url = f"https://production-sfo.browserless.io/download?token={TOKEN}"
headers = {
"Content-Type": "application/javascript"
}
data = """
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);
link.click();
}, rndName, rndEmail);
};
"""
response = requests.post(url, headers=headers, data=data)
with open("data.json", "wb") as file:
file.write(response.content)
print("File saved as data.json")
import java.io.*;
import java.net.*;
import java.net.http.*;
public class DownloadJsonFileWithFaker {
public static void main(String[] args) {
String TOKEN = "YOUR_API_TOKEN_HERE";
String url = "https://production-sfo.browserless.io/download?token=" + TOKEN;
String javascriptCode = """
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);
link.click();
}, rndName, rndEmail);
};
""";
HttpClient client = HttpClient.newHttpClient();
HttpRequest request = HttpRequest.newBuilder()
.uri(URI.create(url))
.header("Content-Type", "application/javascript")
.POST(HttpRequest.BodyPublishers.ofString(javascriptCode))
.build();
try {
HttpResponse<InputStream> response = client.send(request, HttpResponse.BodyHandlers.ofInputStream());
try (InputStream in = response.body();
FileOutputStream fileOut = new FileOutputStream("data.json")) {
in.transferTo(fileOut);
System.out.println("File saved as data.json");
}
} catch (Exception e) {
e.printStackTrace();
}
}
}
using System;
using System.IO;
using System.Net.Http;
using System.Text;
using System.Threading.Tasks;
class Program
{
static async Task Main(string[] args)
{
string TOKEN = "YOUR_API_TOKEN_HERE";
string url = $"https://production-sfo.browserless.io/download?token={TOKEN}";
string javascriptCode = @"
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);
link.click();
}, rndName, rndEmail);
};";
using var client = new HttpClient();
var content = new StringContent(javascriptCode, Encoding.UTF8, "application/javascript");
try
{
var response = await client.PostAsync(url, content);
response.EnsureSuccessStatusCode();
using var stream = await response.Content.ReadAsStreamAsync();
using var fileStream = new FileStream("data.json", FileMode.Create, FileAccess.Write);
await stream.CopyToAsync(fileStream);
Console.WriteLine("File saved as data.json");
}
catch (Exception ex)
{
Console.WriteLine("Error: " + ex.Message);
}
}
}
Response
{
"name": "Jasmine Littel",
"email": "Giovanna26@hotmail.com"
}
Method 2: Send JSON Payload (code + context)
This method sends a JSON payload with Content-Type: application/json. This is useful for sending long or minified code and passing context variables to your function.
The JSON payload must include:
code: String, required — your JavaScript code as a stringcontext: Object, optional — variables to pass to your function
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
- JavaScript
- Python
- Java
- C#
curl --request POST \
--url 'https://production-sfo.browserless.io/download?token=YOUR_API_TOKEN_HERE' \
--header 'Content-Type: application/json' \
--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
}
}'
import { writeFile } from 'fs/promises';
const TOKEN = "YOUR_API_TOKEN_HERE";
const url = `https://production-sfo.browserless.io/download?token=${TOKEN}`;
const headers = {
'Content-Type': 'application/json'
};
const 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
}
};
const downloadFile = async () => {
const response = await fetch(url, {
method: 'POST',
headers: headers,
body: JSON.stringify(data)
});
const buffer = await response.arrayBuffer();
await writeFile("data.json", Buffer.from(buffer));
console.log("File saved as data.json");
};
downloadFile();
import requests
TOKEN = "YOUR_API_TOKEN_HERE"
url = f"https://production-sfo.browserless.io/download?token={TOKEN}"
headers = {
'Content-Type': 'application/json'
}
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
}
}
response = requests.post(url, headers=headers, json=data)
with open("data.json", "wb") as file:
file.write(response.content)
print("File saved as data.json")
import java.io.*;
import java.net.http.*;
import java.net.URI;
public class DownloadJsonFileWithMinifiedCode {
public static void main(String[] args) {
String TOKEN = "YOUR_API_TOKEN_HERE";
String url = "https://production-sfo.browserless.io/download?token=" + TOKEN;
String jsonData = """
{
"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
}
}
""";
HttpClient client = HttpClient.newHttpClient();
HttpRequest request = HttpRequest.newBuilder()
.uri(URI.create(url))
.header("Content-Type", "application/json")
.POST(HttpRequest.BodyPublishers.ofString(jsonData))
.build();
try {
HttpResponse<InputStream> response = client.send(request, HttpResponse.BodyHandlers.ofInputStream());
try (InputStream in = response.body();
FileOutputStream fileOut = new FileOutputStream("data.json")) {
in.transferTo(fileOut);
System.out.println("File saved as data.json");
}
} catch (Exception e) {
e.printStackTrace();
}
}
}
using System;
using System.IO;
using System.Net.Http;
using System.Text;
using System.Threading.Tasks;
class Program {
static async Task Main(string[] args) {
string TOKEN = "YOUR_API_TOKEN_HERE";
string url = $"https://production-sfo.browserless.io/download?token={TOKEN}";
string jsonData = @"
{
""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
}
}
";
using var client = new HttpClient();
var content = new StringContent(jsonData, Encoding.UTF8, "application/json");
try {
var response = await client.PostAsync(url, content);
response.EnsureSuccessStatusCode();
using var stream = await response.Content.ReadAsStreamAsync();
using var fileStream = new FileStream("data.json", FileMode.Create, FileAccess.Write);
await stream.CopyToAsync(fileStream);
Console.WriteLine("File saved as data.json");
} catch (Exception ex) {
Console.WriteLine("Error: " + ex.Message);
}
}
}
Response
{
"url": "https://browserless.io/",
"ping": "pong",
"rnd": [0.123456, 0.234567, 0.345678, 0.456789, 0.567890, 0.678901, 0.789012, 0.890123, 0.901234, 0.012345]
}
Reference: Local Puppeteer Comparison
Click to see how this works with local Puppeteer
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)