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.
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
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.
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.
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.
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
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.
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.
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
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.
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.
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.
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
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.
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.
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
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.
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.
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.
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
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.
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.
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.
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
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.
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.
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():
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:
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.
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.
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.
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.
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.
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.
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.
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
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.
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.
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.
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.
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.
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.
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
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.
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.
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.
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']").
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.
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().
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.