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

BrowserAPI Interaction Methods

The BrowserAPI class provides seven interaction methods through the session.browser interface that let you interact with page elements inside an adaptive mode BBRE session. The click(selector, options) method clicks on any element matching a CSS selector with a configurable delay before the click action. The fill(selector, value) method clears an input field and sets its value instantly, which is the fastest way to populate form fields. The type(selector, value, options) method types text character by character with a configurable delay between keystrokes, simulating realistic human typing behavior. The select(selector, value) method selects an option from a dropdown element by its value attribute. The checkbox(text) method clicks a checkbox by its associated label text, supporting both exact and partial text matching. The fillForm(fields, options) method fills multiple form fields in a single call and optionally submits the form, making it the most efficient way to handle complex forms. The clear(selector) method removes all content from an input field, resetting it to an empty state. All seven interaction methods require an active adaptive mode session because they operate on a real browser instance managed by the BBRE engine. This page provides complete documentation for every interaction method, including method signatures, parameter tables, practical code examples covering login forms, registration flows, search interfaces, multi-step forms, and data entry automation, along with a detailed comparison between fill() and type(), best practices, common issues, and links to related documentation.

Adaptive Mode Required

All BrowserAPI interaction 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 clicking elements, filling inputs, selecting dropdown options, and submitting forms. If you attempt to call interaction 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.

session.browser.click(selector, options)

The click() method clicks on the first element that matches the given CSS selector. Under the hood, it sends a click action to the BBRE engine with the selector and an optional delay parameter. The delay controls how long the engine waits before performing the click, which defaults to 0.1 seconds. This small default delay helps simulate natural user behavior where a brief pause occurs between locating an element and clicking it. You can increase the delay for scenarios where you want to mimic slower, more deliberate user interactions, or set it to a very small value for faster automation. The method resolves when the click action completes successfully and throws an error if the element is not found, not visible, or not clickable. This is the most fundamental interaction method and serves as the building block for button clicks, link navigation, menu toggling, tab switching, and any other action triggered by clicking a page element.

Method Signature

JavaScript
const result = await session.browser.click(selector, options);

Parameters

The click() method accepts a CSS selector string as the first argument and an optional options object as the second argument. The options object allows you to configure the delay before the click action is performed.

Parameter Type Required Description
selector string Required A CSS selector that identifies the element to click. The engine clicks the first element matching this selector. Supports standard CSS selectors including class selectors (.btn-submit), ID selectors (#login-button), attribute selectors ([data-action="save"]), and complex selectors (form .actions button.primary).
options object Optional Configuration object for the click action.
options.delay number Optional The delay in seconds before performing the click. Defaults to 0.1. Increase this value to simulate slower, more human-like interactions. Set to a smaller value for faster automation.

Basic Click Example

The simplest usage of click() targets an element by its CSS selector and clicks it with the default delay. This is suitable for most button clicks, link activations, and general element interactions.

JavaScript
const BBREClient = require("mydisctsolver-bbre");

const client = new BBREClient({ apiKey: "YOUR_API_KEY" });

async function clickButton() {
  const session = client.createSession({ mode: "adaptive" });
  await session.start();

  await session.browser.navigate("https://example.com/dashboard");

  await session.browser.click("#submit-button");

  await session.browser.click(".nav-menu .dropdown-toggle");

  await session.browser.click("[data-action='confirm']");

  await session.close();
}

clickButton();

Click with Custom Delay

When interacting with websites that monitor user behavior patterns, increasing the click delay makes the interaction appear more natural. A longer delay between locating an element and clicking it mimics the time a real user takes to move their cursor and decide to click.

JavaScript
const BBREClient = require("mydisctsolver-bbre");

const client = new BBREClient({ apiKey: "YOUR_API_KEY" });

async function clickWithDelay() {
  const session = client.createSession({ mode: "adaptive" });
  await session.start();

  await session.browser.navigate("https://example.com/checkout");

  await session.browser.click("#add-to-cart", { delay: 0.5 });

  await session.browser.click("#proceed-checkout", { delay: 0.8 });

  await session.browser.click("#confirm-order", { delay: 1.0 });

  await session.close();
}

clickWithDelay();

Sequential Click Navigation

Many web applications require a sequence of clicks to navigate through menus, pagination controls, or multi-step wizards. Chain multiple click() calls to automate these workflows.

JavaScript
const BBREClient = require("mydisctsolver-bbre");

const client = new BBREClient({ apiKey: "YOUR_API_KEY" });

async function navigateWithClicks() {
  const session = client.createSession({ mode: "adaptive" });
  await session.start();

  await session.browser.navigate("https://example.com");

  await session.browser.click(".main-nav a[href='/products']");

  await session.browser.click(".category-filter[data-category='electronics']");

  await session.browser.click(".product-list .product-card:first-child a");

  const title = await session.browser.getText("h1.product-title");
  console.log("Product:", title);

  await session.close();
}

navigateWithClicks();

session.browser.fill(selector, value)

The fill() method sets the value of an input field identified by a CSS selector. Unlike type(), which enters text character by character, the fill() method clears the existing content of the field and sets the new value instantly in a single operation. This makes it significantly faster than type() for populating form fields where character-by-character input is not necessary. The method sends a fill action to the BBRE engine with the selector and the text value. It works with standard HTML input elements including text inputs, password fields, email fields, textarea elements, and other form controls that accept text input. The method resolves when the value has been set successfully and throws an error if the element is not found, not visible, or not editable. Use fill() when you need fast, reliable form population and the target website does not require character-by-character input events to trigger validation or autocomplete behavior.

Method Signature

JavaScript
const result = await session.browser.fill(selector, value);

Parameters

The fill() method accepts a CSS selector string as the first argument and the value to set as the second argument. Both parameters are required.

Parameter Type Required Description
selector string Required A CSS selector that identifies the input element to fill. The engine targets the first element matching this selector. Works with <input>, <textarea>, and other editable form elements.
value string Required The text value to set in the input field. The existing content of the field is cleared before this value is set. Pass an empty string to clear the field without setting a new value.

Basic Fill Example

The simplest usage of fill() targets an input field and sets its value. The method clears any existing content before setting the new value, so you do not need to call clear() first.

JavaScript
const BBREClient = require("mydisctsolver-bbre");

const client = new BBREClient({ apiKey: "YOUR_API_KEY" });

async function fillInputField() {
  const session = client.createSession({ mode: "adaptive" });
  await session.start();

  await session.browser.navigate("https://example.com/search");

  await session.browser.fill("#search-input", "web scraping tools");

  await session.browser.click("#search-button");

  await session.close();
}

fillInputField();

Fill Multiple Fields

When populating a form with multiple fields, call fill() for each field sequentially. Each call clears the target field and sets the new value independently.

JavaScript
const BBREClient = require("mydisctsolver-bbre");

const client = new BBREClient({ apiKey: "YOUR_API_KEY" });

async function fillContactForm() {
  const session = client.createSession({ mode: "adaptive" });
  await session.start();

  await session.browser.navigate("https://example.com/contact");

  await session.browser.fill("#name", "Alice Johnson");
  await session.browser.fill("#email", "[email protected]");
  await session.browser.fill("#subject", "Partnership Inquiry");
  await session.browser.fill("textarea#message", "I would like to discuss a potential partnership opportunity.");

  await session.browser.click("button[type='submit']");

  await session.close();
}

fillContactForm();

session.browser.type(selector, value, options)

The type() method enters text into an input field character by character, simulating realistic keyboard input. Unlike fill() which sets the value instantly, type() dispatches individual key events for each character in the value string, with a configurable delay between keystrokes. This character-level input is essential for websites that rely on keydown, keypress, or keyup events to trigger real-time validation, autocomplete suggestions, search-as-you-type functionality, or input masking behavior. The default delay between keystrokes is 0.05 seconds (50 milliseconds), which produces a natural typing rhythm. You can increase the delay to simulate slower typing or decrease it for faster input while still maintaining the character-by-character event dispatch. The method sends a type action to the BBRE engine with the selector, text value, and delay parameter. It resolves when all characters have been typed and throws an error if the element is not found, not visible, or not editable. Use type() when the target website requires keystroke events to function correctly, or when you want the input behavior to closely resemble a real user typing on a keyboard.

Method Signature

JavaScript
const result = await session.browser.type(selector, value, options);

Parameters

The type() method accepts a CSS selector string as the first argument, the text to type as the second argument, and an optional options object as the third argument. The options object allows you to configure the delay between keystrokes.

Parameter Type Required Description
selector string Required A CSS selector that identifies the input element to type into. The engine targets the first element matching this selector.
value string Required The text to type into the input field. Each character is entered individually with key events dispatched for every keystroke.
options object Optional Configuration object for the typing behavior.
options.delay number Optional The delay in seconds between each keystroke. Defaults to 0.05 (50 milliseconds). Increase for more human-like typing speed, decrease for faster input.

Basic Type Example

The simplest usage of type() enters text into an input field with the default keystroke delay. This triggers all keyboard events for each character, making it suitable for fields with real-time validation or autocomplete.

JavaScript
const BBREClient = require("mydisctsolver-bbre");

const client = new BBREClient({ apiKey: "YOUR_API_KEY" });

async function typeInSearchBox() {
  const session = client.createSession({ mode: "adaptive" });
  await session.start();

  await session.browser.navigate("https://example.com");

  await session.browser.type("#search-box", "javascript tutorials");

  await session.browser.click("#search-submit");

  await session.close();
}

typeInSearchBox();

Type with Custom Delay

Adjusting the keystroke delay lets you control how fast or slow the typing appears. A slower delay (higher value) makes the typing look more natural, while a faster delay (lower value) speeds up the automation without losing the character-by-character event dispatch.

JavaScript
const BBREClient = require("mydisctsolver-bbre");

const client = new BBREClient({ apiKey: "YOUR_API_KEY" });

async function typeWithVariableSpeed() {
  const session = client.createSession({ mode: "adaptive" });
  await session.start();

  await session.browser.navigate("https://example.com/login");

  await session.browser.type("#username", "alice_dev", { delay: 0.08 });

  await session.browser.type("#password", "secureP4ssw0rd!", { delay: 0.12 });

  await session.browser.click("#login-btn");

  await session.close();
}

typeWithVariableSpeed();

Type for Autocomplete and Search Suggestions

Many search interfaces display suggestions as the user types. The character-by-character input of type() triggers these suggestion dropdowns, allowing you to interact with autocomplete results after typing a partial query.

JavaScript
const BBREClient = require("mydisctsolver-bbre");

const client = new BBREClient({ apiKey: "YOUR_API_KEY" });

async function useAutocomplete() {
  const session = client.createSession({ mode: "adaptive" });
  await session.start();

  await session.browser.navigate("https://example.com/search");

  await session.browser.type("#search-input", "node", { delay: 0.1 });

  await session.browser.waitForElement(".autocomplete-dropdown", { timeout: 5 });

  await session.browser.click(".autocomplete-dropdown .suggestion:first-child");

  const results = await session.browser.getText(".search-results-count");
  console.log("Search results:", results);

  await session.close();
}

useAutocomplete();

session.browser.select(selector, value)

The select() method selects an option from a <select> dropdown element by matching the value attribute of the target option. It sends a select action to the BBRE engine with the CSS selector identifying the dropdown element and the value of the option to select. This method works with standard HTML select elements and handles both single-select and the selection of a specific option within multi-select dropdowns. The method resolves when the option has been selected successfully and throws an error if the select element is not found, the specified value does not match any option, or the element is not interactable. Use select() whenever you need to choose an option from a native HTML dropdown in your automation workflow, such as selecting a country, choosing a shipping method, picking a date range, or setting a filter value.

Method Signature

JavaScript
const result = await session.browser.select(selector, value);

Parameters

The select() method accepts a CSS selector string identifying the <select> element and the value of the option to select. Both parameters are required.

Parameter Type Required Description
selector string Required A CSS selector that identifies the <select> dropdown element. The engine targets the first select element matching this selector.
value string Required The value attribute of the <option> element to select. This must match the value attribute exactly, not the visible text of the option.

Basic Select Example

The simplest usage of select() targets a dropdown and selects an option by its value attribute. Remember that the value parameter corresponds to the value attribute of the <option> tag, not the displayed text.

JavaScript
const BBREClient = require("mydisctsolver-bbre");

const client = new BBREClient({ apiKey: "YOUR_API_KEY" });

async function selectCountry() {
  const session = client.createSession({ mode: "adaptive" });
  await session.start();

  await session.browser.navigate("https://example.com/register");

  await session.browser.select("#country", "US");

  await session.browser.select("#language", "en");

  await session.close();
}

selectCountry();

Select in a Filter Form

Dropdown selections are commonly used in filter forms on e-commerce sites, job boards, and data dashboards. Combine select() with other interaction methods to configure complex filter combinations.

JavaScript
const BBREClient = require("mydisctsolver-bbre");

const client = new BBREClient({ apiKey: "YOUR_API_KEY" });

async function applyProductFilters() {
  const session = client.createSession({ mode: "adaptive" });
  await session.start();

  await session.browser.navigate("https://example.com/products");

  await session.browser.select("#category", "electronics");
  await session.browser.select("#sort-by", "price-low-high");
  await session.browser.select("#items-per-page", "50");

  await session.browser.click("#apply-filters");

  const count = await session.browser.getText(".results-count");
  console.log("Filtered results:", count);

  await session.close();
}

applyProductFilters();

session.browser.checkbox(text)

The checkbox() method clicks a checkbox element by matching its associated label text. Instead of using a CSS selector to target the checkbox directly, this method finds the checkbox by the visible text of its label, which is often more intuitive and resilient to DOM structure changes. The method accepts either a plain string for partial text matching or an object with text and exact properties for more precise control. When you pass a string, the engine searches for a checkbox whose label contains that text (partial match). When you pass an object with exact: true, the engine requires the label text to match exactly. The method sends a clickCheckboxByText action to the BBRE engine. It resolves when the checkbox has been clicked and throws an error if no checkbox with the matching label text is found. Use checkbox() for toggling terms of service agreements, newsletter subscriptions, preference settings, filter checkboxes, and any other checkbox interaction where the label text is a reliable identifier.

Method Signature

JavaScript
const result = await session.browser.checkbox(text);
const result = await session.browser.checkbox({ text, exact });

Parameters

The checkbox() method accepts either a string or an object as its single argument. When a string is passed, it performs a partial text match against checkbox labels. When an object is passed, you can control whether the match is exact or partial.

Parameter Type Required Description
text string Required When passed as a string directly, the engine searches for a checkbox whose label contains this text (partial match). Case sensitivity depends on the page content.
text (object form) object Required An object with text and optional exact properties for precise checkbox targeting.
text.text string Required The label text to search for when using the object form.
text.exact boolean Optional When true, the label text must match exactly. When false or omitted, partial matching is used. Defaults to false.

Basic Checkbox Example

The simplest usage of checkbox() passes a string to find and click a checkbox by its label text. This performs a partial match, so you do not need to provide the full label text.

JavaScript
const BBREClient = require("mydisctsolver-bbre");

const client = new BBREClient({ apiKey: "YOUR_API_KEY" });

async function acceptTerms() {
  const session = client.createSession({ mode: "adaptive" });
  await session.start();

  await session.browser.navigate("https://example.com/register");

  await session.browser.checkbox("I agree to the Terms");

  await session.browser.checkbox("Subscribe to newsletter");

  await session.browser.click("#register-btn");

  await session.close();
}

acceptTerms();

Exact Match Checkbox

When a page has multiple checkboxes with similar label text, use the object form with exact: true to target a specific checkbox. This prevents accidentally clicking the wrong checkbox when labels share common words.

JavaScript
const BBREClient = require("mydisctsolver-bbre");

const client = new BBREClient({ apiKey: "YOUR_API_KEY" });

async function selectExactCheckbox() {
  const session = client.createSession({ mode: "adaptive" });
  await session.start();

  await session.browser.navigate("https://example.com/preferences");

  await session.browser.checkbox({ text: "Email notifications", exact: true });

  await session.browser.checkbox({ text: "SMS notifications", exact: true });

  await session.browser.click("#save-preferences");

  await session.close();
}

selectExactCheckbox();

Multiple Checkbox Selection

Filter interfaces and preference pages often present multiple checkboxes that need to be selected together. Call checkbox() multiple times to select each option.

JavaScript
const BBREClient = require("mydisctsolver-bbre");

const client = new BBREClient({ apiKey: "YOUR_API_KEY" });

async function selectMultipleFilters() {
  const session = client.createSession({ mode: "adaptive" });
  await session.start();

  await session.browser.navigate("https://example.com/jobs");

  await session.browser.checkbox("Remote");
  await session.browser.checkbox("Full-time");
  await session.browser.checkbox("Senior level");

  await session.browser.click("#apply-filters");

  const count = await session.browser.getText(".job-count");
  console.log("Matching jobs:", count);

  await session.close();
}

selectMultipleFilters();

session.browser.fillForm(fields, options)

The fillForm() method fills multiple form fields in a single call by accepting an object where each key is a CSS selector and each value is the text to enter into that field. This is the most efficient way to populate complex forms because it sends all field data to the BBRE engine as a single fillForm action, reducing the number of round trips compared to calling fill() individually for each field. The method also accepts an optional submit parameter that, when set to true, automatically submits the form after all fields have been filled. The fields parameter is passed as formData to the engine, and the engine processes each field sequentially, clearing existing content and setting the new value for each selector-value pair. The method resolves when all fields have been filled (and the form submitted, if requested) and throws an error if any of the specified selectors cannot be found or the elements are not editable. Use fillForm() for login forms, registration forms, checkout forms, profile update forms, and any scenario where you need to populate multiple input fields as part of a single logical operation.

Method Signature

JavaScript
const result = await session.browser.fillForm(fields, options);

Parameters

The fillForm() method accepts a fields object as the first argument and an optional options object as the second argument. The fields object maps CSS selectors to the values that should be entered into each corresponding input element.

Parameter Type Required Description
fields object Required An object where each key is a CSS selector identifying a form field and each value is the text to enter into that field. The engine processes each key-value pair sequentially, clearing the field and setting the new value.
options object Optional Configuration object for the form fill operation.
options.submit boolean Optional When true, the form is automatically submitted after all fields have been filled. Defaults to false. The engine submits the form by triggering the form's submit event.

Basic fillForm Example

The simplest usage of fillForm() passes an object mapping selectors to values. All fields are filled in a single operation, which is faster and cleaner than calling fill() for each field individually.

JavaScript
const BBREClient = require("mydisctsolver-bbre");

const client = new BBREClient({ apiKey: "YOUR_API_KEY" });

async function fillLoginForm() {
  const session = client.createSession({ mode: "adaptive" });
  await session.start();

  await session.browser.navigate("https://example.com/login");

  await session.browser.fillForm({
    "#username": "alice_dev",
    "#password": "secureP4ssw0rd!"
  });

  await session.browser.click("#login-btn");

  await session.close();
}

fillLoginForm();

fillForm with Auto Submit

When you set submit: true in the options, the form is automatically submitted after all fields are filled. This eliminates the need for a separate click() call on the submit button.

JavaScript
const BBREClient = require("mydisctsolver-bbre");

const client = new BBREClient({ apiKey: "YOUR_API_KEY" });

async function fillAndSubmitForm() {
  const session = client.createSession({ mode: "adaptive" });
  await session.start();

  await session.browser.navigate("https://example.com/login");

  await session.browser.fillForm({
    "#username": "alice_dev",
    "#password": "secureP4ssw0rd!"
  }, { submit: true });

  const pageTitle = await session.browser.getTitle();
  console.log("After login:", pageTitle);

  await session.close();
}

fillAndSubmitForm();

Complex Registration Form

The fillForm() method handles complex forms with many fields efficiently. Pass all field selectors and values in a single object to populate the entire form at once.

JavaScript
const BBREClient = require("mydisctsolver-bbre");

const client = new BBREClient({ apiKey: "YOUR_API_KEY" });

async function fillRegistrationForm() {
  const session = client.createSession({ mode: "adaptive" });
  await session.start();

  await session.browser.navigate("https://example.com/register");

  await session.browser.fillForm({
    "#first-name": "Alice",
    "#last-name": "Johnson",
    "#email": "[email protected]",
    "#phone": "+1-555-0123",
    "#company": "TechCorp Inc.",
    "#job-title": "Senior Developer",
    "#password": "secureP4ssw0rd!",
    "#confirm-password": "secureP4ssw0rd!"
  });

  await session.browser.select("#country", "US");
  await session.browser.select("#timezone", "America/New_York");

  await session.browser.checkbox("I agree to the Terms of Service");
  await session.browser.checkbox("Subscribe to product updates");

  await session.browser.click("#create-account");

  await session.close();
}

fillRegistrationForm();

session.browser.clear(selector)

The clear() method removes all content from an input field identified by a CSS selector, resetting it to an empty state. It sends a clear action to the BBRE engine with the target selector. This method is useful when you need to reset a field that already contains a value before entering new content, or when you want to test how a form behaves with empty fields. While the fill() method automatically clears the field before setting a new value, the clear() method is specifically designed for scenarios where you only want to empty the field without entering new content. The method resolves when the field has been cleared and throws an error if the element is not found, not visible, or not editable. Use clear() for resetting search inputs, clearing pre-populated form fields, testing form validation on empty fields, and preparing fields for fresh input when fill() is not appropriate.

Method Signature

JavaScript
const result = await session.browser.clear(selector);

Parameters

The clear() method accepts a single CSS selector string that identifies the input element to clear.

Parameter Type Required Description
selector string Required A CSS selector that identifies the input element to clear. The engine targets the first element matching this selector and removes all its content.

Basic Clear Example

The simplest usage of clear() empties an input field. This is useful for resetting search boxes, clearing pre-filled values, or preparing a field for new input.

JavaScript
const BBREClient = require("mydisctsolver-bbre");

const client = new BBREClient({ apiKey: "YOUR_API_KEY" });

async function clearAndRefillSearch() {
  const session = client.createSession({ mode: "adaptive" });
  await session.start();

  await session.browser.navigate("https://example.com/search");

  await session.browser.fill("#search-input", "initial query");
  await session.browser.click("#search-btn");

  await session.browser.clear("#search-input");
  await session.browser.fill("#search-input", "refined query");
  await session.browser.click("#search-btn");

  await session.close();
}

clearAndRefillSearch();

Clear Pre-populated Fields

Some forms come with pre-populated values from user profiles or previous submissions. Use clear() to remove these values before entering fresh data, especially when you want to ensure the field is completely empty before using type() which does not automatically clear existing content.

JavaScript
const BBREClient = require("mydisctsolver-bbre");

const client = new BBREClient({ apiKey: "YOUR_API_KEY" });

async function updateProfileFields() {
  const session = client.createSession({ mode: "adaptive" });
  await session.start();

  await session.browser.navigate("https://example.com/profile/edit");

  await session.browser.clear("#display-name");
  await session.browser.type("#display-name", "Alice Johnson", { delay: 0.06 });

  await session.browser.clear("#bio");
  await session.browser.type("#bio", "Full-stack developer with 8 years of experience.", { delay: 0.04 });

  await session.browser.click("#save-profile");

  await session.close();
}

updateProfileFields();

fill() vs type() Comparison

Choosing between fill() and type() is one of the most important decisions when building form automation workflows. Both methods set the value of an input field, but they do so in fundamentally different ways that affect speed, event dispatch, and compatibility with different types of web applications. Understanding when to use each method will help you build more reliable and efficient automation scripts.

Behavior Comparison

The following table summarizes the key differences between fill() and type() across several important dimensions.

Characteristic fill() type()
Input method Sets the value instantly in a single operation Types each character individually with key events
Speed Very fast, regardless of text length Slower, proportional to text length and delay setting
Clears existing content Yes, automatically clears before setting value No, appends to existing content unless cleared first
Keystroke events Does not dispatch individual keydown/keyup events Dispatches keydown, keypress, and keyup for each character
Autocomplete triggers May not trigger autocomplete or search suggestions Triggers autocomplete and search-as-you-type features
Input validation May bypass real-time character validation Triggers real-time validation on each keystroke
Human-like behavior Less human-like, value appears instantly More human-like, simulates actual keyboard typing
Default delay No delay (instant) 0.05 seconds between keystrokes
Best for Simple forms, fast data entry, fields without event listeners Search boxes, autocomplete fields, forms with real-time validation

When to Use fill()

Use fill() as your default choice for most form fields. It is faster, simpler, and automatically handles clearing existing content. The following scenarios are ideal for fill():

JavaScript
const BBREClient = require("mydisctsolver-bbre");

const client = new BBREClient({ apiKey: "YOUR_API_KEY" });

async function fillExamples() {
  const session = client.createSession({ mode: "adaptive" });
  await session.start();

  await session.browser.navigate("https://example.com/register");

  await session.browser.fill("#first-name", "Alice");
  await session.browser.fill("#last-name", "Johnson");
  await session.browser.fill("#email", "[email protected]");
  await session.browser.fill("#password", "secureP4ssw0rd!");

  await session.browser.fill("#address-line1", "123 Main Street");
  await session.browser.fill("#city", "San Francisco");
  await session.browser.fill("#zip-code", "94102");

  await session.close();
}

fillExamples();

When to Use type()

Use type() when the target field relies on keystroke events to function correctly. The following scenarios require type() for proper behavior:

JavaScript
const BBREClient = require("mydisctsolver-bbre");

const client = new BBREClient({ apiKey: "YOUR_API_KEY" });

async function typeExamples() {
  const session = client.createSession({ mode: "adaptive" });
  await session.start();

  await session.browser.navigate("https://example.com");

  await session.browser.type("#search-box", "web scraping", { delay: 0.08 });
  await session.browser.waitForElement(".suggestions-dropdown", { timeout: 3 });

  await session.browser.navigate("https://example.com/address-form");
  await session.browser.type("#street-address", "123 Main", { delay: 0.06 });
  await session.browser.waitForElement(".address-suggestions", { timeout: 3 });

  await session.browser.navigate("https://example.com/chat");
  await session.browser.type("#message-input", "Hello, I need help with my order.", { delay: 0.1 });

  await session.close();
}

typeExamples();

Combining fill() and type() in the Same Form

In practice, many forms contain a mix of fields where some benefit from fill() and others require type(). Use fill() for straightforward fields and type() for fields that need keystroke events.

JavaScript
const BBREClient = require("mydisctsolver-bbre");

const client = new BBREClient({ apiKey: "YOUR_API_KEY" });

async function mixedFormFilling() {
  const session = client.createSession({ mode: "adaptive" });
  await session.start();

  await session.browser.navigate("https://example.com/booking");

  await session.browser.fill("#guest-name", "Alice Johnson");
  await session.browser.fill("#email", "[email protected]");
  await session.browser.fill("#phone", "+1-555-0123");

  await session.browser.type("#destination", "San Fran", { delay: 0.08 });
  await session.browser.waitForElement(".location-suggestions", { timeout: 3 });
  await session.browser.click(".location-suggestions li:first-child");

  await session.browser.fill("#check-in", "2025-03-15");
  await session.browser.fill("#check-out", "2025-03-20");
  await session.browser.select("#room-type", "deluxe");
  await session.browser.select("#guests", "2");

  await session.browser.click("#search-availability");

  await session.close();
}

mixedFormFilling();

Form Interaction Patterns

Real-world form automation involves combining multiple interaction methods into cohesive workflows. This section demonstrates complete, production-ready patterns for the most common form interaction scenarios you will encounter when building automation with the BBRE BrowserAPI. Each pattern shows how to combine fill(), type(), select(), checkbox(), fillForm(), click(), and clear() to handle different types of forms effectively.

Login Form Pattern

Login forms are the most common form interaction in web automation. They typically consist of a username or email field, a password field, an optional "remember me" checkbox, and a submit button. The following pattern demonstrates a complete login flow with error detection.

JavaScript
const BBREClient = require("mydisctsolver-bbre");

const client = new BBREClient({ apiKey: "YOUR_API_KEY" });

async function loginWorkflow(email, password) {
  const session = client.createSession({ mode: "adaptive" });
  await session.start();

  await session.browser.navigate("https://example.com/login");

  await session.browser.fillForm({
    "#email": email,
    "#password": password
  });

  await session.browser.checkbox("Remember me");

  await session.browser.click("#login-btn", { delay: 0.3 });

  const currentUrl = await session.browser.getUrl();

  if (currentUrl.includes("/dashboard")) {
    console.log("Login successful");
    const welcomeText = await session.browser.getText(".welcome-message");
    console.log(welcomeText);
  } else {
    const errorText = await session.browser.getText(".error-message");
    console.log("Login failed:", errorText);
  }

  await session.close();
}

loginWorkflow("[email protected]", "secureP4ssw0rd!");

Registration Form Pattern

Registration forms are more complex than login forms, often including multiple text fields, dropdown selections, checkbox agreements, and sometimes multi-step wizards. The following pattern demonstrates a complete registration flow that combines all interaction methods.

JavaScript
const BBREClient = require("mydisctsolver-bbre");

const client = new BBREClient({ apiKey: "YOUR_API_KEY" });

async function registrationWorkflow(userData) {
  const session = client.createSession({ mode: "adaptive" });
  await session.start();

  await session.browser.navigate("https://example.com/register");

  await session.browser.fillForm({
    "#first-name": userData.firstName,
    "#last-name": userData.lastName,
    "#email": userData.email,
    "#password": userData.password,
    "#confirm-password": userData.password
  });

  await session.browser.select("#country", userData.country);
  await session.browser.select("#language", userData.language);

  await session.browser.checkbox("I agree to the Terms of Service");

  if (userData.newsletter) {
    await session.browser.checkbox("Subscribe to newsletter");
  }

  await session.browser.click("#create-account", { delay: 0.5 });

  const pageTitle = await session.browser.getTitle();
  console.log("After registration:", pageTitle);

  await session.close();
}

registrationWorkflow({
  firstName: "Alice",
  lastName: "Johnson",
  email: "[email protected]",
  password: "secureP4ssw0rd!",
  country: "US",
  language: "en",
  newsletter: true
});

Search with Filters Pattern

Search interfaces often combine a text input with dropdown filters, checkboxes, and sorting options. The following pattern demonstrates how to perform a filtered search using multiple interaction methods together.

JavaScript
const BBREClient = require("mydisctsolver-bbre");

const client = new BBREClient({ apiKey: "YOUR_API_KEY" });

async function filteredSearch(query, filters) {
  const session = client.createSession({ mode: "adaptive" });
  await session.start();

  await session.browser.navigate("https://example.com/jobs");

  await session.browser.type("#search-input", query, { delay: 0.06 });

  if (filters.category) {
    await session.browser.select("#category", filters.category);
  }

  if (filters.location) {
    await session.browser.select("#location", filters.location);
  }

  if (filters.sortBy) {
    await session.browser.select("#sort-by", filters.sortBy);
  }

  if (filters.remote) {
    await session.browser.checkbox("Remote only");
  }

  if (filters.fullTime) {
    await session.browser.checkbox("Full-time");
  }

  await session.browser.click("#search-btn");

  const resultsCount = await session.browser.getText(".results-count");
  console.log("Found:", resultsCount);

  await session.close();
}

filteredSearch("software engineer", {
  category: "engineering",
  location: "san-francisco",
  sortBy: "date-posted",
  remote: true,
  fullTime: true
});

Multi-step Form Pattern

Multi-step forms (wizards) split the form into several pages or sections, requiring the user to complete each step before proceeding to the next. The following pattern demonstrates how to navigate through a multi-step checkout form.

JavaScript
const BBREClient = require("mydisctsolver-bbre");

const client = new BBREClient({ apiKey: "YOUR_API_KEY" });

async function multiStepCheckout(orderData) {
  const session = client.createSession({ mode: "adaptive" });
  await session.start();

  await session.browser.navigate("https://example.com/checkout");

  await session.browser.fillForm({
    "#full-name": orderData.name,
    "#address": orderData.address,
    "#city": orderData.city,
    "#zip": orderData.zip
  });
  await session.browser.select("#country", orderData.country);
  await session.browser.click("#next-step");

  await session.browser.waitForElement("#shipping-options", { timeout: 5 });
  await session.browser.click("[data-shipping='" + orderData.shipping + "']");
  await session.browser.click("#next-step");

  await session.browser.waitForElement("#payment-form", { timeout: 5 });
  await session.browser.fillForm({
    "#card-number": orderData.cardNumber,
    "#card-name": orderData.cardName,
    "#expiry": orderData.expiry,
    "#cvv": orderData.cvv
  });
  await session.browser.click("#next-step");

  await session.browser.waitForElement("#order-summary", { timeout: 5 });
  const total = await session.browser.getText(".order-total");
  console.log("Order total:", total);

  await session.browser.checkbox("I agree to the purchase terms");
  await session.browser.click("#place-order", { delay: 0.5 });

  await session.close();
}

multiStepCheckout({
  name: "Alice Johnson",
  address: "123 Main Street",
  city: "San Francisco",
  zip: "94102",
  country: "US",
  shipping: "express",
  cardNumber: "4111111111111111",
  cardName: "Alice Johnson",
  expiry: "12/26",
  cvv: "123"
});

Dynamic Form with Conditional Fields

Some forms show or hide fields based on previous selections. The following pattern demonstrates how to handle a form where selecting a specific option reveals additional fields that need to be filled.

JavaScript
const BBREClient = require("mydisctsolver-bbre");

const client = new BBREClient({ apiKey: "YOUR_API_KEY" });

async function dynamicFormWorkflow() {
  const session = client.createSession({ mode: "adaptive" });
  await session.start();

  await session.browser.navigate("https://example.com/support/ticket");

  await session.browser.fill("#subject", "Billing inquiry");
  await session.browser.select("#category", "billing");

  await session.browser.waitForElement("#billing-fields", { timeout: 3 });

  await session.browser.fill("#order-number", "ORD-2025-78432");
  await session.browser.fill("#transaction-id", "TXN-9A8B7C6D");
  await session.browser.select("#billing-issue-type", "refund");

  await session.browser.fill("textarea#description", "I would like to request a refund for my recent order. The product arrived damaged and does not match the description on the website.");

  await session.browser.click("#submit-ticket", { delay: 0.3 });

  const ticketId = await session.browser.getText(".ticket-confirmation .ticket-id");
  console.log("Ticket created:", ticketId);

  await session.close();
}

dynamicFormWorkflow();

Error Handling

All interaction methods can throw errors when the target element is not found, not visible, not interactable, or when the session is not in adaptive mode. Wrapping your interaction calls in try-catch blocks allows you to handle these failures gracefully and implement retry logic or fallback strategies when elements are temporarily unavailable.

Error Types

The following table lists the common errors that can be thrown by the interaction methods, along with their causes and recommended solutions.

Error Message Cause Solution
BROWSER_ACTION_FAILED The browser action could not be completed. The element may not exist, may not be visible, or may not be interactable. Verify the CSS selector is correct. Use waitForElement() before interacting to ensure the element is present and visible. Check if the element is hidden behind an overlay or modal.
Session is not in adaptive mode The session was created with mode: "passive" which does not support browser interactions. Create the session with mode: "adaptive" to enable browser interaction methods.
Session expired The session has exceeded its maximum lifetime and is no longer active. Create a new session and restart the workflow. Consider implementing session health checks before long operations.
Element not found No element matches the provided CSS selector on the current page. Double-check the selector against the page source. The page may not have finished loading, or the element may be dynamically rendered. Use waitForElement() to wait for the element to appear.

Robust Form Filling with Error Handling

The following example demonstrates a production-ready pattern that wraps each interaction in error handling and implements a retry mechanism for transient failures.

JavaScript
const BBREClient = require("mydisctsolver-bbre");

const client = new BBREClient({ apiKey: "YOUR_API_KEY" });

async function safeFill(session, selector, value, retries) {
  for (let attempt = 1; attempt <= retries; attempt++) {
    try {
      await session.browser.waitForElement(selector, { timeout: 5 });
      await session.browser.fill(selector, value);
      return true;
    } catch (error) {
      console.log("Attempt", attempt, "failed for", selector, ":", error.message);
      if (attempt < retries) {
        await new Promise(resolve => setTimeout(resolve, 1000));
      }
    }
  }
  return false;
}

async function safeClick(session, selector, retries) {
  for (let attempt = 1; attempt <= retries; attempt++) {
    try {
      await session.browser.waitForElement(selector, { timeout: 5 });
      await session.browser.click(selector);
      return true;
    } catch (error) {
      console.log("Attempt", attempt, "failed for", selector, ":", error.message);
      if (attempt < retries) {
        await new Promise(resolve => setTimeout(resolve, 1000));
      }
    }
  }
  return false;
}

async function robustLoginWorkflow(email, password) {
  const session = client.createSession({ mode: "adaptive" });
  await session.start();

  try {
    await session.browser.navigate("https://example.com/login");

    const emailFilled = await safeFill(session, "#email", email, 3);
    const passwordFilled = await safeFill(session, "#password", password, 3);

    if (!emailFilled || !passwordFilled) {
      console.log("Failed to fill login form");
      await session.close();
      return false;
    }

    const clicked = await safeClick(session, "#login-btn", 3);

    if (!clicked) {
      console.log("Failed to click login button");
      await session.close();
      return false;
    }

    console.log("Login form submitted successfully");
    await session.close();
    return true;
  } catch (error) {
    console.log("Unexpected error:", error.message);
    await session.close();
    return false;
  }
}

robustLoginWorkflow("[email protected]", "secureP4ssw0rd!");

Best Practices

Use fill() by Default, Switch to type() Only When Needed

Start with fill() for all form fields because it is faster and automatically clears existing content. Only switch to type() when you encounter fields that require keystroke events to function correctly, such as search boxes with autocomplete, address fields with location suggestions, or inputs with real-time character validation. This approach gives you the best balance between speed and compatibility. If a field does not work with fill(), try type() before investigating other causes.

Always Wait for Elements Before Interacting

Before calling any interaction method, use session.browser.waitForElement(selector) to ensure the target element is present and visible on the page. Modern web applications load content dynamically, and elements may not be available immediately after navigation. Waiting for elements prevents BROWSER_ACTION_FAILED errors caused by attempting to interact with elements that have not yet been rendered. This is especially important after page navigation, after clicking buttons that trigger content loading, and in single-page applications where DOM updates happen asynchronously.

Use fillForm() for Multi-field Forms Instead of Multiple fill() Calls

When you need to fill three or more fields in the same form, use fillForm() instead of calling fill() for each field individually. The fillForm() method sends all field data to the BBRE engine in a single action, which reduces the number of API round trips and makes your code cleaner and easier to maintain. Reserve individual fill() calls for cases where you need to mix fill() with other methods like type(), select(), or checkbox() between fields.

Use Specific CSS Selectors for Reliable Element Targeting

Prefer ID selectors (#email) and data attribute selectors ([data-testid="email-input"]) over class selectors or complex structural selectors. ID selectors are unique within a page and are less likely to break when the page layout changes. Data attribute selectors are often added specifically for testing and automation purposes, making them stable targets. Avoid selectors that depend on element position (like :nth-child) or deeply nested DOM structure, as these are fragile and break easily when the page is updated.

Add Realistic Delays for Sensitive Websites

When automating interactions on websites that monitor user behavior patterns, increase the delay parameter on click() and type() to simulate more natural human timing. A real user does not fill a form instantly or click buttons without any pause. Setting click delays between 0.3 and 1.0 seconds and typing delays between 0.06 and 0.15 seconds creates a more believable interaction pattern. Combine this with the BBRE sensibility setting for comprehensive anti-detection behavior.

Verify Form Submission Results

After submitting a form, always verify that the submission was successful by checking the resulting page state. Use getUrl() to check if the page redirected to a success page, getText() to look for success or error messages, or getTitle() to verify the page title changed as expected. Do not assume that a successful click() on the submit button means the form was accepted. Server-side validation may reject the submission, and the page may display error messages that your automation needs to detect and handle.

Use checkbox() with Exact Matching When Labels Are Similar

When a page has multiple checkboxes with similar label text, always use the object form of checkbox() with exact: true to prevent clicking the wrong checkbox. For example, if a page has both "Email notifications" and "Email notifications for promotions" checkboxes, a partial match on "Email notifications" could match either one. Using checkbox({ text: "Email notifications", exact: true }) ensures you target the exact checkbox you intend to click.

Common Issues

fill() Does Not Trigger Autocomplete or Search Suggestions

Symptom: You use fill() to enter text into a search box, but the autocomplete dropdown or search suggestions do not appear.
Cause: The fill() method sets the input value directly without dispatching individual keystroke events. Many autocomplete and search-as-you-type implementations listen for keydown, keypress, or input events on each character to trigger suggestion lookups. Since fill() bypasses these per-character events, the suggestion logic never fires.
Solution: Switch to type() for fields that rely on keystroke events. Use await session.browser.type("#search", "query", { delay: 0.08 }) to type character by character, which dispatches the keyboard events that trigger autocomplete behavior.

type() Appends to Existing Content Instead of Replacing It

Symptom: You call type() on a field that already contains text, and the new text is appended after the existing content instead of replacing it.
Cause: Unlike fill(), the type() method does not automatically clear the field before entering new text. It types each character at the current cursor position, which is typically at the end of the existing content.
Solution: Call clear() before type() to remove existing content first: await session.browser.clear("#field"); await session.browser.type("#field", "new value"); Alternatively, use fill() if you do not need character-by-character input, since it clears the field automatically.

select() Fails Because Value Does Not Match Option Attribute

Symptom: Calling select() throws an error or selects the wrong option, even though you can see the desired option in the dropdown.
Cause: The value parameter in select() must match the value attribute of the <option> element, not the visible display text. For example, a dropdown showing "United States" might have <option value="US">United States</option>, so you need to pass "US" not "United States".
Solution: Inspect the HTML source of the select element to find the exact value attribute for each option. Use session.browser.getHtml("#country") to retrieve the select element's HTML and identify the correct option values.

checkbox() Cannot Find the Checkbox by Label Text

Symptom: Calling checkbox("Terms") throws an error saying no checkbox was found, even though you can see a "Terms and Conditions" checkbox on the page.
Cause: The checkbox() method searches for checkboxes by their associated label text. If the checkbox does not have a proper <label> element, or if the label text does not contain the search string, the method cannot find it. Some websites use custom checkbox implementations with <div> or <span> elements instead of native <input type="checkbox"> elements.
Solution: Try using the full label text or a more specific partial match. If the checkbox uses a custom implementation, use click() with a CSS selector instead: await session.browser.click(".custom-checkbox[data-field='terms']").

Interaction Methods Fail on Passive Mode Sessions

Symptom: Any interaction method (click(), fill(), type(), etc.) throws a BROWSER_ACTION_FAILED error immediately.
Cause: The session was created with mode: "passive" or without specifying a mode (which may default to passive). Passive mode sessions do not launch a browser instance, so there is no browser to interact with. All BrowserAPI methods require an active browser instance that only exists in adaptive mode.
Solution: Create the session with mode: "adaptive": const session = client.createSession({ mode: "adaptive" });. Verify the session mode before attempting browser interactions.

fillForm() Fails When One Selector Is Invalid

Symptom: Calling fillForm() with multiple fields throws an error, and none of the fields are filled, even though most selectors are correct.
Cause: The fillForm() method processes fields sequentially. If any selector in the fields object does not match an element on the page, the entire operation fails at that point. Fields processed before the failing selector may have been filled, but fields after it will not be.
Solution: Verify all selectors before calling fillForm(). Use waitForElement() for each selector to confirm the elements exist. If some fields are optional or may not be present, fill them individually with fill() wrapped in try-catch blocks instead of using fillForm().

click() Succeeds but Nothing Happens on the Page

Symptom: The click() method resolves without error, but the expected action (page navigation, form submission, modal opening) does not occur.
Cause: The CSS selector may be matching a different element than intended, such as an invisible overlay, a disabled button, or a decorative element that sits on top of the actual clickable element. The click lands on the matched element but does not trigger the intended behavior.
Solution: Make your CSS selector more specific to target the exact element. Check if the button is disabled by inspecting its attributes. Try adding a small delay before clicking to allow any animations or transitions to complete. Use session.browser.getHtml(selector) to verify which element the selector is matching.