/function API
A quick way to run commands with Browserless is via our /function API. You can use Python, NodeJS or any other language that supports making HTTP requests, so you don't need to install any libraries on your end.
The /function endpoint allows for POSTing of custom code and context to run them with. The code function, which only supports puppeteer code, gets called with an object containing several properties: a page property, which is a puppeteer page object, and context which is the context you provide in the JSON body.
Functions should return an object with two properties: data and type. data can be whatever you'd like (Buffer, JSON, or plain text) and type is a string describing the Content-Type of data. Browserless reads both of these from your functions return value and resolves the request appropriately.
The /function API, like all REST APIs, automatically closes the browser session after execution completes. If you need to persist sessions or keep browsers alive between requests, consider using BaaS with session management or BrowserQL with the reconnect mutation.
You can view the complete Function API OpenAPI specification.
Basic Usage
Both the /function and the /download API environments use Ecmascript modules. You can use any code and native APIs available in the Chrome browser environment.
JS Code
export default async function ({ page }) {
const rndNumber = () => {
return Math.floor(Math.random() * (10**6 - 0));
};
await page.goto("https://example.com/");
const url = await page.title();
const numbers = [...Array(5)].map(() => rndNumber());
return {
data: {
url,
numbers,
},
// Make sure to match the appropriate content here
type: "application/json",
};
}
- cURL
- Javascript
- Python
- Java
- C#
curl -X POST \
"https://production-sfo.browserless.io/function?token=YOUR_API_TOKEN_HERE" \
-H 'Content-Type: application/javascript' \
-d 'export default async function ({ page }) {
const rndNumber = () => {
return Math.floor(Math.random() * (10**6 - 0));
};
await page.goto("https://example.com/");
const url = await page.title();
const numbers = [...Array(5)].map(() => rndNumber());
return {
data: {
url,
numbers,
},
// Make sure to match the appropriate content here
type: "application/json",
};
}'
const TOKEN = "YOUR_API_TOKEN_HERE";
const url = `https://production-sfo.browserless.io/function?token=${TOKEN}`;
const headers = {
"Content-Type": "application/javascript"
};
const data = `
export default async function ({ page }) {
const rndNumber = () => {
return Math.floor(Math.random() * (10**6 - 0));
};
await page.goto("https://example.com/");
const url = await page.title();
const numbers = [...Array(5)].map(() => rndNumber());
return {
data: {
url,
numbers,
},
type: "application/json",
};
}`;
const sendRequest = async () => {
const response = await fetch(url, {
method: 'POST',
headers: headers,
body: data
});
const result = await response.json();
console.log(result);
};
sendRequest();
import requests
TOKEN = "YOUR_API_TOKEN_HERE"
url = f"https://production-sfo.browserless.io/function?token={TOKEN}"
headers = {
"Content-Type": "application/javascript"
}
data = """
export default async function ({ page }) {
const rndNumber = () => {
return Math.floor(Math.random() * (10**6 - 0));
};
await page.goto("https://example.com/");
const url = await page.title();
const numbers = [...Array(5)].map(() => rndNumber());
return {
data: {
url,
numbers,
},
type: "application/json",
};
}
"""
response = requests.post(url, headers=headers, data=data)
result = response.json()
print(result)
import java.net.URI;
import java.net.http.*;
import org.json.JSONObject;
public class BrowserlessFunction {
public static void main(String[] args) {
String TOKEN = "YOUR_API_TOKEN_HERE";
String url = "https://production-sfo.browserless.io/function?token=" + TOKEN;
String javascriptCode = """
export default async function ({ page }) {
const rndNumber = () => {
return Math.floor(Math.random() * (10**6 - 0));
};
await page.goto("https://example.com/");
const url = await page.title();
const numbers = [...Array(5)].map(() => rndNumber());
return {
data: {
url,
numbers,
},
type: "application/json",
};
}
""";
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<String> response = client.send(request, HttpResponse.BodyHandlers.ofString());
JSONObject jsonResponse = new JSONObject(response.body());
System.out.println(jsonResponse.toString(4));
} catch (Exception e) {
e.printStackTrace();
}
}
}
using System;
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/function?token={TOKEN}";
string javascriptCode = @"
export default async function ({ page }) {
const rndNumber = () => {
return Math.floor(Math.random() * (10**6 - 0));
};
await page.goto('https://example.com/');
const url = await page.title();
const numbers = [...Array(5)].map(() => rndNumber());
return {
data: {
url,
numbers,
},
type: 'application/json',
};
}
";
using var client = new HttpClient();
var content = new StringContent(javascriptCode, Encoding.UTF8, "application/javascript");
try {
var response = await client.PostAsync(url, content);
response.EnsureSuccessStatusCode();
var result = await response.Content.ReadAsStringAsync();
Console.WriteLine(result);
} catch (Exception ex) {
Console.WriteLine("Error: " + ex.Message);
}
}
}
Example Reponse
{
"data": {
"url": "Example Domain",
"numbers": [
854246,
114512,
212580,
482122,
107878
]
},
"type": "application/json"
}
Advanced Usage
The /function API can return other file types beyond JSON, such as PDF files. In this example, we'll generate a full-page PDF of a website by calculating the page height and formatting the PDF accordingly.
JS Code
export default async function ({ page }) {
await page.goto("https://es.wikipedia.org/wiki/Web_scraping", { waitUntil: 'networkidle2', timeout: 60000 });
await page.emulateMediaType('screen');
const height = await page.evaluate(() => {
return document.documentElement.scrollHeight - document.documentElement.clientHeight;
});
const pdf = await page.pdf({
printBackground: true,
pageRanges: '1',
height: `${height}px`,
width: '1800px'
});
return pdf;
}
- cURL
- Javascript
- Python
- Java
- C#
curl -X POST \
'https://production-sfo.browserless.io/function?token=YOUR_API_TOKEN_HERE' \
--header 'Content-Type: application/javascript' \
--data 'export default async function ({ page }) {
await page.goto("https://es.wikipedia.org/wiki/Web_scraping", { waitUntil: '\''networkidle2'\'', timeout: 60000 });
await page.emulateMediaType('\''screen'\'');
const height = await page.evaluate(() => {
return document.documentElement.scrollHeight - document.documentElement.clientHeight;
});
const pdf = await page.pdf({
printBackground: true,
pageRanges: '\''1'\'',
height: `${height}px`,
width: '\''1800px'\''
});
return pdf;
}'
const TOKEN = "YOUR_API_TOKEN_HERE";
const url = `https://production-sfo.browserless.io/function?token=${TOKEN}`;
const headers = {
"Content-Type": "application/javascript"
};
const data = `
export default async function ({ page }) {
await page.goto("https://es.wikipedia.org/wiki/Web_scraping", { waitUntil: 'networkidle2', timeout: 60000 });
await page.emulateMediaType('screen');
const height = await page.evaluate(() => {
return document.documentElement.scrollHeight - document.documentElement.clientHeight;
});
const pdf = await page.pdf({
printBackground: true,
pageRanges: '1',
height: \`\${height}px\`,
width: '1800px'
});
return pdf;
}`;
const sendRequest = async () => {
const response = await fetch(url, {
method: 'POST',
headers: headers,
body: data
});
const pdfBuffer = await response.arrayBuffer();
console.log('PDF generated successfully');
};
sendRequest();
import requests
TOKEN = "YOUR_API_TOKEN_HERE"
url = f"https://production-sfo.browserless.io/function?token={TOKEN}"
headers = {
"Content-Type": "application/javascript"
}
data = """
export default async function ({ page }) {
await page.goto("https://es.wikipedia.org/wiki/Web_scraping", { waitUntil: 'networkidle2', timeout: 60000 });
await page.emulateMediaType('screen');
const height = await page.evaluate(() => {
return document.documentElement.scrollHeight - document.documentElement.clientHeight;
});
const pdf = await page.pdf({
printBackground: true,
pageRanges: '1',
height: `${height}px`,
width: '1800px'
});
return pdf;
}
"""
response = requests.post(url, headers=headers, data=data)
with open("output.pdf", "wb") as file:
file.write(response.content)
print("PDF saved as output.pdf")
import java.io.*;
import java.net.URI;
import java.net.http.*;
import java.nio.file.*;
public class BrowserlessFunctionPDF {
public static void main(String[] args) {
String TOKEN = "YOUR_API_TOKEN_HERE";
String url = "https://production-sfo.browserless.io/function?token=" + TOKEN;
String javascriptCode = """
export default async function ({ page }) {
await page.goto("https://es.wikipedia.org/wiki/Web_scraping", { waitUntil: 'networkidle2', timeout: 60000 });
await page.emulateMediaType('screen');
const height = await page.evaluate(() => {
return document.documentElement.scrollHeight - document.documentElement.clientHeight;
});
const pdf = await page.pdf({
printBackground: true,
pageRanges: '1',
height: `${height}px`,
width: '1800px'
});
return pdf;
}
""";
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());
Files.copy(response.body(), Paths.get("output.pdf"), StandardCopyOption.REPLACE_EXISTING);
System.out.println("PDF saved as output.pdf");
} 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/function?token={TOKEN}";
string javascriptCode = @"
export default async function ({ page }) {
await page.goto('https://es.wikipedia.org/wiki/Web_scraping', { waitUntil: 'networkidle2', timeout: 60000 });
await page.emulateMediaType('screen');
const height = await page.evaluate(() => {
return document.documentElement.scrollHeight - document.documentElement.clientHeight;
});
const pdf = await page.pdf({
printBackground: true,
pageRanges: '1',
height: `${height}px`,
width: '1800px'
});
return pdf;
}
";
using var client = new HttpClient();
var content = new StringContent(javascriptCode, Encoding.UTF8, "application/javascript");
try {
var response = await client.PostAsync(url, content);
response.EnsureSuccessStatusCode();
var pdfBytes = await response.Content.ReadAsByteArrayAsync();
await File.WriteAllBytesAsync("output.pdf", pdfBytes);
Console.WriteLine("PDF saved as output.pdf");
} catch (Exception ex) {
Console.WriteLine("Error: " + ex.Message);
}
}
}
Debug your code
Before sending your code through the /function API, you can test and troubleshoot it using our Live Debugger feature. This powerful tool allows you to write and execute your Puppeteer code in a browser environment, making it easy to iterate and debug before making API calls.
You can access the Live Debugger directly from your account page. Once your code is working as expected, simply copy and paste it as the request body and send it with the application/javascript content-type header to the /function endpoint.
For more details on how to use the Live Debugger and its features, see our Live Debugger documentation.
Importing libraries
Since the /function API uses ESM modules, you can use import syntax over HTTP to load moules. For instance, let's try loading the Fake module.
JS Code
import { faker } from "https://esm.sh/@faker-js/faker";
export default async function () {
const Internet = faker.internet;
const rndData = [...Array(5)].map(() => ({
domain: Internet.domainName(),
ip: Internet.ip(),
mac: Internet.mac(),
protocol: Internet.protocol(),
}));
return {
data: { domains: rndData },
type: "application/json",
};
}
- cURL
- Javascript
- Python
- Java
- C#
curl -X POST \
"https://production-sfo.browserless.io/function?token=YOUR_API_TOKEN_HERE" \
-H 'Content-Type: application/javascript' \
-d 'import { faker } from "https://esm.sh/@faker-js/faker";
export default async function () {
const Internet = faker.internet;
const rndData = [...Array(5)].map(() => ({
domain: Internet.domainName(),
ip: Internet.ip(),
mac: Internet.mac(),
protocol: Internet.protocol(),
}));
return {
data: { domains: rndData },
type: "application/json",
};
}'
const TOKEN = "YOUR_API_TOKEN_HERE";
const url = `https://production-sfo.browserless.io/function?token=${TOKEN}`;
const headers = {
"Content-Type": "application/javascript"
};
const data = `
import { faker } from "https://esm.sh/@faker-js/faker";
export default async function () {
const Internet = faker.internet;
const rndData = [...Array(5)].map(() => ({
domain: Internet.domainName(),
ip: Internet.ip(),
mac: Internet.mac(),
protocol: Internet.protocol(),
}));
return {
data: { domains: rndData },
type: "application/json",
};
}`;
const sendRequest = async () => {
const response = await fetch(url, {
method: 'POST',
headers: headers,
body: data
});
const result = await response.json();
console.log(result);
};
sendRequest();
import requests
TOKEN = "YOUR_API_TOKEN_HERE"
url = f"https://production-sfo.browserless.io/function?token={TOKEN}"
headers = {
"Content-Type": "application/javascript"
}
data = """
import { faker } from "https://esm.sh/@faker-js/faker";
export default async function () {
const Internet = faker.internet;
const rndData = [...Array(5)].map(() => ({
domain: Internet.domainName(),
ip: Internet.ip(),
mac: Internet.mac(),
protocol: Internet.protocol(),
}));
return {
data: { domains: rndData },
type: "application/json",
};
}
"""
response = requests.post(url, headers=headers, data=data)
result = response.json()
print(result)
import java.net.URI;
import java.net.http.*;
import org.json.JSONObject;
public class BrowserlessFakerFunction {
public static void main(String[] args) {
String TOKEN = "YOUR_API_TOKEN_HERE";
String url = "https://production-sfo.browserless.io/function?token=" + TOKEN;
String javascriptCode = """
import { faker } from "https://esm.sh/@faker-js/faker";
export default async function () {
const Internet = faker.internet;
const rndData = [...Array(5)].map(() => ({
domain: Internet.domainName(),
ip: Internet.ip(),
mac: Internet.mac(),
protocol: Internet.protocol(),
}));
return {
data: { domains: rndData },
type: "application/json",
};
}
""";
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<String> response = client.send(request, HttpResponse.BodyHandlers.ofString());
JSONObject jsonResponse = new JSONObject(response.body());
System.out.println(jsonResponse.toString(4));
} catch (Exception e) {
e.printStackTrace();
}
}
}
using System;
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/function?token={TOKEN}";
string javascriptCode = @"
import { faker } from 'https://esm.sh/@faker-js/faker';
export default async function () {
const Internet = faker.internet;
const rndData = [...Array(5)].map(() => ({
domain: Internet.domainName(),
ip: Internet.ip(),
mac: Internet.mac(),
protocol: Internet.protocol(),
}));
return {
data: { domains: rndData },
type: 'application/json',
};
}
";
using var client = new HttpClient();
var content = new StringContent(javascriptCode, Encoding.UTF8, "application/javascript");
try {
var response = await client.PostAsync(url, content);
response.EnsureSuccessStatusCode();
var result = await response.Content.ReadAsStringAsync();
Console.WriteLine(result);
} catch (Exception ex) {
Console.WriteLine("Error: " + ex.Message);
}
}
}
JSON API
You can also use the /function API for sending a JSON payload. For that you must send an object with the following values:
code: String, required — custom function code.context: Object, optional — value used to pass context values and arguments to thecode
Example
JS Code
import { faker } from "https://esm.sh/@faker-js/faker";
export default async function ({ context }) {
const Internet = faker.internet;
const rndData = [...Array(context.len)].map(() => ({
domain: Internet.domainName(),
ip: Internet.ip(),
mac: Internet.mac(),
protocol: Internet.protocol(),
}));
return {
data: {
domains: rndData,
length: context.len
},
type: "application/json",
};
}
- cURL
- Javascript
- Python
- Java
- C#
curl --request POST \
--url 'https://production-sfo.browserless.io/function?token=YOUR_API_TOKEN_HERE' \
--header 'Content-Type: application/json' \
# Minified code
--data '{
"code": "import{faker as a}from\"https://esm.sh/@faker-js/faker\";export default async function({context:o}){let t=a.internet,e=[...Array(o.len)].map(()=>({domain:t.domainName(),ip:t.ip(),mac:t.mac(),protocol:t.protocol()}));return{data:{domains:e,length:o.len},type:`application/json`}};",
"context": {
"len": 10
}
}'
import fetch from 'node-fetch';
const TOKEN = "YOUR_API_TOKEN_HERE";
const url = `https://production-sfo.browserless.io/function?token=${TOKEN}`;
const headers = {
"Content-Type": "application/json"
};
const data = {
code: 'import{faker as a}from"https://esm.sh/@faker-js/faker";export default async function({context:o}){let t=a.internet,e=[...Array(o.len)].map(()=>({domain:t.domainName(),ip:t.ip(),mac:t.mac(),protocol:t.protocol()}));return{data:{domains:e,length:o.len},type:`application/json`}};',
context: { len: 10 }
};
const sendRequest = async () => {
const response = await fetch(url, {
method: 'POST',
headers: headers,
body: JSON.stringify(data)
});
const result = await response.json();
console.log(result);
};
sendRequest();
import requests
TOKEN = "YOUR_API_TOKEN_HERE"
url = f"https://production-sfo.browserless.io/function?token={TOKEN}"
headers = {
"Content-Type": "application/json"
}
data = {
"code": 'import{faker as a}from"https://esm.sh/@faker-js/faker";export default async function({context:o}){let t=a.internet,e=[...Array(o.len)].map(()=>({domain:t.domainName(),ip:t.ip(),mac:t.mac(),protocol:t.protocol()}));return{data:{domains:e,length:o.len},type:`application/json`}};',
"context": {
"len": 10
}
}
response = requests.post(url, headers=headers, json=data)
result = response.json()
print(result)
import java.net.URI;
import java.net.http.*;
import org.json.JSONObject;
public class BrowserlessFakerMinified {
public static void main(String[] args) {
String TOKEN = "YOUR_API_TOKEN_HERE";
String url = "https://production-sfo.browserless.io/function?token=" + TOKEN;
String jsonData = """
{
"code": "import{faker as a}from\\\"https://esm.sh/@faker-js/faker\\\";export default async function({context:o}){let t=a.internet,e=[...Array(o.len)].map(()=>({domain:t.domainName(),ip:t.ip(),mac:t.mac(),protocol:t.protocol()}));return{data:{domains:e,length:o.len},type:`application/json`}};",
"context": {
"len": 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<String> response = client.send(request, HttpResponse.BodyHandlers.ofString());
JSONObject jsonResponse = new JSONObject(response.body());
System.out.println(jsonResponse.toString(4));
} catch (Exception e) {
e.printStackTrace();
}
}
}
using System;
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/function?token={TOKEN}";
string jsonData = @"
{
""code"": ""import{faker as a}from\""https://esm.sh/@faker-js/faker\"";export default async function({context:o}){let t=a.internet,e=[...Array(o.len)].map(()=>({domain:t.domainName(),ip:t.ip(),mac:t.mac(),protocol:t.protocol()}));return{data:{domains:e,length:o.len},type:`application/json`}};"",
""context"": {
""len"": 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();
var result = await response.Content.ReadAsStringAsync();
Console.WriteLine(result);
} catch (Exception ex) {
Console.WriteLine("Error: " + ex.Message);
}
}
}
Exception handling
When working with the /function API, you can catch exceptions and handle errors gracefully. This is particularly useful for debugging and providing meaningful error responses when automation fails.
The following example shows how to implement comprehensive error, allowing you to:
- Capture detailed error information including the error message, stack trace, and error type
- Take a screenshot when an error occurs for visual debugging
- Handle screenshot capture errors gracefully
- Return both successful data and error information in a structured format
JS Code
export default async ({ page }) => {
let error;
let title;
try {
await page.goto('https://www.example.com');
title = await page.title();
await page.click('.nonexistent-button'); // This will throw
} catch (err) {
const errorDetails = {
message: err.message,
stack: err.stack,
name: err.name,
};
try {
const screenshot = await page.screenshot({ encoding: 'base64' });
errorDetails.screenshot = screenshot;
} catch (screenshotErr) {
errorDetails.screenshotError = {
message: screenshotErr.message,
stack: screenshotErr.stack,
name: screenshotErr.name,
};
}
error = errorDetails;
}
return {
data: {
title,
error,
},
};
};
- cURL
- Javascript
- Python
- Java
- C#
curl -X POST \
"https://production-sfo.browserless.io/function?token=YOUR_API_TOKEN_HERE" \
-H 'Content-Type: application/javascript' \
-d 'export default async ({ page }) => {
let error;
let title;
try {
await page.goto("https://www.example.com");
title = await page.title();
await page.click(".nonexistent-button"); // This will throw
} catch (err) {
const errorDetails = {
message: err.message,
stack: err.stack,
name: err.name,
};
try {
const screenshot = await page.screenshot({ encoding: "base64" });
errorDetails.screenshot = screenshot;
} catch (screenshotErr) {
errorDetails.screenshotError = {
message: screenshotErr.message,
stack: screenshotErr.stack,
name: screenshotErr.name,
};
}
error = errorDetails;
}
return {
data: {
title,
error,
},
};
};'
const TOKEN = "YOUR_API_TOKEN_HERE";
const url = `https://production-sfo.browserless.io/function?token=${TOKEN}`;
const headers = {
"Content-Type": "application/javascript"
};
const data = `
export default async ({ page }) => {
let error;
let title;
try {
await page.goto('https://www.example.com');
title = await page.title();
await page.click('.nonexistent-button'); // This will throw
} catch (err) {
const errorDetails = {
message: err.message,
stack: err.stack,
name: err.name,
};
try {
const screenshot = await page.screenshot({ encoding: 'base64' });
errorDetails.screenshot = screenshot;
} catch (screenshotErr) {
errorDetails.screenshotError = {
message: screenshotErr.message,
stack: screenshotErr.stack,
name: screenshotErr.name,
};
}
error = errorDetails;
}
return {
data: {
title,
error,
},
};
};`;
const sendRequest = async () => {
const response = await fetch(url, {
method: 'POST',
headers: headers,
body: data
});
const result = await response.json();
console.log(result);
};
sendRequest();
import requests
TOKEN = "YOUR_API_TOKEN_HERE"
url = f"https://production-sfo.browserless.io/function?token={TOKEN}"
headers = {
"Content-Type": "application/javascript"
}
data = """
export default async ({ page }) => {
let error;
let title;
try {
await page.goto('https://www.example.com');
title = await page.title();
await page.click('.nonexistent-button'); // This will throw
} catch (err) {
const errorDetails = {
message: err.message,
stack: err.stack,
name: err.name,
};
try {
const screenshot = await page.screenshot({ encoding: 'base64' });
errorDetails.screenshot = screenshot;
} catch (screenshotErr) {
errorDetails.screenshotError = {
message: screenshotErr.message,
stack: screenshotErr.stack,
name: screenshotErr.name,
};
}
error = errorDetails;
}
return {
data: {
title,
error,
},
};
};
"""
response = requests.post(url, headers=headers, data=data)
result = response.json()
print(result)
import java.net.URI;
import java.net.http.*;
import org.json.JSONObject;
public class BrowserlessExceptionHandling {
public static void main(String[] args) {
String TOKEN = "YOUR_API_TOKEN_HERE";
String url = "https://production-sfo.browserless.io/function?token=" + TOKEN;
String javascriptCode = """
export default async ({ page }) => {
let error;
let title;
try {
await page.goto('https://www.example.com');
title = await page.title();
await page.click('.nonexistent-button'); // This will throw
} catch (err) {
const errorDetails = {
message: err.message,
stack: err.stack,
name: err.name,
};
try {
const screenshot = await page.screenshot({ encoding: 'base64' });
errorDetails.screenshot = screenshot;
} catch (screenshotErr) {
errorDetails.screenshotError = {
message: screenshotErr.message,
stack: screenshotErr.stack,
name: screenshotErr.name,
};
}
error = errorDetails;
}
return {
data: {
title,
error,
},
};
};
""";
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<String> response = client.send(request, HttpResponse.BodyHandlers.ofString());
JSONObject jsonResponse = new JSONObject(response.body());
System.out.println(jsonResponse.toString(4));
} catch (Exception e) {
e.printStackTrace();
}
}
}
using System;
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/function?token={TOKEN}";
string javascriptCode = @"
export default async ({ page }) => {
let error;
let title;
try {
await page.goto('https://www.example.com');
title = await page.title();
await page.click('.nonexistent-button'); // This will throw
} catch (err) {
const errorDetails = {
message: err.message,
stack: err.stack,
name: err.name,
};
try {
const screenshot = await page.screenshot({ encoding: 'base64' });
errorDetails.screenshot = screenshot;
} catch (screenshotErr) {
errorDetails.screenshotError = {
message: screenshotErr.message,
stack: screenshotErr.stack,
name: screenshotErr.name,
};
}
error = errorDetails;
}
return {
data: {
title,
error,
},
};
};
";
using var client = new HttpClient();
var content = new StringContent(javascriptCode, Encoding.UTF8, "application/javascript");
try {
var response = await client.PostAsync(url, content);
response.EnsureSuccessStatusCode();
var result = await response.Content.ReadAsStringAsync();
Console.WriteLine(result);
} catch (Exception ex) {
Console.WriteLine("Error: " + ex.Message);
}
}
}
Example Response
{
"data": {
"title": "Example Domain",
"error": {
"message": "No node found for selector: .nonexistent-button",
"stack": "Error: No node found for selector: .nonexistent-button\n at ...",
"name": "Error",
"screenshot": "iVBORw0KGgoAAAANSUhEUgAAA..."
}
}
}