Chat with us, powered by LiveChat
← Return to MyDisct Solver

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.

Adaptive Mode Required

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.

Session Failure Behavior

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

JavaScript
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.

JavaScript
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.

JavaScript
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.

JavaScript
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.

JavaScript
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.

JavaScript
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

JavaScript
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; })()
Use return Statements to Get Values Back

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.

JavaScript
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.

JavaScript
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.

JavaScript
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.

JavaScript
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.

JavaScript
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

JavaScript
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.

JavaScript
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.

JavaScript
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

JavaScript
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.

JavaScript
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.

JavaScript
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.

JavaScript
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.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

JavaScript
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.

JavaScript
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.

JavaScript
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.

JavaScript
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();

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.

JavaScript
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.

JavaScript
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.

JavaScript
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.

JavaScript
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.

JavaScript
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

Save Screenshots at Every Critical Step in Your Workflow

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.

Use execute() Return Values Instead of Separate Query Calls

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: ... }.

Always Use return Statements in execute() Scripts

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.

Clear Cookies Before Navigating to a New Domain

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.

Validate Cookie State After Setting Cookies

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.

Keep execute() Scripts Simple and Focused

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

execute() Returns undefined Instead of Expected Value

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; })().

screenshot() Returns Empty or Very Short Base64 String

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.

setCookie() Does Not Persist After Page Navigation

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.

execute() Script Fails with Syntax Error

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 &lt; 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.

getCookies() Returns Empty Object on a Page with Visible Cookies

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.

Browser Actions Fail with [SESSION_STOPPED] Error

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.