BrowserAPI Advanced Methods
The BrowserAPI class provides six advanced methods through the
session.browser interface that handle screenshots, JavaScript execution,
and cookie management within an adaptive mode BBRE session. The
screenshot(options) method captures the current browser viewport or the
full page as a base64-encoded image string, giving you the ability to save visual
snapshots of pages at any point during your automation workflow. The
execute(script) method runs arbitrary JavaScript code inside the live
browser context, allowing you to manipulate the DOM, extract computed values, trigger
events, and perform any operation that native JavaScript supports. The
evaluate(script) method is a direct alias for execute(),
providing a familiar naming convention for developers who are used to Puppeteer or
Playwright APIs. The getCookies() method retrieves all cookies currently
stored in the browser session, returning them as a key-value object that you can
inspect, log, or use for session state verification. The
setCookie(name, value, options) method sets a single cookie in the
browser with full control over domain, path, expiration, httpOnly, and secure flags.
The clearCookies() method removes all cookies from the browser session,
which is useful for resetting authentication state, testing login flows from scratch,
or ensuring a clean cookie environment before navigating to a new domain. Together,
these six methods form the advanced capabilities layer of the BrowserAPI, enabling
you to build sophisticated automation workflows that go beyond simple navigation and
element interaction. Screenshots let you create visual audit trails and debug
rendering issues. JavaScript execution gives you unlimited control over the page
when the built-in BrowserAPI methods are not sufficient. Cookie management lets you
manipulate authentication tokens, session identifiers, consent flags, and any other
cookie-based state that websites depend on. This page provides complete documentation
for every advanced method, including method signatures, parameter tables, return
types, practical code examples covering full-page screenshots, DOM manipulation,
data extraction via JavaScript, cookie inspection, authentication cookie injection,
and combined cookie management workflows, along with best practices, common issues,
and links to related documentation.
All BrowserAPI advanced methods require an active session running in
adaptive mode. Adaptive mode sessions launch a real browser instance
managed by the BBRE engine, which is necessary for capturing screenshots, executing
JavaScript in the browser context, and managing cookies. If you attempt to call these
methods on a passive mode session, the operation will fail with a
BROWSER_ACTION_FAILED error. Create your session with
mode: "adaptive" to use these methods. For simple HTTP requests where
you only need the raw HTML response without browser rendering, screenshots, or cookie
manipulation, consider using passive mode with session.request() instead,
which is faster and consumes fewer credits.
When session.force is set to false (the default), any
browser action failure will automatically close the session and throw a
[SESSION_STOPPED] error. This means that if a screenshot capture fails,
a JavaScript execution throws an unhandled exception, or a cookie operation encounters
an error, the entire session will be terminated. Always wrap browser action calls in
try-catch blocks in production code, and consider setting force: true on
the session if you want to continue the workflow even when individual actions fail.
session.browser.screenshot(options)
The screenshot() method captures a visual snapshot of the current browser
viewport and returns it as a base64-encoded string. This is one of the most valuable
debugging and auditing tools available in the BrowserAPI because it gives you a pixel-
perfect representation of exactly what the browser is rendering at the moment of
capture. The method sends a screenshot action to the BBRE engine with
the provided options object and extracts the screenshot value from the response. You
can control whether the screenshot captures only the visible viewport or the entire
scrollable page by setting the fullPage option. The image format and
quality can also be configured through the options object. The returned base64 string
can be saved directly to a file by converting it to a Buffer, sent to an image
processing service, stored in a database for visual regression testing, or embedded
in HTML reports. Screenshots are particularly useful for debugging automation
workflows because they show you the exact state of the page at any point in your
script, including dynamically loaded content, modal dialogs, error messages, and
layout issues that would not be visible from the HTML source alone.
Method Signature
const base64Image = await session.browser.screenshot(options);
Parameters
The screenshot() method accepts a single optional parameter: an options
object that controls the screenshot behavior. If omitted, the method captures a
default viewport screenshot.
| Parameter | Type | Required | Description |
|---|---|---|---|
options |
object | Optional | An object containing screenshot configuration. When omitted, a default viewport screenshot is captured. |
options.fullPage |
boolean | Optional | When set to true, captures the entire scrollable page instead of just the visible viewport. Defaults to false. |
options.type |
string | Optional | The image format for the screenshot. Supported values are "png" and "jpeg". Defaults to "png". |
options.quality |
number | Optional | The image quality for JPEG screenshots, expressed as a number between 0 and 100. Only applies when type is set to "jpeg". Higher values produce larger files with better quality. |
Return Type
The method returns a Promise that resolves to a base64-encoded string
representing the screenshot image. This string can be decoded into binary image data
using Buffer.from(base64String, "base64") and written to a file.
| Return Type | Description |
|---|---|
| Promise<string> | Resolves to a base64-encoded string of the screenshot image. The encoding format depends on the type option (PNG by default). |
Basic Viewport Screenshot
The simplest usage of screenshot() captures the currently visible
viewport. This is useful for quick visual checks during automation to confirm that
the page has loaded correctly and the expected content is visible.
const { BBRESession } = require("mydisctsolver-bbre");
const session = new BBRESession({
apiKey: "YOUR_API_KEY",
mode: "adaptive",
sensibility: "medium"
});
async function captureViewport() {
await session.start();
await session.browser.navigate("https://example.com");
await session.browser.wait(2);
const screenshot = await session.browser.screenshot();
console.log("Screenshot base64 length:", screenshot.length);
await session.close();
}
captureViewport();
Full Page Screenshot
Set fullPage: true to capture the entire scrollable page, not just the
visible viewport. This is essential when you need a complete visual record of a long
page, such as a product listing, an article, or a dashboard with content that extends
below the fold. Full page screenshots are significantly larger than viewport
screenshots because they include all content from the top to the bottom of the page.
const { BBRESession } = require("mydisctsolver-bbre");
const fs = require("fs");
const session = new BBRESession({
apiKey: "YOUR_API_KEY",
mode: "adaptive",
sensibility: "medium"
});
async function captureFullPage() {
await session.start();
await session.browser.navigate("https://example.com/products");
await session.browser.wait(3);
const screenshot = await session.browser.screenshot({ fullPage: true });
const buffer = Buffer.from(screenshot, "base64");
fs.writeFileSync("full-page-screenshot.png", buffer);
console.log("Full page screenshot saved:", buffer.length, "bytes");
await session.close();
}
captureFullPage();
JPEG Screenshot with Quality Control
When file size matters more than pixel-perfect quality, use JPEG format with a quality setting. JPEG screenshots are typically 3 to 5 times smaller than PNG screenshots, making them ideal for batch processing, storage in databases, or sending over networks where bandwidth is limited. A quality value of 80 provides a good balance between file size and visual clarity for most use cases.
const { BBRESession } = require("mydisctsolver-bbre");
const fs = require("fs");
const session = new BBRESession({
apiKey: "YOUR_API_KEY",
mode: "adaptive",
sensibility: "low"
});
async function captureJpegScreenshot() {
await session.start();
await session.browser.navigate("https://example.com/dashboard");
await session.browser.wait(2);
const screenshot = await session.browser.screenshot({
type: "jpeg",
quality: 80
});
const buffer = Buffer.from(screenshot, "base64");
fs.writeFileSync("dashboard.jpg", buffer);
console.log("JPEG screenshot saved:", buffer.length, "bytes");
await session.close();
}
captureJpegScreenshot();
Screenshot at Multiple Points in a Workflow
One of the most powerful uses of screenshot() is capturing the page
state at multiple points during an automation workflow. This creates a visual audit
trail that you can review later to verify that each step executed correctly, debug
failures, or generate visual reports for stakeholders.
const { BBRESession } = require("mydisctsolver-bbre");
const fs = require("fs");
const session = new BBRESession({
apiKey: "YOUR_API_KEY",
mode: "adaptive",
sensibility: "medium"
});
async function workflowWithScreenshots() {
await session.start();
await session.browser.navigate("https://example.com/login");
await session.browser.wait(2);
const step1 = await session.browser.screenshot();
fs.writeFileSync("step1-login-page.png", Buffer.from(step1, "base64"));
await session.browser.fill("#email", "[email protected]");
await session.browser.fill("#password", "securepassword");
const step2 = await session.browser.screenshot();
fs.writeFileSync("step2-form-filled.png", Buffer.from(step2, "base64"));
await session.browser.click("#login-button");
await session.browser.wait(3);
const step3 = await session.browser.screenshot();
fs.writeFileSync("step3-after-login.png", Buffer.from(step3, "base64"));
const currentUrl = await session.browser.getUrl();
console.log("Current URL after login:", currentUrl);
await session.close();
}
workflowWithScreenshots();
Error Handling for screenshot()
The screenshot() method can fail if the session is not in adaptive mode,
the session has expired or been closed, or the browser encounters an internal error
during the capture process. Always wrap screenshot calls in try-catch blocks when
building production workflows.
const { BBRESession } = require("mydisctsolver-bbre");
const fs = require("fs");
const session = new BBRESession({
apiKey: "YOUR_API_KEY",
mode: "adaptive",
sensibility: "medium"
});
async function safeScreenshot(filename) {
try {
const screenshot = await session.browser.screenshot({ fullPage: true });
const buffer = Buffer.from(screenshot, "base64");
fs.writeFileSync(filename, buffer);
console.log("Screenshot saved to", filename);
return true;
} catch (error) {
console.log("Screenshot failed:", error.message);
return false;
}
}
async function main() {
await session.start();
await session.browser.navigate("https://example.com");
await session.browser.wait(2);
const saved = await safeScreenshot("page-capture.png");
if (!saved) {
console.log("Continuing workflow without screenshot");
}
await session.close();
}
main();
session.browser.execute(script)
The execute() method runs arbitrary JavaScript code inside the live
browser context and returns the result. This is the most powerful method in the
BrowserAPI because it gives you direct access to the browser's JavaScript engine,
allowing you to do anything that native JavaScript can do: manipulate the DOM, read
computed styles, access localStorage and sessionStorage, trigger custom events, call
functions defined by the page's own scripts, and extract data that is not accessible
through the standard BrowserAPI query methods. The method accepts a JavaScript code
string as its only parameter. If the script does not start with (function
or (() =>, the method automatically wraps it in an Immediately Invoked
Function Expression (IIFE) before sending it to the browser. This auto-wrapping
ensures that your script executes in its own scope and can use return
statements to send values back to your Node.js code. If you provide a script that
is already wrapped in an IIFE, the method sends it as-is without additional wrapping.
The return value of your script becomes the resolved value of the Promise returned
by execute(). If your script does not explicitly return a value, the
method returns undefined. If your script throws an error, the method
propagates that error as a rejected Promise.
Method Signature
const result = await session.browser.execute(script);
Parameters
The execute() method accepts a single required parameter: a string
containing the JavaScript code to run in the browser context.
| Parameter | Type | Required | Description |
|---|---|---|---|
script |
string | Required | A string containing JavaScript code to execute in the browser context. If the script does not start with (function or (() =>, it is automatically wrapped in an IIFE: (function() { YOUR_SCRIPT })(); |
Auto-Wrapping Behavior
The execute() method inspects the beginning of your script string to
determine whether it needs to be wrapped in an IIFE. This auto-wrapping behavior
is important to understand because it affects how you write your scripts and how
return values work.
| Script Starts With | Wrapping Applied | Example |
|---|---|---|
(function |
No wrapping, sent as-is | (function() { return document.title; })() |
(() => |
No wrapping, sent as-is | (() => document.title)() |
| Anything else | Wrapped in (function() { ... })() |
return document.title; becomes (function() { return document.title; })() |
When your script is auto-wrapped in an IIFE, you can use return
statements to send values back to your Node.js code. The returned value becomes
the resolved value of the Promise. Without a return statement, the
method returns undefined. If you provide your own IIFE wrapper,
make sure it also returns the value you want to capture.
Return Type
The method returns a Promise that resolves to whatever value your
JavaScript code returns. The return value is serialized by the browser engine and
deserialized in Node.js, so it supports primitive types (strings, numbers, booleans,
null), arrays, and plain objects. Functions, DOM elements, and other non-serializable
values cannot be returned directly.
| Return Type | Description |
|---|---|
| Promise<any> | Resolves to the return value of the executed JavaScript code. Returns undefined if the script does not explicitly return a value. |
Extract Page Title
The simplest use of execute() is extracting a single value from the
page. While getTitle() already provides this functionality, this example
demonstrates the basic pattern of returning a value from an executed script.
const { BBRESession } = require("mydisctsolver-bbre");
const session = new BBRESession({
apiKey: "YOUR_API_KEY",
mode: "adaptive",
sensibility: "medium"
});
async function getPageTitle() {
await session.start();
await session.browser.navigate("https://example.com");
await session.browser.wait(2);
const title = await session.browser.execute("return document.title;");
console.log("Page title:", title);
await session.close();
}
getPageTitle();
Extract Structured Data from the DOM
One of the most common uses of execute() is extracting structured data
from the page that would be difficult or impossible to get using the standard query
methods. By running JavaScript directly in the browser, you can use
querySelectorAll, iterate over elements, and build a structured object
that contains exactly the data you need.
const { BBRESession } = require("mydisctsolver-bbre");
const session = new BBRESession({
apiKey: "YOUR_API_KEY",
mode: "adaptive",
sensibility: "medium"
});
async function extractProductData() {
await session.start();
await session.browser.navigate("https://example.com/products");
await session.browser.wait(3);
const products = await session.browser.execute(`
var items = document.querySelectorAll(".product-card");
var results = [];
for (var i = 0; i < items.length; i++) {
var item = items[i];
var nameEl = item.querySelector(".product-name");
var priceEl = item.querySelector(".product-price");
var ratingEl = item.querySelector(".product-rating");
results.push({
name: nameEl ? nameEl.textContent.trim() : "",
price: priceEl ? priceEl.textContent.trim() : "",
rating: ratingEl ? ratingEl.textContent.trim() : ""
});
}
return results;
`);
console.log("Found", products.length, "products");
products.forEach(function(p) {
console.log(p.name, "-", p.price, "-", p.rating);
});
await session.close();
}
extractProductData();
Modify the DOM Before Interaction
Sometimes you need to modify the page before interacting with it. For example, you
might need to remove an overlay that blocks clicks, disable a form validation that
prevents submission, or change an element's visibility to make it interactable. The
execute() method lets you make these modifications directly.
const { BBRESession } = require("mydisctsolver-bbre");
const session = new BBRESession({
apiKey: "YOUR_API_KEY",
mode: "adaptive",
sensibility: "high"
});
async function removeOverlayAndInteract() {
await session.start();
await session.browser.navigate("https://example.com/page-with-overlay");
await session.browser.wait(3);
await session.browser.execute(`
var overlay = document.querySelector(".modal-overlay");
if (overlay) {
overlay.parentNode.removeChild(overlay);
}
var backdrop = document.querySelector(".modal-backdrop");
if (backdrop) {
backdrop.parentNode.removeChild(backdrop);
}
document.body.style.overflow = "auto";
`);
await session.browser.wait(0.5);
await session.browser.click("#main-content-link");
await session.browser.wait(2);
const pageText = await session.browser.getText("body");
console.log("Page content length:", pageText.length);
await session.close();
}
removeOverlayAndInteract();
Access localStorage and sessionStorage
The execute() method gives you access to browser storage APIs that are
not available through the standard BrowserAPI methods. You can read, write, and
delete values in both localStorage and sessionStorage, which is useful for managing
application state, authentication tokens, and user preferences.
const { BBRESession } = require("mydisctsolver-bbre");
const session = new BBRESession({
apiKey: "YOUR_API_KEY",
mode: "adaptive",
sensibility: "medium"
});
async function manageLocalStorage() {
await session.start();
await session.browser.navigate("https://example.com/app");
await session.browser.wait(2);
const storageData = await session.browser.execute(`
var data = {};
for (var i = 0; i < localStorage.length; i++) {
var key = localStorage.key(i);
data[key] = localStorage.getItem(key);
}
return data;
`);
console.log("localStorage contents:", storageData);
await session.browser.execute(`
localStorage.setItem("app_theme", "dark");
localStorage.setItem("app_language", "en");
`);
await session.browser.navigate("https://example.com/app");
await session.browser.wait(2);
const theme = await session.browser.execute(`
return localStorage.getItem("app_theme");
`);
console.log("Current theme:", theme);
await session.close();
}
manageLocalStorage();
Using Pre-Wrapped IIFE Scripts
If you prefer to manage the IIFE wrapping yourself, or if you are generating scripts
dynamically and want full control over the execution context, you can provide a
script that already starts with (function or (() =>.
The execute() method will detect this and send the script without
additional wrapping.
const { BBRESession } = require("mydisctsolver-bbre");
const session = new BBRESession({
apiKey: "YOUR_API_KEY",
mode: "adaptive",
sensibility: "medium"
});
async function executePreWrappedScript() {
await session.start();
await session.browser.navigate("https://example.com");
await session.browser.wait(2);
const linkCount = await session.browser.execute(
"(function() { return document.querySelectorAll('a').length; })()"
);
console.log("Number of links on page:", linkCount);
const imageCount = await session.browser.execute(
"(() => document.querySelectorAll('img').length)()"
);
console.log("Number of images on page:", imageCount);
await session.close();
}
executePreWrappedScript();
session.browser.evaluate(script)
The evaluate() method is a direct alias for execute().
Internally, it calls this.execute(script) and returns the result without
any additional processing. The two methods are completely interchangeable and produce
identical results for the same input. The evaluate() name exists to
provide a familiar API for developers who are accustomed to Puppeteer's
page.evaluate() or Playwright's page.evaluate() methods.
If you are migrating automation scripts from Puppeteer or Playwright to the BBRE SDK,
you can use evaluate() as a drop-in replacement without changing your
mental model. All the same auto-wrapping rules, return value behavior, and error
handling that apply to execute() also apply to evaluate()
because it delegates entirely to execute() under the hood.
Method Signature
const result = await session.browser.evaluate(script);
Parameters
The evaluate() method accepts the same single required parameter as
execute(): a string containing JavaScript code to run in the browser
context.
| Parameter | Type | Required | Description |
|---|---|---|---|
script |
string | Required | A string containing JavaScript code to execute in the browser context. Identical behavior to execute() including auto-wrapping in an IIFE when the script does not start with (function or (() =>. |
Return Type
| Return Type | Description |
|---|---|
| Promise<any> | Resolves to the return value of the executed JavaScript code. Identical behavior to execute(). |
When to Use evaluate() vs execute()
Since both methods are functionally identical, the choice between them is purely a matter of naming preference and code readability. Here are some guidelines to help you decide which name to use in your codebase.
| Scenario | Recommended Method | Reason |
|---|---|---|
| Migrating from Puppeteer or Playwright | evaluate() |
Matches the naming convention you are already familiar with, reducing cognitive overhead during migration. |
| Extracting data from the page | evaluate() |
The word "evaluate" implies computing and returning a value, which aligns with data extraction use cases. |
| Modifying the DOM or triggering side effects | execute() |
The word "execute" implies performing an action, which aligns with DOM manipulation and side-effect use cases. |
| Running scripts that do not return a value | execute() |
When the script performs an action without returning data, "execute" better describes the intent. |
| New projects without migration constraints | Either | Pick one and use it consistently throughout your codebase for readability. |
Basic evaluate() Usage
This example demonstrates using evaluate() to extract the number of
form elements on a page. The behavior is identical to calling execute()
with the same script.
const { BBRESession } = require("mydisctsolver-bbre");
const session = new BBRESession({
apiKey: "YOUR_API_KEY",
mode: "adaptive",
sensibility: "medium"
});
async function evaluatePageStructure() {
await session.start();
await session.browser.navigate("https://example.com/contact");
await session.browser.wait(2);
const formCount = await session.browser.evaluate(
"return document.querySelectorAll('form').length;"
);
console.log("Number of forms:", formCount);
const inputCount = await session.browser.evaluate(
"return document.querySelectorAll('input').length;"
);
console.log("Number of inputs:", inputCount);
const metaDescription = await session.browser.evaluate(`
var meta = document.querySelector('meta[name="description"]');
return meta ? meta.getAttribute("content") : null;
`);
console.log("Meta description:", metaDescription);
await session.close();
}
evaluatePageStructure();
Puppeteer Migration Example
If you are migrating from Puppeteer to the BBRE SDK, the evaluate()
method provides a familiar interface. The main difference is that BBRE's
evaluate() accepts a string instead of a function reference, so you
need to convert your Puppeteer evaluate callbacks to string-based scripts.
const { BBRESession } = require("mydisctsolver-bbre");
const session = new BBRESession({
apiKey: "YOUR_API_KEY",
mode: "adaptive",
sensibility: "medium"
});
async function puppeteerStyleEvaluate() {
await session.start();
await session.browser.navigate("https://example.com/products");
await session.browser.wait(3);
const pageData = await session.browser.evaluate(`
var title = document.title;
var url = window.location.href;
var productCount = document.querySelectorAll(".product").length;
var hasNextPage = !!document.querySelector(".pagination .next");
return {
title: title,
url: url,
productCount: productCount,
hasNextPage: hasNextPage
};
`);
console.log("Page title:", pageData.title);
console.log("Current URL:", pageData.url);
console.log("Products found:", pageData.productCount);
console.log("Has next page:", pageData.hasNextPage);
await session.close();
}
puppeteerStyleEvaluate();
session.browser.getCookies()
The getCookies() method retrieves all cookies currently stored in the
browser session and returns them as a key-value object. Each key in the returned
object is a cookie name, and each value is the corresponding cookie value. This
method is essential for inspecting the browser's cookie state at any point during
your automation workflow. You can use it to verify that authentication cookies were
set after a login, check consent cookies, inspect session identifiers, or extract
tracking cookies for analysis. The method sends a getCookies action to
the BBRE engine and processes the response to extract the cookies object. If the
browser has no cookies, or if the response format does not contain cookie data, the
method returns an empty object. The returned cookies include all cookies for the
current domain and any cookies set for parent domains that are accessible from the
current page, following standard browser cookie scoping rules.
Method Signature
const cookies = await session.browser.getCookies();
Parameters
The getCookies() method does not accept any parameters. It retrieves
all cookies from the current browser session.
| Parameter | Type | Required | Description |
|---|---|---|---|
| This method does not accept any parameters. | |||
Return Type
The method returns a Promise that resolves to an object containing
cookie name-value pairs. If no cookies are present, an empty object is returned.
| Return Type | Description |
|---|---|
| Promise<object> | Resolves to an object where keys are cookie names and values are cookie values. Returns an empty object {} if no cookies are present. |
Retrieve All Cookies
The basic usage of getCookies() retrieves all cookies from the browser
and logs them. This is useful for debugging and understanding what cookies a website
sets during normal browsing.
const { BBRESession } = require("mydisctsolver-bbre");
const session = new BBRESession({
apiKey: "YOUR_API_KEY",
mode: "adaptive",
sensibility: "medium"
});
async function inspectCookies() {
await session.start();
await session.browser.navigate("https://example.com");
await session.browser.wait(2);
const cookies = await session.browser.getCookies();
const cookieNames = Object.keys(cookies);
console.log("Total cookies:", cookieNames.length);
cookieNames.forEach(function(name) {
console.log(name + ":", cookies[name]);
});
await session.close();
}
inspectCookies();
Verify Authentication Cookies After Login
After performing a login flow, use getCookies() to verify that the
expected authentication cookies were set. This is a critical validation step in
automation workflows that depend on authenticated sessions.
const { BBRESession } = require("mydisctsolver-bbre");
const session = new BBRESession({
apiKey: "YOUR_API_KEY",
mode: "adaptive",
sensibility: "high"
});
async function verifyLoginCookies() {
await session.start();
await session.browser.navigate("https://example.com/login");
await session.browser.wait(2);
await session.browser.fill("#username", "testuser");
await session.browser.fill("#password", "testpassword");
await session.browser.click("#login-submit");
await session.browser.wait(3);
const cookies = await session.browser.getCookies();
if (cookies["session_id"]) {
console.log("Login successful, session cookie found");
console.log("Session ID:", cookies["session_id"]);
} else {
console.log("Login may have failed, no session cookie found");
}
if (cookies["auth_token"]) {
console.log("Auth token cookie present");
}
await session.close();
}
verifyLoginCookies();
Extract and Save Cookies for Later Use
You can extract cookies from a browser session and save them to a file for later use. This is useful when you want to persist authentication state across multiple automation runs without repeating the login process each time.
const { BBRESession } = require("mydisctsolver-bbre");
const fs = require("fs");
const session = new BBRESession({
apiKey: "YOUR_API_KEY",
mode: "adaptive",
sensibility: "medium"
});
async function saveCookiesToFile() {
await session.start();
await session.browser.navigate("https://example.com/login");
await session.browser.wait(2);
await session.browser.fill("#email", "[email protected]");
await session.browser.fill("#password", "securepassword");
await session.browser.click("#login-btn");
await session.browser.wait(3);
const cookies = await session.browser.getCookies();
fs.writeFileSync("cookies.json", JSON.stringify(cookies, null, 2));
console.log("Cookies saved to cookies.json");
console.log("Cookie count:", Object.keys(cookies).length);
await session.close();
}
saveCookiesToFile();
session.browser.setCookie(name, value, options)
The setCookie() method sets a single cookie in the browser session with
the specified name, value, and optional configuration. This method gives you full
control over cookie attributes including domain, path, expiration, httpOnly flag, and
secure flag. Setting cookies programmatically is essential for a wide range of
automation scenarios: injecting authentication tokens to skip login flows, setting
consent cookies to bypass cookie banners, configuring locale or language preferences,
and pre-loading session state before navigating to a page. The method sends a
setCookie action to the BBRE engine with the name, value, and any
additional options merged into the action payload. The cookie is set immediately in
the browser and will be included in subsequent HTTP requests to matching domains and
paths, following standard browser cookie behavior.
Method Signature
await session.browser.setCookie(name, value, options);
Parameters
The setCookie() method accepts three parameters: the cookie name and
value are required, and an optional options object controls additional cookie
attributes.
| Parameter | Type | Required | Description |
|---|---|---|---|
name |
string | Required | The name of the cookie to set. Must be a non-empty string. Cookie names are case-sensitive. |
value |
string | Required | The value to assign to the cookie. Can be any string value including empty strings, JSON-encoded objects, or encoded tokens. |
options |
object | Optional | An object containing additional cookie attributes. When omitted, the cookie is set with default browser behavior for the current domain and path. |
options.domain |
string | Optional | The domain for which the cookie is valid. If omitted, the cookie is set for the current page's domain. Use a leading dot (e.g., .example.com) to make the cookie available to all subdomains. |
options.path |
string | Optional | The URL path for which the cookie is valid. Defaults to "/" if omitted, making the cookie available on all paths. |
options.expires |
number | Optional | The expiration time of the cookie as a Unix timestamp (seconds since epoch). If omitted, the cookie is a session cookie that expires when the browser session ends. |
options.httpOnly |
boolean | Optional | When set to true, the cookie is not accessible via JavaScript's document.cookie API. Defaults to false. |
options.secure |
boolean | Optional | When set to true, the cookie is only sent over HTTPS connections. Defaults to false. |
Return Type
The method returns a Promise that resolves to the action result object
from the BBRE engine confirming the cookie was set.
| Return Type | Description |
|---|---|
| Promise<object> | Resolves to the action result from the BBRE engine containing the cookie set confirmation. |
Set a Simple Cookie
The simplest usage of setCookie() sets a cookie with just a name and
value. The cookie will be scoped to the current domain and path with default
attributes.
const { BBRESession } = require("mydisctsolver-bbre");
const session = new BBRESession({
apiKey: "YOUR_API_KEY",
mode: "adaptive",
sensibility: "medium"
});
async function setSimpleCookie() {
await session.start();
await session.browser.navigate("https://example.com");
await session.browser.wait(1);
await session.browser.setCookie("user_preference", "dark_mode");
const cookies = await session.browser.getCookies();
console.log("user_preference:", cookies["user_preference"]);
await session.close();
}
setSimpleCookie();
Set a Cookie with Full Options
For production use cases, you typically need to set cookies with specific domain, path, expiration, and security attributes. This example demonstrates setting a cookie with all available options.
const { BBRESession } = require("mydisctsolver-bbre");
const session = new BBRESession({
apiKey: "YOUR_API_KEY",
mode: "adaptive",
sensibility: "medium"
});
async function setFullOptionsCookie() {
await session.start();
await session.browser.navigate("https://example.com");
await session.browser.wait(1);
const oneHourFromNow = Math.floor(Date.now() / 1000) + 3600;
await session.browser.setCookie("auth_token", "eyJhbGciOiJIUzI1NiJ9.abc123", {
domain: ".example.com",
path: "/",
expires: oneHourFromNow,
httpOnly: true,
secure: true
});
console.log("Auth cookie set with 1 hour expiration");
await session.browser.navigate("https://example.com/dashboard");
await session.browser.wait(2);
const pageTitle = await session.browser.getTitle();
console.log("Dashboard title:", pageTitle);
await session.close();
}
setFullOptionsCookie();
Inject Authentication Cookie to Skip Login
One of the most practical uses of setCookie() is injecting an
authentication cookie before navigating to a protected page. This lets you skip the
login flow entirely, saving time and credits in automation workflows that need to
access authenticated content. You can obtain the cookie value from a previous
session, a saved cookies file, or an external authentication service.
const { BBRESession } = require("mydisctsolver-bbre");
const fs = require("fs");
const session = new BBRESession({
apiKey: "YOUR_API_KEY",
mode: "adaptive",
sensibility: "medium"
});
async function skipLoginWithCookie() {
await session.start();
await session.browser.navigate("https://example.com");
await session.browser.wait(1);
var savedCookies = JSON.parse(fs.readFileSync("cookies.json", "utf8"));
var cookieNames = Object.keys(savedCookies);
for (var i = 0; i < cookieNames.length; i++) {
var name = cookieNames[i];
await session.browser.setCookie(name, savedCookies[name], {
domain: ".example.com",
path: "/"
});
}
console.log("Injected", cookieNames.length, "cookies");
await session.browser.navigate("https://example.com/account/settings");
await session.browser.wait(2);
const currentUrl = await session.browser.getUrl();
console.log("Current URL:", currentUrl);
if (currentUrl.indexOf("/login") === -1) {
console.log("Successfully accessed protected page without login");
} else {
console.log("Cookies may have expired, redirected to login");
}
await session.close();
}
skipLoginWithCookie();
Set Consent Cookie to Bypass Cookie Banner
Many websites display a cookie consent banner that blocks interaction until the user accepts or rejects cookies. By setting the consent cookie before navigating to the page, you can bypass this banner entirely and interact with the page content immediately.
const { BBRESession } = require("mydisctsolver-bbre");
const session = new BBRESession({
apiKey: "YOUR_API_KEY",
mode: "adaptive",
sensibility: "medium"
});
async function bypassCookieBanner() {
await session.start();
await session.browser.navigate("https://example.com");
await session.browser.wait(1);
await session.browser.setCookie("cookie_consent", "accepted", {
domain: ".example.com",
path: "/",
expires: Math.floor(Date.now() / 1000) + 86400 * 365
});
await session.browser.setCookie("gdpr_consent", "1", {
domain: ".example.com",
path: "/"
});
await session.browser.navigate("https://example.com/products");
await session.browser.wait(2);
const pageText = await session.browser.getText("body");
console.log("Page loaded without cookie banner");
console.log("Content length:", pageText.length);
await session.close();
}
bypassCookieBanner();
session.browser.clearCookies()
The clearCookies() method removes all cookies from the browser session.
Internally, it sends a deleteCookies action to the BBRE engine with an
empty options object, which instructs the engine to delete every cookie stored in the
browser. This method is useful for resetting the browser's authentication state,
testing login flows from a clean state, switching between user accounts within the
same session, and ensuring that no residual cookies from previous navigation affect
subsequent requests. After calling clearCookies(), the browser will
behave as if it has never visited any website before, with no session identifiers,
authentication tokens, consent flags, or tracking cookies. Any page that depends on
cookies for authentication will require a fresh login after cookies are cleared.
Method Signature
await session.browser.clearCookies();
Parameters
The clearCookies() method does not accept any parameters. It removes
all cookies from the browser session unconditionally.
| Parameter | Type | Required | Description |
|---|---|---|---|
| This method does not accept any parameters. | |||
Return Type
The method returns a Promise that resolves to the action result object
from the BBRE engine confirming the cookies were deleted.
| Return Type | Description |
|---|---|
| Promise<object> | Resolves to the action result from the BBRE engine confirming all cookies were deleted. |
Clear All Cookies
The basic usage of clearCookies() removes all cookies and verifies
that the browser is in a clean state.
const { BBRESession } = require("mydisctsolver-bbre");
const session = new BBRESession({
apiKey: "YOUR_API_KEY",
mode: "adaptive",
sensibility: "medium"
});
async function clearAllCookies() {
await session.start();
await session.browser.navigate("https://example.com");
await session.browser.wait(2);
const beforeCookies = await session.browser.getCookies();
console.log("Cookies before clear:", Object.keys(beforeCookies).length);
await session.browser.clearCookies();
const afterCookies = await session.browser.getCookies();
console.log("Cookies after clear:", Object.keys(afterCookies).length);
await session.close();
}
clearAllCookies();
Test Login Flow from Clean State
When testing login functionality, you need to ensure that no existing authentication
cookies interfere with the test. Call clearCookies() before starting the
login flow to guarantee a clean state.
const { BBRESession } = require("mydisctsolver-bbre");
const session = new BBRESession({
apiKey: "YOUR_API_KEY",
mode: "adaptive",
sensibility: "high"
});
async function testLoginFromCleanState() {
await session.start();
await session.browser.navigate("https://example.com");
await session.browser.wait(1);
await session.browser.clearCookies();
console.log("Cookies cleared, starting fresh login test");
await session.browser.navigate("https://example.com/login");
await session.browser.wait(2);
await session.browser.fill("#username", "testuser");
await session.browser.fill("#password", "testpassword");
await session.browser.click("#login-button");
await session.browser.wait(3);
const cookies = await session.browser.getCookies();
const hasSessionCookie = !!cookies["session_id"];
console.log("Login created session cookie:", hasSessionCookie);
const currentUrl = await session.browser.getUrl();
console.log("Redirected to:", currentUrl);
await session.close();
}
testLoginFromCleanState();
Switch Between User Accounts
When your automation needs to interact with a website as multiple different users
within the same session, use clearCookies() between account switches
to ensure that the previous user's authentication state does not carry over.
const { BBRESession } = require("mydisctsolver-bbre");
const session = new BBRESession({
apiKey: "YOUR_API_KEY",
mode: "adaptive",
sensibility: "medium"
});
async function loginAsUser(username, password) {
await session.browser.navigate("https://example.com/login");
await session.browser.wait(2);
await session.browser.fill("#username", username);
await session.browser.fill("#password", password);
await session.browser.click("#login-button");
await session.browser.wait(3);
return await session.browser.getUrl();
}
async function switchBetweenAccounts() {
await session.start();
var redirectUrl = await loginAsUser("admin_user", "admin_pass");
console.log("Admin logged in, redirected to:", redirectUrl);
var adminData = await session.browser.getText(".admin-panel");
console.log("Admin panel content:", adminData.substring(0, 100));
await session.browser.clearCookies();
console.log("Cookies cleared, switching to regular user");
redirectUrl = await loginAsUser("regular_user", "regular_pass");
console.log("Regular user logged in, redirected to:", redirectUrl);
var userData = await session.browser.getText(".user-dashboard");
console.log("User dashboard content:", userData.substring(0, 100));
await session.close();
}
switchBetweenAccounts();
Combined Cookie Management
The three cookie methods (getCookies(), setCookie(), and
clearCookies()) work together to give you complete control over the
browser's cookie state. This section demonstrates practical patterns that combine
all three methods in real-world automation scenarios.
Cookie Backup and Restore
This pattern saves the current cookie state, performs an operation that modifies cookies, and then restores the original cookies. This is useful when you need to temporarily change the browser's authentication state without losing the original session.
const { BBRESession } = require("mydisctsolver-bbre");
const session = new BBRESession({
apiKey: "YOUR_API_KEY",
mode: "adaptive",
sensibility: "medium"
});
async function cookieBackupAndRestore() {
await session.start();
await session.browser.navigate("https://example.com/login");
await session.browser.wait(2);
await session.browser.fill("#email", "[email protected]");
await session.browser.fill("#password", "primarypass");
await session.browser.click("#login-btn");
await session.browser.wait(3);
var originalCookies = await session.browser.getCookies();
console.log("Saved", Object.keys(originalCookies).length, "cookies");
await session.browser.clearCookies();
await session.browser.navigate("https://example.com/login");
await session.browser.wait(2);
await session.browser.fill("#email", "[email protected]");
await session.browser.fill("#password", "secondarypass");
await session.browser.click("#login-btn");
await session.browser.wait(3);
var secondaryData = await session.browser.getText(".profile-name");
console.log("Secondary user profile:", secondaryData);
await session.browser.clearCookies();
var cookieNames = Object.keys(originalCookies);
for (var i = 0; i < cookieNames.length; i++) {
var name = cookieNames[i];
await session.browser.setCookie(name, originalCookies[name], {
domain: ".example.com",
path: "/"
});
}
console.log("Restored", cookieNames.length, "original cookies");
await session.browser.navigate("https://example.com/dashboard");
await session.browser.wait(2);
var primaryData = await session.browser.getText(".profile-name");
console.log("Primary user profile:", primaryData);
await session.close();
}
cookieBackupAndRestore();
Cookie-Based A/B Testing
Many websites use cookies to assign users to A/B test groups. By manipulating these cookies, you can force the browser into a specific test variant and capture screenshots or extract data from each variant for comparison.
const { BBRESession } = require("mydisctsolver-bbre");
const fs = require("fs");
const session = new BBRESession({
apiKey: "YOUR_API_KEY",
mode: "adaptive",
sensibility: "low"
});
async function captureABTestVariants() {
await session.start();
var variants = ["control", "variant_a", "variant_b"];
for (var i = 0; i < variants.length; i++) {
var variant = variants[i];
await session.browser.clearCookies();
await session.browser.navigate("https://example.com");
await session.browser.wait(1);
await session.browser.setCookie("ab_test_group", variant, {
domain: ".example.com",
path: "/"
});
await session.browser.navigate("https://example.com/landing");
await session.browser.wait(3);
var screenshot = await session.browser.screenshot({ fullPage: true });
var filename = "ab-test-" + variant + ".png";
fs.writeFileSync(filename, Buffer.from(screenshot, "base64"));
var headline = await session.browser.getText("h1");
var ctaText = await session.browser.getText(".cta-button");
console.log("Variant:", variant);
console.log(" Headline:", headline);
console.log(" CTA:", ctaText);
console.log(" Screenshot saved:", filename);
}
await session.close();
}
captureABTestVariants();
Multi-Domain Cookie Management
When your automation workflow spans multiple domains (for example, a main site and
its API subdomain), you can use setCookie() with explicit domain
settings to manage cookies across domains within the same session.
const { BBRESession } = require("mydisctsolver-bbre");
const session = new BBRESession({
apiKey: "YOUR_API_KEY",
mode: "adaptive",
sensibility: "medium"
});
async function multiDomainCookies() {
await session.start();
await session.browser.navigate("https://example.com");
await session.browser.wait(1);
await session.browser.setCookie("session_token", "abc123xyz", {
domain: ".example.com",
path: "/",
secure: true
});
await session.browser.setCookie("api_token", "api_key_value_here", {
domain: "api.example.com",
path: "/v1/",
secure: true,
httpOnly: true
});
await session.browser.setCookie("cdn_pref", "us-east", {
domain: "cdn.example.com",
path: "/"
});
var allCookies = await session.browser.getCookies();
console.log("Total cookies set:", Object.keys(allCookies).length);
await session.browser.navigate("https://example.com/dashboard");
await session.browser.wait(3);
var dashboardContent = await session.browser.getText(".dashboard-content");
console.log("Dashboard loaded:", dashboardContent.length, "characters");
await session.close();
}
multiDomainCookies();
JavaScript Execution Patterns
The execute() and evaluate() methods open up a wide range
of possibilities for browser automation. This section covers common patterns that
you will encounter frequently when building automation workflows with the BBRE SDK.
Extract Table Data as Structured Array
HTML tables are one of the most common data structures on the web. This pattern extracts all rows from a table and converts them into an array of objects with column headers as keys.
const { BBRESession } = require("mydisctsolver-bbre");
const session = new BBRESession({
apiKey: "YOUR_API_KEY",
mode: "adaptive",
sensibility: "medium"
});
async function extractTableData() {
await session.start();
await session.browser.navigate("https://example.com/pricing");
await session.browser.wait(3);
var tableData = await session.browser.execute(`
var table = document.querySelector("table.pricing-table");
if (!table) return [];
var headers = [];
var headerCells = table.querySelectorAll("thead th");
for (var h = 0; h < headerCells.length; h++) {
headers.push(headerCells[h].textContent.trim());
}
var rows = [];
var bodyRows = table.querySelectorAll("tbody tr");
for (var r = 0; r < bodyRows.length; r++) {
var cells = bodyRows[r].querySelectorAll("td");
var row = {};
for (var c = 0; c < cells.length; c++) {
if (c < headers.length) {
row[headers[c]] = cells[c].textContent.trim();
}
}
rows.push(row);
}
return rows;
`);
console.log("Extracted", tableData.length, "rows from pricing table");
tableData.forEach(function(row) {
console.log(JSON.stringify(row));
});
await session.close();
}
extractTableData();
Wait for a Dynamic Condition
While the BrowserAPI provides waitForElement() and
waitForText() methods, sometimes you need to wait for a more complex
condition that cannot be expressed with a simple CSS selector or text match. The
execute() method lets you implement custom polling logic directly in
the browser.
const { BBRESession } = require("mydisctsolver-bbre");
const session = new BBRESession({
apiKey: "YOUR_API_KEY",
mode: "adaptive",
sensibility: "medium"
});
async function waitForCustomCondition() {
await session.start();
await session.browser.navigate("https://example.com/dashboard");
await session.browser.wait(2);
var isReady = await session.browser.execute(`
return new Promise(function(resolve) {
var attempts = 0;
var maxAttempts = 20;
var interval = setInterval(function() {
attempts++;
var spinner = document.querySelector(".loading-spinner");
var content = document.querySelector(".dashboard-content");
if ((!spinner || spinner.style.display === "none") && content && content.children.length > 0) {
clearInterval(interval);
resolve(true);
}
if (attempts >= maxAttempts) {
clearInterval(interval);
resolve(false);
}
}, 500);
});
`);
if (isReady) {
console.log("Dashboard content loaded successfully");
var content = await session.browser.getText(".dashboard-content");
console.log("Content:", content.substring(0, 200));
} else {
console.log("Dashboard content did not load within timeout");
}
await session.close();
}
waitForCustomCondition();
Modify CSS Styles for Better Scraping
Some websites use CSS to hide content that is present in the DOM but not visible to
users. By modifying CSS styles with execute(), you can reveal hidden
content, remove animations that interfere with screenshots, or adjust the layout
for better data extraction.
const { BBRESession } = require("mydisctsolver-bbre");
const fs = require("fs");
const session = new BBRESession({
apiKey: "YOUR_API_KEY",
mode: "adaptive",
sensibility: "low"
});
async function cleanPageForScreenshot() {
await session.start();
await session.browser.navigate("https://example.com/article");
await session.browser.wait(3);
await session.browser.execute(`
var style = document.createElement("style");
style.textContent = [
".ad-banner { display: none !important; }",
".popup-overlay { display: none !important; }",
".sticky-header { position: relative !important; }",
".cookie-notice { display: none !important; }",
"* { animation: none !important; transition: none !important; }"
].join(" ");
document.head.appendChild(style);
`);
await session.browser.wait(0.5);
var screenshot = await session.browser.screenshot({ fullPage: true });
fs.writeFileSync("clean-article.png", Buffer.from(screenshot, "base64"));
console.log("Clean screenshot saved");
await session.close();
}
cleanPageForScreenshot();
Trigger Custom Events
Some web applications respond to custom JavaScript events rather than standard click
or input events. The execute() method lets you dispatch any event type,
including custom events with arbitrary data payloads.
const { BBRESession } = require("mydisctsolver-bbre");
const session = new BBRESession({
apiKey: "YOUR_API_KEY",
mode: "adaptive",
sensibility: "medium"
});
async function triggerCustomEvents() {
await session.start();
await session.browser.navigate("https://example.com/spa");
await session.browser.wait(3);
await session.browser.execute(`
var searchInput = document.querySelector("#search-input");
if (searchInput) {
searchInput.value = "automation tools";
searchInput.dispatchEvent(new Event("input", { bubbles: true }));
searchInput.dispatchEvent(new Event("change", { bubbles: true }));
}
`);
await session.browser.wait(2);
var results = await session.browser.execute(`
var items = document.querySelectorAll(".search-result");
var data = [];
for (var i = 0; i < items.length; i++) {
data.push(items[i].textContent.trim());
}
return data;
`);
console.log("Search results:", results.length);
results.forEach(function(result) {
console.log(" -", result.substring(0, 80));
});
await session.close();
}
triggerCustomEvents();
Extract Computed Styles and Dimensions
When you need to verify visual properties of elements or calculate positions for
scroll operations, execute() gives you access to
getComputedStyle() and getBoundingClientRect(), which
are not available through the standard BrowserAPI methods.
const { BBRESession } = require("mydisctsolver-bbre");
const session = new BBRESession({
apiKey: "YOUR_API_KEY",
mode: "adaptive",
sensibility: "medium"
});
async function extractElementDimensions() {
await session.start();
await session.browser.navigate("https://example.com/layout-test");
await session.browser.wait(2);
var dimensions = await session.browser.execute(`
var element = document.querySelector(".main-content");
if (!element) return null;
var rect = element.getBoundingClientRect();
var style = window.getComputedStyle(element);
return {
width: rect.width,
height: rect.height,
top: rect.top,
left: rect.left,
fontSize: style.fontSize,
color: style.color,
backgroundColor: style.backgroundColor,
padding: style.padding,
margin: style.margin
};
`);
if (dimensions) {
console.log("Element dimensions:", dimensions.width, "x", dimensions.height);
console.log("Position:", dimensions.top, ",", dimensions.left);
console.log("Font size:", dimensions.fontSize);
console.log("Background:", dimensions.backgroundColor);
}
await session.close();
}
extractElementDimensions();
Best Practices
When building multi-step automation workflows, capture a screenshot after every
critical action (page navigation, form submission, button click, login attempt).
These screenshots create a visual audit trail that is invaluable for debugging
failures. When a workflow fails at step 7 of 10, the screenshots from steps 1
through 6 show you exactly what the browser saw at each point, making it much
easier to identify where things went wrong. Store screenshots with descriptive
filenames that include the step number and a brief description, such as
step03-form-submitted.png. In production environments, consider
using JPEG format with quality 70 to 80 to reduce storage costs while maintaining
enough visual detail for debugging.
When you need to extract multiple pieces of data from a page, use a single
execute() call that returns all the data in one object instead of
making multiple separate getText() or getHtml() calls.
Each BrowserAPI method call is a round trip to the BBRE engine, so combining
multiple extractions into a single execute() call reduces latency
and credit consumption. For example, instead of calling getText("h1"),
getText(".price"), and getText(".description")
separately, write a single execute() script that returns
{ title: ..., price: ..., description: ... }.
When writing scripts for execute() or evaluate(),
always include an explicit return statement if you expect a value
back. The auto-wrapping IIFE means your script runs inside a function body, so
without a return statement, the function returns
undefined regardless of what your script computes. This is a common
source of confusion for developers who expect the last expression's value to be
returned automatically. If your script only performs side effects (like removing
an element or modifying a style) and you do not need a return value, you can
omit the return statement.
When your automation workflow navigates between different domains within the same
session, call clearCookies() before navigating to the new domain to
prevent cookie leakage. While browsers enforce same-origin policies for cookie
access, clearing cookies ensures a completely clean state and prevents any
unexpected behavior from residual cookies. This is especially important when
switching between a staging environment and a production environment, or when
testing multiple independent websites in sequence.
After calling setCookie(), always verify that the cookie was
actually set by calling getCookies() and checking for the expected
cookie name and value. Some cookie configurations may be silently rejected by
the browser, for example if you try to set a secure cookie on an HTTP page, or
if the domain does not match the current page's domain. Validating the cookie
state immediately after setting it catches these issues early, before they cause
mysterious failures later in the workflow when the website does not recognize
the expected authentication or preference cookies.
Resist the temptation to write long, complex scripts for execute().
Instead, break complex operations into multiple smaller execute()
calls, each performing a single focused task. This makes your code easier to
debug because you can identify exactly which step failed. It also makes the
scripts easier to maintain and test. If you find yourself writing more than 20
to 30 lines of JavaScript in a single execute() call, consider
splitting it into multiple calls or using the built-in BrowserAPI methods for
the parts that they can handle natively.
Common Issues
Symptom: You call execute() with a script that
computes a value, but the method returns undefined instead of the
expected result.
Cause: The script does not include a return
statement. When the script is auto-wrapped in an IIFE, the function body must
explicitly return a value. Without a return statement, the IIFE
returns undefined by default. This is different from the browser
console where the last expression's value is automatically displayed.
Solution: Add a return statement before the value
you want to capture. For example, change
document.title; to return document.title;. If you are
using a pre-wrapped IIFE, make sure the function returns the value:
(function() { return document.title; })().
Symptom: The screenshot() method returns a base64
string that is unusually short (less than 1000 characters), and the resulting
image is blank or shows only a white page.
Cause: The screenshot was captured before the page finished
loading. The browser may have started rendering but the main content, images,
and CSS styles have not been fully loaded yet. This is especially common on
pages with heavy JavaScript rendering or large image assets.
Solution: Add a longer wait() call before taking
the screenshot. Start with 3 to 5 seconds and adjust based on the target page's
loading speed. For pages with dynamic content, use
waitForSelector() to wait for a specific element that indicates the
page is fully loaded before capturing the screenshot.
Symptom: You set a cookie with setCookie(), but
after navigating to a new page, getCookies() does not include the
cookie you set.
Cause: The cookie's domain or path does not match the new page's
URL. Browsers only include cookies in requests when the domain and path match.
If you set a cookie for example.com but navigate to
shop.example.com, the cookie may not be visible unless you used a
domain with a leading dot (.example.com) to make it available to
all subdomains.
Solution: When setting cookies that need to persist across
subdomains, use the domain option with a leading dot:
{ domain: ".example.com" }. Also ensure the path
option is set to "/" to make the cookie available on all paths.
After setting the cookie, call getCookies() to verify it was
accepted before navigating.
Symptom: The execute() method throws an error
indicating a JavaScript syntax error in the script you provided.
Cause: The script string contains characters that conflict with
the string delimiter or the IIFE wrapping. Common causes include unescaped
backticks inside template literal strings, unmatched parentheses or braces, or
using ES6+ syntax that the browser engine does not support. Another common cause
is including HTML entities like < in the script string when
the script is embedded in an EJS template.
Solution: Test your script in a browser console first to verify
it is syntactically correct. When embedding scripts in strings, be careful with
quote escaping. Use var instead of let or
const if you encounter scope-related issues with the IIFE wrapping.
If the script is complex, consider storing it in a separate file and reading it
at runtime.
Symptom: You can see cookies in the browser's developer tools,
but getCookies() returns an empty object {}.
Cause: The cookies may be httpOnly cookies that are not
accessible through the standard cookie API, or the response format from the BBRE
engine may not match the expected structure. The getCookies() method
checks multiple response formats (r.result.cookies and
r.cookies) but may not find the cookies if the engine returns them
in an unexpected format.
Solution: Try using execute() to read cookies
directly via document.cookie:
execute("return document.cookie;"). This returns the cookie string
as the browser sees it, which may include cookies that
getCookies() missed. Note that httpOnly cookies will not appear in
document.cookie either, as they are intentionally hidden from
JavaScript access for security reasons.
Symptom: Any browser method call throws an error containing
[SESSION_STOPPED] in the message, and subsequent calls also fail.
Cause: A previous browser action failed, and because
session.force is set to false (the default), the
session was automatically closed after the failure. Once a session is stopped,
no further browser actions can be executed on it.
Solution: Wrap all browser action calls in try-catch blocks to
handle failures gracefully. If you want the session to continue even when
individual actions fail, set force: true when creating the session.
With force mode enabled, failed actions will throw errors but the session will
remain active for subsequent calls. Always check the session status after
catching an error to determine if the session is still usable.