Skip to main content
Version: v2

Connecting other libraries

BrowserQL is our first-class browser automation API, and includes powerful options like human-like, reconnecting and proxying. It's a full rethink of how to do browser automation with a minimalistic stealth-first approach. In order to get started, you'll need to sign-up for a cloud plan and get your API Key as well as our Desktop editor -- all of which are available via the account portal.

If you already have an automation library that works over WebSockets (like puppeteer or playwright), then you can mix-and-match BrowserQL with the library of your choice. This is perfect for getting past a nasty bot blockage and then connecting your existing scripts back.

Similarly, if you want to run more BrowserQL at a later time then you can do that as well.

Connecting A Library

Using "example.com" as a basis, you can run the following BrowserQL query then ask for a connection back:

mutation Reconnect {
goto(url: "https://example.com/", waitUntil: networkIdle) {
status
}

reconnect (timeout: 30000) {
browserWSEndpoint
}
}

The reconnect query has a timeout argument, which is a limit (in milliseconds) for how long the browser should be available before it gets shutdown when nothing connects to it. If a connection were to happen after this time, a semantic 404 is returned back. When a connection happens, this will clear the timer and the session can continue past this limit.

Here are full examples using Puppeteer and Playwright:

import puppeteer from 'puppeteer-core';

const url = 'https://example.com';
const token = 'YOUR_API_TOKEN_HERE';
const timeout = 5 * 60 * 1000;

const queryParams = new URLSearchParams({
timeout,
token,
}).toString();

const query = `
mutation Reconnect($url: String!) {
goto(url: $url, waitUntil: networkIdle) {
status
}
reconnect(timeout: 30000) {
browserWSEndpoint
}
}
`;

const variables = { url };

const endpoint =
`https://production-sfo.browserless.io/chromium/bql?${queryParams}`;

const options = {
method: 'POST',
headers: {
'content-type': 'application/json'
},
body: JSON.stringify({
query,
variables,
}),
};

try {
console.log(`Running BQL Query: ${url}`);

const response = await fetch(endpoint, options);

if (!response.ok) {
throw new Error(`Got non-ok response:\n` + (await response.text()));
}

const { data } = await response.json();
const browserWSEndpoint = data.reconnect.browserWSEndpoint
console.log(`Got OK response! Connecting puppeteer to ${browserWSEndpoint}`);
const browser = await puppeteer.connect({
browserWSEndpoint,
});
console.log(`Connected to ${await browser.version()}`);
const pages = await browser.pages();
const page = pages.find((p) => p.url().includes(url));
await page.screenshot({ fullPage: true, path: 'temp.png' });
await browser.close();
} catch (error) {
console.error(error);
}

Reconnecting with more BrowserQL

Similar to connecting a 3rd-party library, you can also reconnect back and execute more BrowserQL as well. BrowserQL does this by generating a new unique URL to use for running more queries. You can take this URL, append your API-token to it, and run more query language.

This is particularly useful for cases like AI where you might want to run several queries as users interact with your platform, but you don't want to necessarily keep an open connection.

Here are full examples running two BrowserQL queries on the same browser:

const url = 'https://example.com';
const token = 'YOUR_API_TOKEN_HERE';
const timeout = 5 * 60 * 1000;

const queryParams = new URLSearchParams({
timeout,
token,
}).toString();
const endpoint = `https://production-sfo.browserless.io/chromium/bql`;
const variables = { url };
const query = `
mutation Reconnect($url: String!) {
goto(url: $url, waitUntil: networkIdle) {
status
}
reconnect(timeout: 30000) {
browserQLEndpoint
}
}
`;
const queryTwo = `
mutation GetText {
text {
text
}
}
`;
const bql = async (url, query, variables) => {
const data = await fetch(`${url}?${queryParams}`, {
method: 'POST',
headers: {
'content-type': 'application/json',
},
body: JSON.stringify({
query,
variables,
}),
});

if (!data.ok) {
throw new Error(`Non OK response: ${await data.text()}`);
}

return data.json();
};

try {
console.log(`Running BQL Query#1: ${url}`);
const first = await bql(endpoint, query, variables);
const browserQLEndpoint = first.data.reconnect.browserQLEndpoint;

console.log(`Running BQL Query#2: ${browserQLEndpoint}`);
const second = await bql(browserQLEndpoint, queryTwo);
console.log(`Got results: "${second.data.text.text}"`);
} catch (error) {
console.error(error);
}