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

Session Request Methods

The BBRESession class provides five powerful request methods that cover every type of HTTP and browser interaction you might need within an active session: request(), submitForm(), runSteps(), interact(), and checkPage(). These methods build on top of the session lifecycle (start, close, status) and give you fine-grained control over how your session communicates with target websites. The request() method is the lowest-level entry point, sending a raw HTTP request through the session with full control over method, headers, body, cookies, authentication, redirects, and timeout. It automatically merges session cookies with per-request cookies, stores response cookies back into the session cookie jar, and updates the session profile whenever the BBRE engine returns new profile data. The submitForm() method is a high-level convenience wrapper that navigates to a URL, fills form fields, selects dropdown values, checks checkboxes, clicks a submit button, and waits for a result, all in a single call. The runSteps() method navigates to a URL and then executes an arbitrary array of step objects in sequence, giving you full control over multi-step browser workflows like checkout flows, multi-page wizards, and complex data entry processes. The interact() method is similar to runSteps() but uses an options.actions array instead of a separate steps parameter, making it convenient for inline action definitions. The checkPage() method navigates to a URL and optionally checks for the presence of specific text or elements, returning a simple result object with success, found, finalUrl, and cookies fields. This page provides complete documentation for all five methods, including method signatures, parameter tables, return types, internal behavior, step type references, practical code examples for real-world scenarios, best practices for production usage, common issues with solutions, and links to related documentation pages.

About Session Request Methods

All five request methods documented on this page require an active session. You must call session.start() before using any of these methods. If you call request() without starting the session first, it throws an error with the message "Session not started. Call start() first." The browser-based methods (submitForm(), runSteps(), interact(), and checkPage()) internally use the batch browser action system, which means they require the session to be running in "adaptive" mode. The request() method works in both "passive" and "adaptive" modes since it sends standard HTTP requests through the session. All methods automatically manage cookies: session cookies persist across calls, and response cookies are merged back into the session cookie jar after each request completes.

session.request(options)

The request() method sends an HTTP request through the active session, maintaining the session's cookie state and browser profile across multiple calls. This is the core method for making HTTP requests within a session context. Unlike the standalone BBREClient.request() method, the session version automatically merges the session's accumulated cookies with any per-request cookies you provide, sends the merged cookies along with the request, stores any cookies returned in the response back into the session cookie jar, and updates the session's browser profile whenever the BBRE engine returns new profile data. This cookie and profile management happens transparently, so you can focus on your request logic without manually tracking state between calls.

Internally, request() first checks that the session has been started by verifying that sessionId is set. If the session has not been started, it throws an error immediately. It then merges the session's stored cookies with any cookies provided in the options object, giving priority to the per-request cookies when there are conflicts. The merged cookies and the session ID are passed to the internal _sessionRequest() method, which sends a POST request to the /session/request endpoint on the BBRE API. When the response comes back, any cookies in the response are merged back into the session cookie jar, and if the response contains profile data, the session profile is updated. The formatted response is then returned to the caller.

Method Signature

JavaScript
const response = await session.request(options);

Parameters

The request() method accepts a single options object with the following properties. The url property is the only required field. All other properties have sensible defaults that work for most use cases.

Parameter Type Required Description
options.url string Required The target URL to send the request to. Must be a fully qualified URL including the protocol (http or https).
options.method string Optional The HTTP method to use. Defaults to "GET". The value is automatically converted to uppercase internally. Common values: "GET", "POST", "PUT", "DELETE", "PATCH", "HEAD", "OPTIONS".
options.headers object Optional Custom HTTP headers to include in the request. Defaults to an empty object. These headers are merged with the session's default headers. Example: { "Content-Type": "application/json", "Accept": "text/html" }.
options.body any Optional The request body. Can be a string, object, or any serializable value. For JSON payloads, pass a plain JavaScript object and set the Content-Type header to "application/json". For form data, pass a URL-encoded string.
options.params object Optional URL query parameters as key-value pairs. These are appended to the URL as query string parameters. Example: { page: 1, limit: 20 } becomes ?page=1&limit=20.
options.cookies object Optional Additional cookies to include in this specific request. These are merged with the session's accumulated cookies. Per-request cookies take priority over session cookies when there are name conflicts. Defaults to an empty object.
options.timeout number Optional Request timeout in seconds. Defaults to 120 seconds. The BBRE engine will abort the request if it does not complete within this time. The actual HTTP client timeout is set to timeout * 1000 + 10000 milliseconds to allow for processing overhead.
options.allowRedirects boolean Optional Whether to follow HTTP redirects automatically. Defaults to true. Set to false if you need to inspect redirect responses (3xx status codes) directly.
options.maxRedirects number Optional Maximum number of redirects to follow when allowRedirects is true. Defaults to 10. Prevents infinite redirect loops by capping the number of consecutive redirects.
options.verify boolean Optional Whether to verify SSL/TLS certificates. Defaults to true. Set to false to allow requests to servers with self-signed or expired certificates. Use with caution in production environments.
options.auth object Optional HTTP authentication credentials. Pass an object with username and password properties for Basic authentication. Defaults to null (no authentication).

Return Type

The request() method returns a Promise that resolves to a formatted response object. The response is processed by the internal formatResponse() method, which extracts the relevant fields from the BBRE engine's raw response and adds processing time information.

Field Type Description
statusCode number The HTTP status code returned by the target server (e.g., 200, 301, 404, 500).
headers object The response headers returned by the target server as key-value pairs.
body string The response body content as a string. For JSON responses, you need to parse this with JSON.parse().
cookies object Cookies returned in the response. These are automatically merged into the session cookie jar.
processingTime number The total processing time in milliseconds, including network latency and BBRE engine processing.

Cookie Merging Behavior

Understanding how cookies are managed is critical for session-based workflows. The request() method implements a two-phase cookie management strategy that ensures cookies accumulate correctly across multiple requests within the same session.

Phase 1 (Before Request): The method merges the session's stored cookies (this.sessionCookies) with any cookies you provide in options.cookies. The per-request cookies take priority, meaning if both the session and the request options contain a cookie with the same name, the value from options.cookies is used. This allows you to override specific session cookies for individual requests without permanently changing the session state.

Phase 2 (After Response): When the response comes back, any cookies included in the response are merged into the session cookie jar. This means that cookies set by the target server (such as session tokens, CSRF tokens, or tracking cookies) are automatically preserved and sent with subsequent requests. You do not need to manually extract and re-send cookies between requests.

Basic GET Request

The simplest usage of request() sends a GET request to a URL through the active session. The session's cookies and profile are automatically included in the request.

JavaScript
const { BBRESession } = require("mydisctsolver-bbre");

const session = new BBRESession({
  apiKey: "YOUR_API_KEY",
  mode: "passive",
  sensibility: "medium"
});

async function fetchPageThroughSession() {
  await session.start();

  const response = await session.request({
    url: "https://httpbin.org/get"
  });

  console.log("Status:", response.statusCode);
  console.log("Body length:", response.body.length);
  console.log("Cookies received:", Object.keys(response.cookies).length);

  await session.close();
}

fetchPageThroughSession();

POST Request with JSON Body

To send a POST request with a JSON payload, set the method to "POST", provide the body as a JavaScript object, and include the appropriate Content-Type header. The session cookies are automatically included, which is essential for authenticated API calls where the server expects a session cookie.

JavaScript
const { BBRESession } = require("mydisctsolver-bbre");

const session = new BBRESession({
  apiKey: "YOUR_API_KEY",
  mode: "passive",
  sensibility: "low"
});

async function postDataThroughSession() {
  await session.start();

  const response = await session.request({
    url: "https://httpbin.org/post",
    method: "POST",
    headers: {
      "Content-Type": "application/json",
      "Accept": "application/json"
    },
    body: {
      username: "testuser",
      action: "update_profile",
      data: {
        displayName: "Test User",
        timezone: "UTC"
      }
    }
  });

  console.log("Status:", response.statusCode);

  const result = JSON.parse(response.body);
  console.log("Server received:", result.json);

  await session.close();
}

postDataThroughSession();

Authenticated Request with Basic Auth

When the target server requires HTTP Basic authentication, pass the credentials through the auth option. The BBRE engine handles the Base64 encoding and header construction internally. Combined with session cookies, this allows you to authenticate once and maintain the authenticated state across subsequent requests.

JavaScript
const { BBRESession } = require("mydisctsolver-bbre");

const session = new BBRESession({
  apiKey: "YOUR_API_KEY",
  mode: "passive",
  sensibility: "medium"
});

async function authenticatedSessionRequest() {
  await session.start();

  const loginResponse = await session.request({
    url: "https://httpbin.org/basic-auth/myuser/mypass",
    auth: {
      username: "myuser",
      password: "mypass"
    }
  });

  console.log("Auth status:", loginResponse.statusCode);

  const protectedResponse = await session.request({
    url: "https://httpbin.org/get",
    headers: {
      "Accept": "application/json"
    }
  });

  console.log("Protected page status:", protectedResponse.statusCode);

  await session.close();
}

authenticatedSessionRequest();

Request with Custom Cookies and Query Parameters

You can pass additional cookies and query parameters alongside the session's existing cookies. Per-request cookies are merged with session cookies, and query parameters are appended to the URL automatically.

JavaScript
const { BBRESession } = require("mydisctsolver-bbre");

const session = new BBRESession({
  apiKey: "YOUR_API_KEY",
  mode: "passive",
  sensibility: "low"
});

async function requestWithCookiesAndParams() {
  await session.start();

  const response = await session.request({
    url: "https://httpbin.org/get",
    params: {
      page: 2,
      limit: 50,
      sort: "created_at"
    },
    cookies: {
      tracking_id: "abc123",
      preferences: "dark_mode"
    },
    timeout: 60,
    allowRedirects: true,
    maxRedirects: 5
  });

  console.log("Status:", response.statusCode);
  console.log("Processing time:", response.processingTime, "ms");

  await session.close();
}

requestWithCookiesAndParams();

Multi-Request Session with Cookie Persistence

One of the most powerful features of session requests is automatic cookie persistence. When you make multiple requests within the same session, cookies from each response are stored and automatically included in subsequent requests. This is essential for workflows that involve logging in, navigating authenticated pages, and performing actions that depend on server-side session state.

JavaScript
const { BBRESession } = require("mydisctsolver-bbre");

const session = new BBRESession({
  apiKey: "YOUR_API_KEY",
  mode: "passive",
  sensibility: "medium"
});

async function multiRequestWorkflow() {
  await session.start();

  const loginResponse = await session.request({
    url: "https://example.com/api/login",
    method: "POST",
    headers: { "Content-Type": "application/json" },
    body: { email: "[email protected]", password: "securepass" }
  });

  console.log("Login status:", loginResponse.statusCode);

  const dashboardResponse = await session.request({
    url: "https://example.com/api/dashboard"
  });

  console.log("Dashboard status:", dashboardResponse.statusCode);

  const settingsResponse = await session.request({
    url: "https://example.com/api/settings",
    method: "PUT",
    headers: { "Content-Type": "application/json" },
    body: { theme: "dark", language: "en" }
  });

  console.log("Settings update:", settingsResponse.statusCode);

  await session.close();
}

multiRequestWorkflow();

Error Handling for request()

The request() method throws errors in several scenarios: when the session has not been started, when the BBRE engine returns a failure response, when the request times out, or when a network error occurs. Always wrap session requests in try-catch blocks, especially in production workflows where you need to handle failures gracefully and ensure the session is properly closed.

JavaScript
const { BBRESession } = require("mydisctsolver-bbre");

const session = new BBRESession({
  apiKey: "YOUR_API_KEY",
  mode: "passive",
  sensibility: "medium"
});

async function safeSessionRequest() {
  try {
    await session.start();

    const response = await session.request({
      url: "https://example.com/api/data",
      timeout: 30
    });

    console.log("Status:", response.statusCode);
    return response;
  } catch (error) {
    console.log("Session request failed:", error.message);
    return null;
  } finally {
    if (session.isActive()) {
      await session.close();
    }
  }
}

safeSessionRequest();

session.submitForm(url, options)

The submitForm() method is a high-level convenience method designed specifically for form submission workflows. Instead of manually constructing a sequence of browser actions (navigate, fill fields, select dropdowns, check boxes, click submit), you describe the form interaction declaratively through an options object, and submitForm() builds and executes the entire sequence for you. This method is ideal for login forms, registration forms, search forms, contact forms, and any other HTML form that requires filling fields and clicking a submit button.

Internally, submitForm() constructs an ordered array of step objects based on the options you provide. It always starts with a navigation step to the specified URL. If you provide options.fields, it adds a fill step that populates input fields using CSS selectors as keys and field values as values. If you provide options.select, it adds a select step for dropdown menus. If you provide options.checkbox, it adds one or more checkbox steps (the value can be a single string or an array of strings, where each string is the checkbox label text). If you provide options.submit, it adds a click step that clicks the submit button using the provided CSS selector. If you provide options.waitFor, it adds a final wait step that waits for specific text or an element to appear after submission. The constructed steps are then converted into batch actions using the internal _buildBatchActions() method and executed through the browser action system. The stopOnError behavior defaults to the inverse of the session's force setting, meaning errors will stop execution unless you explicitly set force: true in the constructor or override stopOnError in the options.

Method Signature

JavaScript
const result = await session.submitForm(url, options);

Parameters

The submitForm() method accepts a URL string as the first argument and an optional options object as the second argument. The URL is the page containing the form you want to submit. The options object describes the form fields, selections, checkboxes, submit button, and post-submission wait conditions.

Parameter Type Required Description
url string Required The URL of the page containing the form. The method navigates to this URL before interacting with the form elements.
options object Optional Configuration object describing the form interaction. All properties are optional. If omitted, the method simply navigates to the URL without performing any form actions.
options.fields object Optional An object mapping CSS selectors to values for text input fields. Each key is a CSS selector that identifies an input element, and each value is the text to type into that field. Example: { "#email": "[email protected]", "#password": "secret123" }.
options.select object Optional An object mapping CSS selectors to values for dropdown select elements. Each key is a CSS selector that identifies a <select> element, and each value is the option value to select. Example: { "#country": "US", "#language": "en" }.
options.checkbox string | string[] Optional A checkbox label text or an array of checkbox label texts to check. Each string identifies a checkbox by its associated label text. The method creates a separate checkbox action for each item. Example: "I agree to terms" or ["Newsletter", "Terms of Service"].
options.submit string Optional A CSS selector for the submit button to click after filling the form. Example: "button[type='submit']" or "#login-btn".
options.waitFor string | object Optional A condition to wait for after form submission. Can be a simple string (waits for that text to appear on the page) or an object with text, selector, and timeout properties for more precise control. Example: "Welcome back" or { text: "Dashboard", timeout: 10 }.
options.waitUntil string Optional The page load event to wait for during navigation. Defaults to "load". Other common values: "domcontentloaded", "networkidle".
options.timeout number Optional Navigation timeout in seconds. Defaults to 30. This controls how long the browser waits for the initial page load before timing out.
options.stopOnError boolean Optional Whether to stop executing remaining steps when an error occurs. Defaults to the inverse of the session's force setting. Set to false to continue executing remaining steps even if one fails.

Return Type

The submitForm() method returns a Promise that resolves to a batch result object. This object contains information about the overall success of the form submission, the final URL after any redirects, cookies set during the process, individual step results, and completion statistics.

Field Type Description
success boolean Whether all steps in the form submission completed successfully. true if every step succeeded, false if any step failed.
finalUrl string The URL of the page after all steps have been executed. This may differ from the original URL if the form submission triggered a redirect.
cookies object Cookies collected during the form submission process, including any new cookies set by the server after form submission.
results array An array of individual step results. Each element corresponds to one step in the execution sequence and contains the outcome of that specific action.
stepsCompleted number The number of steps that were executed. If stopOnError is true and an error occurs, this may be less than totalSteps.
totalSteps number The total number of steps that were planned for execution, including the navigation step.

Login Form Submission

The most common use case for submitForm() is submitting a login form. This example navigates to a login page, fills in the email and password fields, clicks the login button, and waits for the dashboard text to appear, confirming a successful login.

JavaScript
const { BBRESession } = require("mydisctsolver-bbre");

const session = new BBRESession({
  apiKey: "YOUR_API_KEY",
  mode: "adaptive",
  sensibility: "medium",
  browserSpeed: "human"
});

async function loginToWebsite() {
  await session.start();

  const result = await session.submitForm("https://example.com/login", {
    fields: {
      "#email": "[email protected]",
      "#password": "securepassword123"
    },
    submit: "button[type='submit']",
    waitFor: "Welcome back"
  });

  console.log("Login success:", result.success);
  console.log("Final URL:", result.finalUrl);
  console.log("Steps completed:", result.stepsCompleted, "/", result.totalSteps);

  await session.close();
}

loginToWebsite();

Registration Form with Dropdowns and Checkboxes

For more complex forms that include dropdown menus and checkboxes in addition to text fields, use the select and checkbox options. This example fills a registration form with a name, email, password, country selection, language preference, and terms acceptance checkbox.

JavaScript
const { BBRESession } = require("mydisctsolver-bbre");

const session = new BBRESession({
  apiKey: "YOUR_API_KEY",
  mode: "adaptive",
  sensibility: "high",
  browserSpeed: "human"
});

async function registerAccount() {
  await session.start();

  const result = await session.submitForm("https://example.com/register", {
    fields: {
      "#full-name": "Alice Johnson",
      "#email": "[email protected]",
      "#password": "StrongP@ss2024",
      "#confirm-password": "StrongP@ss2024"
    },
    select: {
      "#country": "US",
      "#language": "en"
    },
    checkbox: [
      "I agree to the Terms of Service",
      "Subscribe to newsletter"
    ],
    submit: "#register-btn",
    waitFor: {
      text: "Registration successful",
      timeout: 15
    },
    timeout: 30
  });

  console.log("Registration success:", result.success);
  console.log("Final URL:", result.finalUrl);
  console.log("Cookies after registration:", Object.keys(result.cookies));

  if (result.success) {
    console.log("All", result.totalSteps, "steps completed successfully");
  } else {
    console.log("Completed", result.stepsCompleted, "of", result.totalSteps, "steps");
  }

  await session.close();
}

registerAccount();

Search Form Submission

Search forms are another common use case. This example navigates to a search page, enters a search query, selects a category from a dropdown, and clicks the search button. The waitFor option waits for search results to appear before returning.

JavaScript
const { BBRESession } = require("mydisctsolver-bbre");

const session = new BBRESession({
  apiKey: "YOUR_API_KEY",
  mode: "adaptive",
  sensibility: "low",
  browserSpeed: "fast"
});

async function searchProducts(query, category) {
  await session.start();

  const result = await session.submitForm("https://example.com/search", {
    fields: {
      "#search-input": query
    },
    select: {
      "#category-filter": category
    },
    submit: "#search-btn",
    waitFor: {
      selector: ".search-results",
      timeout: 10
    }
  });

  console.log("Search completed:", result.success);
  console.log("Results page URL:", result.finalUrl);

  await session.close();
  return result;
}

searchProducts("wireless headphones", "electronics");

Form Submission with Single Checkbox

When a form has only one checkbox, you can pass a single string instead of an array to the checkbox option. The method handles both formats transparently.

JavaScript
const { BBRESession } = require("mydisctsolver-bbre");

const session = new BBRESession({
  apiKey: "YOUR_API_KEY",
  mode: "adaptive",
  sensibility: "medium"
});

async function submitContactForm() {
  await session.start();

  const result = await session.submitForm("https://example.com/contact", {
    fields: {
      "#name": "Bob Smith",
      "#email": "[email protected]",
      "#message": "I have a question about your enterprise plan pricing and features."
    },
    checkbox: "I consent to data processing",
    submit: "button.submit-btn",
    waitFor: "Thank you for your message"
  });

  console.log("Form submitted:", result.success);

  await session.close();
}

submitContactForm();

session.runSteps(url, steps, options)

The runSteps() method is the most flexible browser automation method in the BBRESession class. It navigates to a URL and then executes an arbitrary array of step objects in sequence, giving you complete control over the browser interaction flow. Unlike submitForm() which is optimized for form-specific workflows, runSteps() accepts any combination of step types, making it suitable for complex multi-step workflows like e-commerce checkout flows, multi-page wizards, data entry processes, and any scenario where you need to perform a specific sequence of browser actions.

Internally, runSteps() prepends a navigation step to the beginning of your steps array, so the first action is always navigating to the specified URL. Your step objects are then appended after the navigation step. The combined array is converted into batch actions using _buildBatchActions() and executed through the browser action system. The stopOnError behavior follows the same logic as submitForm(): it defaults to the inverse of the session's force setting unless you explicitly override it in the options.

Method Signature

JavaScript
const result = await session.runSteps(url, steps, options);

Parameters

The runSteps() method accepts three arguments: the target URL, an array of step objects, and an optional options object for controlling navigation and error behavior.

Parameter Type Required Description
url string Required The URL to navigate to before executing the steps. This becomes the first step in the execution sequence.
steps array Required An array of step objects to execute in order after navigation. Each step object must contain exactly one step type key. See the Step Types Reference section below for all supported step types.
options object Optional Configuration object for navigation and execution behavior.
options.waitUntil string Optional The page load event to wait for during the initial navigation. Defaults to "load".
options.timeout number Optional Navigation timeout in seconds for the initial page load. Defaults to 30.
options.stopOnError boolean Optional Whether to stop executing remaining steps when an error occurs. Defaults to the inverse of the session's force setting.

Step Types Reference

Each step in the steps array is a plain JavaScript object with exactly one key that identifies the step type. The value associated with that key provides the step's configuration. The following table documents all supported step types that can be used with runSteps(), interact(), and internally by submitForm().

Step Type Value Type Description
navigate string Navigates the browser to the specified URL. The value is the target URL string. Example: { navigate: "https://example.com/page2" }.
fill object Fills input fields with values. The value is an object mapping CSS selectors to text values. Example: { fill: { "#username": "alice", "#email": "[email protected]" } }.
select object Selects options in dropdown elements. The value is an object mapping CSS selectors to option values. Example: { select: { "#country": "US" } }.
checkbox string Checks a checkbox identified by its label text. The value is the label text string. Example: { checkbox: "Remember me" }.
click string Clicks an element identified by a CSS selector. The value is the CSS selector string. Example: { click: "#next-btn" } or { click: "a.continue-link" }.
wait number Pauses execution for the specified number of seconds. Useful for waiting for animations, AJAX requests, or dynamic content to load. Example: { wait: 2 }.
waitFor string | object Waits for specific text or an element to appear on the page. Can be a simple string (waits for that text) or an object with text, selector, and timeout properties. Example: { waitFor: "Order confirmed" } or { waitFor: { selector: ".results", timeout: 10 } }.
scroll object Scrolls the page with custom options. The value is an object with scroll configuration properties. Example: { scroll: { x: 0, y: 500 } }.
scrollDown number Scrolls the page down by the specified number of pixels. Example: { scrollDown: 300 }.
execute string Executes a JavaScript script in the browser context. The value is the JavaScript code as a string. Example: { execute: "document.title" }.

Return Type

The runSteps() method returns the same batch result object as submitForm(). See the submitForm() Return Type section above for the complete field reference.

Multi-Step Login and Data Extraction

This example demonstrates a multi-step workflow that logs into a website, navigates to a specific page, scrolls down to load dynamic content, and executes JavaScript to extract data from the page.

JavaScript
const { BBRESession } = require("mydisctsolver-bbre");

const session = new BBRESession({
  apiKey: "YOUR_API_KEY",
  mode: "adaptive",
  sensibility: "medium",
  browserSpeed: "human"
});

async function loginAndExtractData() {
  await session.start();

  const result = await session.runSteps("https://example.com/login", [
    { fill: { "#email": "[email protected]", "#password": "securepass" } },
    { click: "#login-btn" },
    { waitFor: "Dashboard" },
    { navigate: "https://example.com/dashboard/reports" },
    { waitFor: { selector: ".report-table", timeout: 10 } },
    { scrollDown: 500 },
    { wait: 1 },
    { execute: "JSON.stringify(Array.from(document.querySelectorAll('.report-row')).map(r => r.textContent))" }
  ]);

  console.log("Workflow success:", result.success);
  console.log("Steps completed:", result.stepsCompleted, "/", result.totalSteps);
  console.log("Final URL:", result.finalUrl);

  if (result.results && result.results.length > 0) {
    const lastResult = result.results[result.results.length - 1];
    console.log("Extracted data:", lastResult);
  }

  await session.close();
}

loginAndExtractData();

E-Commerce Checkout Flow

This example demonstrates a complete e-commerce checkout flow that adds a product to the cart, proceeds to checkout, fills in shipping information, selects a shipping method, and confirms the order. Each step builds on the previous one, and the session maintains cookies and state throughout the entire process.

JavaScript
const { BBRESession } = require("mydisctsolver-bbre");

const session = new BBRESession({
  apiKey: "YOUR_API_KEY",
  mode: "adaptive",
  sensibility: "high",
  browserSpeed: "human"
});

async function checkoutFlow() {
  await session.start();

  const result = await session.runSteps("https://shop.example.com/product/12345", [
    { click: "#add-to-cart" },
    { waitFor: "Added to cart" },
    { wait: 1 },
    { click: "#go-to-checkout" },
    { waitFor: { selector: "#checkout-form", timeout: 10 } },
    { fill: {
        "#first-name": "Alice",
        "#last-name": "Johnson",
        "#address": "123 Main Street",
        "#city": "San Francisco",
        "#zip": "94102",
        "#phone": "+1-555-0123"
    } },
    { select: { "#state": "CA", "#country": "US" } },
    { click: "#shipping-standard" },
    { wait: 1 },
    { click: "#continue-to-payment" },
    { waitFor: { selector: "#payment-form", timeout: 10 } },
    { fill: {
        "#card-number": "4111111111111111",
        "#card-expiry": "12/26",
        "#card-cvv": "123"
    } },
    { click: "#place-order" },
    { waitFor: { text: "Order confirmed", timeout: 15 } }
  ]);

  console.log("Checkout success:", result.success);
  console.log("Steps completed:", result.stepsCompleted, "/", result.totalSteps);
  console.log("Order page URL:", result.finalUrl);

  await session.close();
}

checkoutFlow();

Multi-Page Wizard with Scroll and Wait

Some websites use multi-page wizards where you fill information across several pages. This example demonstrates navigating through a three-step wizard, filling fields on each page, scrolling to reveal hidden content, and waiting for page transitions.

JavaScript
const { BBRESession } = require("mydisctsolver-bbre");

const session = new BBRESession({
  apiKey: "YOUR_API_KEY",
  mode: "adaptive",
  sensibility: "medium",
  browserSpeed: "fast"
});

async function multiPageWizard() {
  await session.start();

  const result = await session.runSteps("https://example.com/apply/step1", [
    { fill: { "#first-name": "Bob", "#last-name": "Smith", "#dob": "1990-05-15" } },
    { select: { "#gender": "male" } },
    { scrollDown: 400 },
    { click: "#next-step" },
    { waitFor: { selector: "#step2-form", timeout: 10 } },

    { fill: { "#street": "456 Oak Avenue", "#city": "Portland", "#zip": "97201" } },
    { select: { "#state": "OR" } },
    { click: "#next-step" },
    { waitFor: { selector: "#step3-form", timeout: 10 } },

    { fill: { "#employer": "Acme Corp", "#position": "Engineer", "#years": "5" } },
    { checkbox: "I certify this information is accurate" },
    { scrollDown: 300 },
    { click: "#submit-application" },
    { waitFor: "Application submitted successfully" }
  ], {
    timeout: 45,
    stopOnError: true
  });

  console.log("Application submitted:", result.success);
  console.log("Total steps executed:", result.stepsCompleted);

  await session.close();
}

multiPageWizard();

session.interact(url, options)

The interact() method provides a convenient way to navigate to a URL and execute a series of browser actions defined in an options.actions array. It is functionally similar to runSteps(), but instead of accepting the steps as a separate parameter, the actions are embedded within the options object. This makes interact() particularly well-suited for scenarios where you want to define the entire interaction inline as a single configuration object, such as when building dynamic interaction sequences from configuration files, database records, or user-defined workflows.

Internally, interact() constructs a steps array that starts with a navigation step to the specified URL, then appends each action from the options.actions array. The combined steps are converted into batch actions and executed through the browser action system, following the same execution model as runSteps() and submitForm(). The stopOnError behavior defaults to the inverse of the session's force setting, and you can override it through the options.

Method Signature

JavaScript
const result = await session.interact(url, options);

Parameters

The interact() method accepts a URL string and an optional options object. The options.actions array contains the step objects to execute after navigation. All step types supported by runSteps() are also supported here.

Parameter Type Required Description
url string Required The URL to navigate to before executing the actions.
options object Optional Configuration object containing the actions array and execution settings.
options.actions array Optional An array of step objects to execute after navigation. Each step object follows the same format as the steps in runSteps(). If omitted, the method only navigates to the URL without performing additional actions.
options.waitUntil string Optional The page load event to wait for during navigation. Defaults to "load".
options.timeout number Optional Navigation timeout in seconds. Defaults to 30.
options.stopOnError boolean Optional Whether to stop executing remaining actions when an error occurs. Defaults to the inverse of the session's force setting.

Return Type

The interact() method returns the same batch result object as runSteps() and submitForm(). See the submitForm() Return Type section for the complete field reference.

Page Interaction with Click and Scroll

This example navigates to a product listing page, scrolls down to load more products, clicks on a specific product, and waits for the product detail page to load. The actions are defined inline within the options object.

JavaScript
const { BBRESession } = require("mydisctsolver-bbre");

const session = new BBRESession({
  apiKey: "YOUR_API_KEY",
  mode: "adaptive",
  sensibility: "medium",
  browserSpeed: "human"
});

async function browseProducts() {
  await session.start();

  const result = await session.interact("https://shop.example.com/products", {
    actions: [
      { waitFor: { selector: ".product-grid", timeout: 10 } },
      { scrollDown: 800 },
      { wait: 2 },
      { scrollDown: 800 },
      { wait: 1 },
      { click: ".product-card:nth-child(5) a" },
      { waitFor: { selector: ".product-detail", timeout: 10 } }
    ]
  });

  console.log("Browsing success:", result.success);
  console.log("Final URL:", result.finalUrl);
  console.log("Steps completed:", result.stepsCompleted, "/", result.totalSteps);

  await session.close();
}

browseProducts();

Data Extraction with JavaScript Execution

The interact() method is excellent for data extraction workflows where you need to navigate to a page, wait for content to load, and then execute JavaScript to extract structured data from the DOM. This example extracts product information from a listing page.

JavaScript
const { BBRESession } = require("mydisctsolver-bbre");

const session = new BBRESession({
  apiKey: "YOUR_API_KEY",
  mode: "adaptive",
  sensibility: "low",
  browserSpeed: "fast"
});

async function extractProductData() {
  await session.start();

  const result = await session.interact("https://shop.example.com/category/electronics", {
    actions: [
      { waitFor: { selector: ".product-list", timeout: 10 } },
      { scrollDown: 1000 },
      { wait: 2 },
      { execute: "JSON.stringify(Array.from(document.querySelectorAll('.product-item')).map(item => ({ name: item.querySelector('.name').textContent.trim(), price: item.querySelector('.price').textContent.trim(), rating: item.querySelector('.rating').textContent.trim() })))" }
    ],
    timeout: 30
  });

  console.log("Extraction success:", result.success);

  if (result.results && result.results.length > 0) {
    const extractedData = result.results[result.results.length - 1];
    console.log("Products found:", extractedData);
  }

  await session.close();
}

extractProductData();

Dynamic Interaction Sequence from Configuration

Because interact() accepts actions as part of the options object, you can easily build dynamic interaction sequences from external configuration. This pattern is useful for building configurable scraping pipelines where the interaction steps are defined in a database or configuration file.

JavaScript
const { BBRESession } = require("mydisctsolver-bbre");

const session = new BBRESession({
  apiKey: "YOUR_API_KEY",
  mode: "adaptive",
  sensibility: "medium"
});

function buildActionsFromConfig(config) {
  const actions = [];

  if (config.waitForSelector) {
    actions.push({ waitFor: { selector: config.waitForSelector, timeout: 10 } });
  }

  if (config.scrollPixels) {
    actions.push({ scrollDown: config.scrollPixels });
    actions.push({ wait: 1 });
  }

  if (config.clickSelector) {
    actions.push({ click: config.clickSelector });
  }

  if (config.extractScript) {
    actions.push({ execute: config.extractScript });
  }

  return actions;
}

async function runConfigurableInteraction(targetUrl, config) {
  await session.start();

  const actions = buildActionsFromConfig(config);

  const result = await session.interact(targetUrl, {
    actions: actions,
    stopOnError: false
  });

  console.log("Interaction success:", result.success);
  console.log("Steps completed:", result.stepsCompleted);

  await session.close();
  return result;
}

const pageConfig = {
  waitForSelector: ".content-loaded",
  scrollPixels: 600,
  clickSelector: "#load-more",
  extractScript: "document.querySelector('.main-content').textContent"
};

runConfigurableInteraction("https://example.com/articles", pageConfig);

session.checkPage(url, options)

The checkPage() method is a lightweight utility method designed for verifying page availability and checking for the presence of specific content. Unlike the other browser methods that return full batch results with step arrays and completion statistics, checkPage() returns a simplified result object with just four fields: success, found, finalUrl, and cookies. This makes it ideal for health checks, content verification, redirect detection, and pre-flight page validation before starting more complex workflows.

Internally, checkPage() constructs a minimal steps array: a navigation step to the specified URL, and optionally a waitFor step if you provide the options.check parameter. The steps are executed with stopOnError always set to false, which means the method never throws an error due to step failures. Instead, it returns a result object where success indicates whether the navigation succeeded and found indicates whether the checked content was detected on the page. This non-throwing behavior makes checkPage() safe to use in conditional logic without requiring try-catch blocks for normal operation.

Method Signature

JavaScript
const result = await session.checkPage(url, options);

Parameters

The checkPage() method accepts a URL string and an optional options object. The options.check parameter defines what content to look for on the page after navigation.

Parameter Type Required Description
url string Required The URL to navigate to and check.
options object Optional Configuration object for the page check.
options.check string | object Optional The content to check for on the page. Can be a simple string (checks for that text on the page) or an object with text, selector, and timeout properties. If omitted, the method only checks whether the page loads successfully without looking for specific content. When omitted, the found field in the result is always false.
options.waitUntil string Optional The page load event to wait for during navigation. Defaults to "load".
options.timeout number Optional Navigation timeout in seconds. Defaults to 30.

Return Type

The checkPage() method returns a simplified result object with four fields. Unlike the other browser methods, it does not include results, stepsCompleted, or totalSteps fields.

Field Type Description
success boolean Whether the page navigation completed successfully. true if the page loaded without errors, false if navigation failed (timeout, network error, etc.).
found boolean Whether the checked content was found on the page. true if the text or element specified in options.check was detected, false otherwise. Always false when options.check is not provided.
finalUrl string The URL of the page after navigation, including any redirects. Useful for detecting redirect chains and verifying the final destination.
cookies object Cookies collected during the page check, including any cookies set by the server during navigation.

Simple Page Availability Check

The simplest use of checkPage() verifies that a URL is accessible and loads successfully. This is useful for health checks and monitoring scripts that need to verify that a website is online.

JavaScript
const { BBRESession } = require("mydisctsolver-bbre");

const session = new BBRESession({
  apiKey: "YOUR_API_KEY",
  mode: "adaptive",
  sensibility: "low",
  browserSpeed: "instant"
});

async function checkPageAvailability(url) {
  await session.start();

  const result = await session.checkPage(url);

  console.log("Page accessible:", result.success);
  console.log("Final URL:", result.finalUrl);
  console.log("Cookies received:", Object.keys(result.cookies).length);

  await session.close();
  return result.success;
}

checkPageAvailability("https://example.com");

Content Detection with Text Check

Use the options.check parameter to verify that specific text appears on the page. This is useful for verifying that a page contains expected content, checking whether a user is logged in, or detecting error messages.

JavaScript
const { BBRESession } = require("mydisctsolver-bbre");

const session = new BBRESession({
  apiKey: "YOUR_API_KEY",
  mode: "adaptive",
  sensibility: "low",
  browserSpeed: "fast"
});

async function checkForContent(url, expectedText) {
  await session.start();

  const result = await session.checkPage(url, {
    check: expectedText
  });

  console.log("Page loaded:", result.success);
  console.log("Content found:", result.found);
  console.log("Final URL:", result.finalUrl);

  await session.close();
  return result.found;
}

checkForContent("https://example.com/status", "All systems operational");

Element Detection with Selector Check

For more precise content detection, pass an object to options.check with a selector property to check for the presence of a specific DOM element. You can also set a custom timeout to control how long the method waits for the element to appear.

JavaScript
const { BBRESession } = require("mydisctsolver-bbre");

const session = new BBRESession({
  apiKey: "YOUR_API_KEY",
  mode: "adaptive",
  sensibility: "low",
  browserSpeed: "fast"
});

async function checkForElement(url, selector) {
  await session.start();

  const result = await session.checkPage(url, {
    check: {
      selector: selector,
      timeout: 10
    }
  });

  console.log("Page loaded:", result.success);
  console.log("Element found:", result.found);

  await session.close();
  return result;
}

checkForElement("https://example.com/dashboard", "#user-profile-widget");

Redirect Detection

The finalUrl field in the result is particularly useful for detecting redirects. By comparing the original URL with the final URL, you can determine whether the page redirected and where it redirected to. This is useful for verifying authentication redirects, detecting URL canonicalization, and checking whether a page has been moved.

JavaScript
const { BBRESession } = require("mydisctsolver-bbre");

const session = new BBRESession({
  apiKey: "YOUR_API_KEY",
  mode: "adaptive",
  sensibility: "low",
  browserSpeed: "instant"
});

async function detectRedirect(url) {
  await session.start();

  const result = await session.checkPage(url);

  const wasRedirected = result.finalUrl !== url;

  console.log("Original URL:", url);
  console.log("Final URL:", result.finalUrl);
  console.log("Was redirected:", wasRedirected);

  if (wasRedirected) {
    console.log("Redirect destination:", result.finalUrl);
  }

  await session.close();
  return { wasRedirected, finalUrl: result.finalUrl };
}

detectRedirect("https://example.com/old-page");

Login State Verification

After performing a login through submitForm() or runSteps(), you can use checkPage() to verify that the login was successful by checking for authenticated content on a protected page. This pattern is useful for validating session state before proceeding with authenticated workflows.

JavaScript
const { BBRESession } = require("mydisctsolver-bbre");

const session = new BBRESession({
  apiKey: "YOUR_API_KEY",
  mode: "adaptive",
  sensibility: "medium",
  browserSpeed: "human"
});

async function loginAndVerify() {
  await session.start();

  await session.submitForm("https://example.com/login", {
    fields: {
      "#email": "[email protected]",
      "#password": "securepass"
    },
    submit: "#login-btn",
    waitFor: "Dashboard"
  });

  const verification = await session.checkPage("https://example.com/profile", {
    check: "Account Settings"
  });

  if (verification.found) {
    console.log("Login verified successfully");
    console.log("Profile page URL:", verification.finalUrl);
  } else {
    console.log("Login verification failed");
    console.log("Redirected to:", verification.finalUrl);
  }

  await session.close();
}

loginAndVerify();

Batch URL Checking

You can use checkPage() in a loop to check multiple URLs within the same session. Since the session maintains its state across calls, this is efficient for monitoring multiple pages or verifying a list of URLs.

JavaScript
const { BBRESession } = require("mydisctsolver-bbre");

const session = new BBRESession({
  apiKey: "YOUR_API_KEY",
  mode: "adaptive",
  sensibility: "low",
  browserSpeed: "instant"
});

async function checkMultiplePages(urls) {
  await session.start();

  const results = [];

  for (const url of urls) {
    const result = await session.checkPage(url, {
      check: { selector: "body", timeout: 5 }
    });

    results.push({
      url: url,
      accessible: result.success,
      contentFound: result.found,
      finalUrl: result.finalUrl
    });

    console.log(url, "->", result.success ? "OK" : "FAIL");
  }

  await session.close();

  const accessible = results.filter(r => r.accessible).length;
  console.log("Results:", accessible, "/", results.length, "pages accessible");

  return results;
}

const urlsToCheck = [
  "https://example.com",
  "https://example.com/about",
  "https://example.com/products",
  "https://example.com/contact"
];

checkMultiplePages(urlsToCheck);

Method Comparison

Choosing the right request method depends on your specific use case. The following table compares all five session request methods to help you decide which one to use for different scenarios.

Method Mode Use Case Complexity
request() passive / adaptive Raw HTTP requests with session cookie management. API calls, data fetching, form POST submissions without browser rendering. Low
submitForm() adaptive HTML form submissions with fields, dropdowns, checkboxes, and submit buttons. Login forms, registration forms, search forms. Low
runSteps() adaptive Complex multi-step browser workflows with full control over step sequence. Checkout flows, multi-page wizards, data entry processes. Medium
interact() adaptive Dynamic browser interactions defined as inline action arrays. Configurable scraping pipelines, page exploration, data extraction. Medium
checkPage() adaptive Page availability checks, content detection, redirect verification, login state validation. Returns simplified result. Low

When to Use request() vs Browser Methods

The request() method sends raw HTTP requests through the BBRE engine without rendering the page in a browser. This makes it faster and cheaper than the browser-based methods, but it cannot interact with JavaScript-rendered content, dynamic forms, or single-page applications. Use request() when you need to call REST APIs, fetch static HTML pages, or submit form data via POST without needing browser rendering. Use the browser methods (submitForm(), runSteps(), interact(), checkPage()) when you need to interact with pages that require JavaScript execution, dynamic content loading, or visual browser automation.

When to Use submitForm() vs runSteps()

Use submitForm() when your workflow is a straightforward form submission: navigate to a page, fill fields, select dropdowns, check boxes, click submit, and wait for a result. The declarative options object makes the code clean and readable. Use runSteps() when your workflow involves actions beyond form submission, such as navigating to multiple pages, scrolling, executing JavaScript, or performing actions in a specific order that does not fit the form submission pattern. The runSteps() method gives you full control over the step sequence, while submitForm() abstracts the sequence behind a declarative interface.

When to Use interact() vs runSteps()

Both interact() and runSteps() execute arrays of step objects after navigating to a URL. The difference is in the API design: runSteps() accepts the steps as a separate parameter (runSteps(url, steps, options)), while interact() embeds the actions within the options object (interact(url, { actions: [...] })). Use runSteps() when you have a pre-built array of steps that you want to pass directly. Use interact() when you want to define the actions inline as part of a single configuration object, which is particularly convenient when building dynamic interaction sequences from configuration data.

Error Handling

Each of the five request methods has different error behavior. Understanding these differences is important for writing robust session workflows.

Error Behavior by Method

Method Throws on Failure stopOnError Default Notes
request() Yes N/A Throws if session not started, if the BBRE engine returns an error, or if the request times out. Always wrap in try-catch.
submitForm() Depends !force Returns batch result. Individual step failures are reflected in the success field and stepsCompleted count.
runSteps() Depends !force Same behavior as submitForm(). Step failures are captured in the batch result.
interact() Depends !force Same behavior as runSteps(). Action failures are captured in the batch result.
checkPage() No false (always) Never stops on error. Navigation failures result in success: false. Content not found results in found: false.

Comprehensive Error Handling Pattern

The following example demonstrates a robust error handling pattern that covers all five request methods within a single session workflow. The try-catch-finally pattern ensures the session is always closed, even when errors occur.

JavaScript
const { BBRESession } = require("mydisctsolver-bbre");

const session = new BBRESession({
  apiKey: "YOUR_API_KEY",
  mode: "adaptive",
  sensibility: "medium",
  browserSpeed: "human"
});

async function robustWorkflow() {
  try {
    await session.start();

    const pageCheck = await session.checkPage("https://example.com/login", {
      check: { selector: "#login-form", timeout: 10 }
    });

    if (!pageCheck.success || !pageCheck.found) {
      console.log("Login page not available or form not found");
      return null;
    }

    const loginResult = await session.submitForm("https://example.com/login", {
      fields: { "#email": "[email protected]", "#password": "securepass" },
      submit: "#login-btn",
      waitFor: "Dashboard"
    });

    if (!loginResult.success) {
      console.log("Login failed at step", loginResult.stepsCompleted, "of", loginResult.totalSteps);
      return null;
    }

    const apiResponse = await session.request({
      url: "https://example.com/api/user/data",
      headers: { "Accept": "application/json" }
    });

    console.log("API response status:", apiResponse.statusCode);
    return JSON.parse(apiResponse.body);
  } catch (error) {
    console.log("Workflow error:", error.message);
    return null;
  } finally {
    if (session.isActive()) {
      await session.close();
    }
  }
}

robustWorkflow();

Best Practices

Always Close Sessions in a Finally Block

Wrap your session workflow in a try-catch-finally pattern and close the session in the finally block. This ensures the session is released even when errors occur during request execution. Unclosed sessions consume server resources and count against your 10-session-per-account limit until they expire automatically. Use session.isActive() to check whether the session needs closing before calling session.close() in the finally block.

Use checkPage() for Pre-flight Validation Before Complex Workflows

Before starting a complex multi-step workflow with runSteps() or submitForm(), use checkPage() to verify that the target page is accessible and contains the expected elements. Since checkPage() never throws errors and returns a simple boolean result, it is safe to use in conditional logic. This prevents wasting time and credits on workflows that will fail because the target page is down, has changed its structure, or requires authentication that has not been completed yet.

Prefer submitForm() Over Manual Step Construction for Form Workflows

When your workflow involves submitting an HTML form, use submitForm() instead of manually constructing fill, select, checkbox, and click steps with runSteps(). The submitForm() method handles the step construction internally and produces cleaner, more readable code. Reserve runSteps() for workflows that go beyond simple form submission, such as multi-page navigation, scrolling, JavaScript execution, or complex interaction sequences that do not fit the form submission pattern.

Use request() for API Calls and submitForm() for Browser Forms

The request() method sends raw HTTP requests without browser rendering, making it faster and more efficient for REST API calls, JSON endpoints, and static page fetching. The browser-based methods (submitForm(), runSteps(), interact()) render pages in a real browser, which is necessary for JavaScript-heavy sites but consumes more resources. Choose the right method based on whether the target requires browser rendering. Within the same session, you can mix request() calls with browser method calls to optimize your workflow.

Add waitFor Steps After Navigation and Form Submission

After navigating to a new page or submitting a form, always include a waitFor step that waits for specific content to appear before proceeding with the next action. This ensures that the page has fully loaded and the expected content is available before your workflow continues. Without waitFor steps, subsequent actions may fail because they try to interact with elements that have not been rendered yet. Use text-based waits ({ waitFor: "Welcome" }) for simple cases and selector-based waits ({ waitFor: { selector: "#content", timeout: 10 } }) for more precise control.

Set Appropriate Timeout Values Based on Target Site Performance

The default timeout for request() is 120 seconds, and the default navigation timeout for browser methods is 30 seconds. These defaults work well for most websites, but you should adjust them based on the target site's performance characteristics. For fast APIs, reduce the request() timeout to 30 or 60 seconds to fail faster on unresponsive servers. For slow-loading pages with heavy JavaScript, increase the navigation timeout to 45 or 60 seconds. For waitFor steps, set the timeout based on how long the specific content typically takes to appear after the triggering action.

Use Human Browser Speed for Sensitive Targets

When using browser methods (submitForm(), runSteps(), interact()) on websites with anti-bot detection, set the browser speed to "human" in the session constructor. This adds realistic delays between browser actions, simulating natural human interaction patterns. Combined with "high" sensibility, this significantly reduces the chance of detection. For internal tools and APIs where detection is not a concern, use "instant" or "fast" speed for maximum throughput.

Common Issues

"Session not started. Call start() first." Error

Symptom: Calling request() throws an error with the message "Session not started. Call start() first."
Cause: The request() method checks for a valid sessionId before sending the request. If session.start() has not been called, or if the session was already closed, the sessionId is null and the method throws immediately.
Solution: Always call await session.start() before using any request methods. If you are reusing a session object, check session.isActive() before making requests and call session.start() again if the session has expired or been closed.

submitForm() Steps Execute But Form Does Not Submit

Symptom: The submitForm() method returns success: true and all steps complete, but the form was not actually submitted. The finalUrl is still the form page URL.
Cause: The options.submit CSS selector does not match the actual submit button on the page. The click action executes without error because the selector syntax is valid, but it does not find a matching element or clicks the wrong element.
Solution: Verify the submit button selector by inspecting the target page's HTML. Common selectors include "button[type='submit']", "input[type='submit']", or a specific ID like "#submit-btn". Use the browser developer tools to test your selector before using it in submitForm(). Also ensure that the waitFor option is set to detect the post-submission page, which helps confirm whether the form was actually submitted.

runSteps() Fails Midway Through a Multi-Step Workflow

Symptom: The runSteps() method returns with success: false and stepsCompleted is less than totalSteps. Some steps executed successfully but the workflow stopped before completing all steps.
Cause: One of the steps failed (for example, a CSS selector did not match any element, a waitFor condition timed out, or a navigation failed), and stopOnError was true (the default when force is not set in the constructor).
Solution: Check the stepsCompleted value to identify which step failed. Review the step at that index in your steps array. Common fixes include adding wait steps before actions that depend on dynamic content, increasing waitFor timeouts, and verifying CSS selectors against the actual page structure. If you want the workflow to continue past failures, set stopOnError: false in the options.

checkPage() Returns found: false Even Though Content Exists

Symptom: The checkPage() method returns found: false even though you can see the expected content when visiting the page in a regular browser.
Cause: The content may be loaded dynamically via JavaScript after the initial page load. The default waitFor timeout may not be long enough for the dynamic content to render. Another common cause is that the content is inside an iframe or shadow DOM that the check cannot access directly.
Solution: Increase the timeout in the options.check object: { check: { text: "Expected text", timeout: 15 } }. If the content is loaded via AJAX, try using waitUntil: "networkidle" in the options to wait for all network requests to complete before checking. For content inside iframes, you may need to use runSteps() with an execute step to access the iframe content directly.

Cookies Not Persisting Between request() Calls

Symptom: You make a login request with request() and then a subsequent request to a protected page, but the server responds as if you are not authenticated. The session cookies from the login response are not being sent with the second request.
Cause: This typically happens when you create a new BBRESession instance between requests, or when the session was closed and restarted between the login and the subsequent request. Each session.start() call resets the session state, including cookies.
Solution: Ensure you are using the same session instance for all requests in your workflow, and that you do not call session.close() and session.start() between the login and subsequent requests. The cookie persistence only works within a single session lifecycle (from start() to close()).

Browser Methods Fail with "Session mode must be adaptive"

Symptom: Calling submitForm(), runSteps(), interact(), or checkPage() fails with an error indicating that the session mode must be adaptive.
Cause: The session was created with mode: "passive", which only supports raw HTTP requests through the request() method. Browser-based methods require the "adaptive" mode because they need a real browser instance to render pages and execute browser actions.
Solution: Set mode: "adaptive" in the BBRESession constructor: new BBRESession({ apiKey: "KEY", mode: "adaptive" }). If you need both raw HTTP requests and browser automation in the same workflow, use "adaptive" mode for the session and use request() for the HTTP calls and browser methods for the automation steps.