/download API
The /download
API is used for returning files Chrome has downloaded during the execution of puppeteer code, which is ran inside context of the browser. Browserless sets up a blank page, a fresh download directory, injects your puppeteer code, and then executes it.
You can load external libraries via the import
syntax, and import ESM-style modules that are written for execution inside of the browser. Once your script is finished, any downloaded files from Chromium are returned back with the appropriate content-type header.
You can check the full Open API schema here.
If your download request doesn't result in a file being downloaded, Browserless will likely time out the function.
Example
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)
Approach using Browserless
Instead of monitoring the file system, send an HTTP request to Browserless to handle file downloads automatically. The code below does just that for you.
Core JavaScript Code
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();
});
// Add delay to ensure download completes
await new Promise(r => setTimeout(r, 1000));
}
Implementation Examples
- 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 () => {
try {
console.log("Testing JavaScript download functionality...");
const response = await fetch(url, {
method: 'POST',
headers: headers,
body: data
});
console.log("Response status:", response.status);
console.log("Response headers:", Object.fromEntries(response.headers.entries()));
if (response.ok) {
const buffer = await response.arrayBuffer();
await writeFile("data.json", Buffer.from(buffer));
console.log("File saved as data.json");
const content = Buffer.from(buffer).toString('utf-8');
console.log("Downloaded content:", content);
} else {
console.error("Request failed:", response.status, response.statusText);
const errorText = await response.text();
console.error("Error details:", errorText);
}
} catch (error) {
console.error("Error:", error.message);
}
};
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));
};
"""
def test_download():
try:
print("Testing Python download functionality...")
print(f"URL: {url}")
print(f"Headers: {headers}")
response = requests.post(url, headers=headers, data=data)
print(f"Response status: {response.status_code}")
print(f"Response headers: {dict(response.headers)}")
if response.ok:
with open("data.json", "wb") as file:
file.write(response.content)
print("File saved as data.json")
content = response.content.decode('utf-8')
print(f"Downloaded content: {content}")
else:
print(f"Request failed: {response.status_code} {response.reason}")
print(f"Error details: {response.text}")
except Exception as e:
print(f"Error: {e}")
if __name__ == "__main__":
test_download()
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 {
System.out.println("Testing Java download functionality...");
System.out.println("URL: " + url);
System.out.println("Headers: Content-Type: application/javascript");
HttpResponse<String> response = client.send(request, HttpResponse.BodyHandlers.ofString());
System.out.println("Response status: " + response.statusCode());
System.out.println("Response headers: " + response.headers().map());
if (response.statusCode() == 200) {
String content = response.body();
try (FileWriter writer = new FileWriter("data.json")) {
writer.write(content);
System.out.println("File saved as data.json");
}
System.out.println("Downloaded content: " + content);
} else {
System.out.println("Request failed: " + response.statusCode());
System.out.println("Error details: " + response.body());
}
} catch (Exception e) {
System.out.println("Error: " + e.getMessage());
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 = @"
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
{
Console.WriteLine("Testing C# download functionality...");
Console.WriteLine($"URL: {url}");
Console.WriteLine("Headers: Content-Type: application/javascript");
var response = await client.PostAsync(url, content);
Console.WriteLine($"Response status: {(int)response.StatusCode}");
Console.WriteLine($"Response headers: {response.Headers}");
if (response.IsSuccessStatusCode)
{
var responseContent = await response.Content.ReadAsStringAsync();
await File.WriteAllTextAsync("data.json", responseContent);
Console.WriteLine("File saved as data.json");
Console.WriteLine($"Downloaded content: {responseContent}");
}
else
{
Console.WriteLine($"Request failed: {(int)response.StatusCode} {response.ReasonPhrase}");
var errorContent = await response.Content.ReadAsStringAsync();
Console.WriteLine($"Error details: {errorContent}");
}
}
catch (Exception ex)
{
Console.WriteLine($"Error: {ex.Message}");
Console.WriteLine($"Stack trace: {ex.StackTrace}");
}
}
}
This API is sensitive to the downloaded file and will return an appropriate Content-Type
with the response.
Import 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
- 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);
}
}
}
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 thecode
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' \
# 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
}
}''
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'
};
// Minified code
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'
}
# 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
}
}
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);
}
}
}