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

BBREClient.request()

The request() method is the core function of the BBREClient class and the foundation for all HTTP communication through the BBRE (Browser-Backed Request Engine) service. Every other HTTP convenience method on the client, including get(), post(), put(), delete(), patch(), head(), and options(), is a thin wrapper around request(). When you call request(), you pass a single options object that describes the target URL, HTTP method, headers, body content, proxy settings, fingerprint overrides, cookie handling, timeout behavior, and whether the request should execute synchronously or asynchronously. The method processes these options, sends the request to the BBRE API, waits for the result (either by polling or by synchronous execution), and returns a standardized response object containing the HTTP status code, response headers, body content, parsed data, cookies, processing profile information, and timing data. This page provides a complete reference for every request option, the response object structure, body handling strategies, cookie formats, fingerprint merging behavior, synchronous versus asynchronous execution flows, and practical code examples covering common and advanced usage patterns.

About BBREClient.request()

The request() method is asynchronous by default. It returns a Promise that resolves to a response object when the request completes. In the default async flow, the SDK sends a POST /request/create call to create a task, then polls POST /request/result at the configured polling interval until the task finishes. When you set sync: true in the options, the SDK instead sends a single POST /request/execute call that blocks until the result is ready. The url parameter is the only required option. All other options have sensible defaults inherited from the client constructor configuration or from built-in fallback values.

Method Signature

The request() method accepts a single options object as its argument. This object contains all the parameters that control the HTTP request, including the target URL, HTTP method, headers, body, proxy, fingerprint, cookies, and execution mode. The method returns a Promise that resolves to a standardized response object. If the request fails due to a network error, timeout, or API error, the Promise rejects with an error object containing details about the failure.

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

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

const response = await client.request(options);

The options parameter is a plain JavaScript object. The only required property is url, which specifies the target URL for the request. All other properties are optional and fall back to either the client constructor defaults or built-in default values. The following sections describe every available option in detail.

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

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

const response = await client.request({
  url: "https://api.example.com/data",
  method: "GET",
  headers: { "Accept": "application/json" },
  params: { page: 1, limit: 50 },
  mode: "passive",
  sensibility: "medium",
  timeout: 120,
  cookies: {},
  fingerprint: {},
  sync: false,
  allowRedirects: true,
  maxRedirects: 10,
  verify: true
});

RequestOptions Parameters

The options object supports a comprehensive set of parameters that give you full control over every aspect of the HTTP request. Parameters are grouped into categories: target and method, body and data, network and proxy, browser identity, execution control, and security. The following table lists every parameter with its type, requirement status, default value, and description. Detailed explanations for key parameters follow in dedicated sections below.

Parameter Type Required Default Description
url string required - The target URL for the HTTP request. Must be a fully qualified URL including the protocol (http or https).
method string optional "GET" The HTTP method to use. Accepts standard methods: GET, POST, PUT, DELETE, PATCH, HEAD, OPTIONS.
headers object optional {} Custom HTTP headers to include in the request. Merged with BBRE engine default headers. Your custom headers take precedence over defaults.
body any optional - The raw request body. Sent as-is without automatic serialization. Use for pre-formatted body content or binary data.
data any optional - Alias for body. If both body and data are provided, body takes precedence.
json any optional - JSON request body. Automatically serialized with JSON.stringify() and sets Content-Type: application/json header.
files any optional - File upload data for multipart form submissions. Accepts file objects or file path references.
params object optional - Query parameters appended to the URL. Object keys become parameter names and values become parameter values. Automatically URL-encoded.
mode string optional from constructor Override the client default mode for this request. Accepts "passive" or "adaptive".
sensibility string optional from constructor Override the client default sensibility for this request. Accepts "low", "medium", or "high".
fingerprint object optional {} Request-level fingerprint attributes. Merged with the client default fingerprint. Request-level values override constructor defaults for matching keys.
proxy object optional from constructor Override the client default proxy for this request. Requires host and port. Optionally includes username and password.
cookies object/string/array optional {} Request cookies. Accepts an object of key-value pairs, a raw cookie header string, or an array of cookie objects.
timeout number optional from constructor Override the client default timeout (in seconds) for this request. Controls the maximum wait time for the entire request lifecycle.
sync boolean optional false When true, uses synchronous execution via POST /request/execute. When false (default), uses async task creation and polling.
allowRedirects boolean optional true Whether to follow HTTP redirects (301, 302, 303, 307, 308). When false, the response contains the redirect status code and Location header.
maxRedirects number optional 10 Maximum number of redirects to follow before stopping. Prevents infinite redirect loops. Only applies when allowRedirects is true.
verify boolean optional true Whether to verify SSL/TLS certificates. Set to false to allow requests to servers with self-signed or expired certificates.
auth object optional - HTTP Basic or Digest authentication credentials. Object with username and password string properties.
cert object optional - Client certificate for mutual TLS authentication. Object with certificate and key data.
sessionId string optional - Session ID for session-bound requests. When provided, the request executes within the specified session context, sharing cookies and browser state.

Async vs Sync Execution

The request() method supports two execution modes that determine how the BBRE API processes your request and returns the result. The default asynchronous mode creates a task and polls for the result, while the synchronous mode sends a single blocking request that waits for the result before responding. Both modes return the same response object format, so your response handling code works identically regardless of which execution mode you choose.

Asynchronous Execution (Default)

When sync is false (the default), the SDK follows a two-step process. First, it sends a POST /request/create call to the BBRE API with your request options. The API responds immediately with a taskId. The SDK then enters a polling loop, calling POST /request/result with the taskId at the interval specified by the client pollingInterval configuration. Each poll returns the current task status. When the status changes to completed, the SDK extracts the response data and returns it. If the task status becomes failed or the timeout is reached, the SDK throws an error.

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

const client = new BBREClient({
  apiKey: "YOUR_API_KEY",
  pollingInterval: 2000,
  timeout: 120
});

async function asyncRequest() {
  const response = await client.request({
    url: "https://api.example.com/data",
    method: "GET"
  });

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

asyncRequest();

The asynchronous flow is ideal for most use cases because it allows the BBRE engine to queue and process requests efficiently. The polling mechanism ensures that your application receives the result as soon as it is available without holding an open HTTP connection for the entire processing duration. This is especially important for adaptive mode requests that may take 30 seconds or more to complete.

Synchronous Execution

When sync is true, the SDK sends a single POST /request/execute call that blocks until the BBRE engine finishes processing the request. The API holds the connection open and returns the complete response when the task finishes. There is no polling involved. This mode is simpler but keeps an HTTP connection open for the entire processing duration, which may cause issues with connection timeouts on slow requests or when processing many concurrent requests.

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

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

async function syncRequest() {
  const response = await client.request({
    url: "https://api.example.com/data",
    method: "GET",
    sync: true
  });

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

syncRequest();

Choosing Between Async and Sync

The following table compares the two execution modes to help you choose the right one for your use case. In general, the default asynchronous mode is recommended for production applications, while synchronous mode is convenient for simple scripts, testing, and scenarios where you need immediate results without polling overhead.

Aspect Async (default) Sync (sync: true)
API Flow POST /request/create then poll POST /request/result Single POST /request/execute
Connection Behavior Short-lived connections for each poll request Single long-lived connection held open until completion
Timeout Handling Client-side timeout based on elapsed time across polls Server-side timeout on the single connection
Concurrency Better for high concurrency with many parallel requests Each request holds a connection, limiting practical concurrency
Simplicity Slightly more complex internal flow (transparent to the developer) Simpler single-request flow
Best For Production applications, batch processing, long-running requests Simple scripts, testing, quick one-off requests

Response Object

The request() method returns a standardized response object that provides access to every aspect of the HTTP response. The response object is created by the internal formatResponse function, which normalizes the raw API response into a consistent structure regardless of whether the request was executed synchronously or asynchronously. The response object includes the HTTP status code, response headers, the raw body as a string, a parsed version of the body (automatically parsed as JSON when the response Content-Type is application/json), cookies set by the target server, profile information from the BBRE engine, and the total processing time. Several convenience aliases are provided for common access patterns.

Property Type Description
success boolean Always true when the request completes without errors. Indicates that the BBRE engine successfully processed the request and received a response from the target server.
statusCode number The HTTP status code returned by the target server. Common values: 200 (OK), 301 (Redirect), 403 (Forbidden), 404 (Not Found), 500 (Server Error).
status number Alias for statusCode. Provided for convenience and compatibility with other HTTP client libraries.
headers object The HTTP response headers as a key-value object. Header names are lowercase. Multiple values for the same header are joined with commas.
body string The raw response body as a string. Contains the unmodified content returned by the target server.
data any The parsed response body. Automatically parsed as JSON when the response Content-Type header contains application/json. Otherwise, contains the raw body string.
text string Alias for body. Provided for compatibility with libraries that use text as the response body property name.
content string Alias for body. Provided for compatibility with libraries that use content as the response body property name.
cookies object Cookies set by the target server in the response. Parsed from Set-Cookie headers into a key-value object where keys are cookie names and values are cookie values.
profile object/null The browser profile used by the BBRE engine for this request. Contains fingerprint details like user agent, platform, and screen resolution. May be null for some request types.
processingTime number The total time in milliseconds that the BBRE engine spent processing the request. Includes network time, rendering time (for adaptive mode), and any evasion delays.
json() function A convenience method that parses the body string as JSON and returns the resulting object. Throws a SyntaxError if the body is not valid JSON.

Accessing Response Data

The response object provides multiple ways to access the response body depending on your needs. Use body (or its aliases text and content) for the raw string content. Use data for automatically parsed JSON content. Use the json() method when you want explicit JSON parsing with error handling.

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

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

async function accessResponseData() {
  const response = await client.request({
    url: "https://api.example.com/users",
    method: "GET"
  });

  console.log("Success:", response.success);
  console.log("Status Code:", response.statusCode);
  console.log("Status (alias):", response.status);

  console.log("Raw body:", response.body);
  console.log("Text (alias):", response.text);
  console.log("Content (alias):", response.content);

  console.log("Parsed data:", response.data);
  console.log("JSON parse:", response.json());

  console.log("Headers:", response.headers);
  console.log("Cookies:", response.cookies);
  console.log("Profile:", response.profile);
  console.log("Processing time:", response.processingTime, "ms");
}

accessResponseData();

Response Object Example

The following shows a typical response object structure returned by the request() method when fetching a JSON API endpoint.

JSON
{
  "success": true,
  "statusCode": 200,
  "status": 200,
  "headers": {
    "content-type": "application/json; charset=utf-8",
    "content-length": "256",
    "server": "nginx",
    "date": "Wed, 15 Jan 2025 10:30:00 GMT"
  },
  "body": "{"users":[{"id":1,"name":"Alice"},{"id":2,"name":"Bob"}]}",
  "data": {
    "users": [
      { "id": 1, "name": "Alice" },
      { "id": 2, "name": "Bob" }
    ]
  },
  "text": "{"users":[{"id":1,"name":"Alice"},{"id":2,"name":"Bob"}]}",
  "content": "{"users":[{"id":1,"name":"Alice"},{"id":2,"name":"Bob"}]}",
  "cookies": {
    "session_id": "abc123def456",
    "tracking": "xyz789"
  },
  "profile": {
    "userAgent": "Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36",
    "platform": "Win32",
    "language": "en-US"
  },
  "processingTime": 3450
}

Body Handling

The request() method provides four different ways to send a request body: body, data, json, and files. Each option handles serialization and Content-Type headers differently. Understanding when to use each option ensures that your request body is formatted correctly for the target server.

body Parameter

The body parameter sends the request body exactly as provided, without any automatic serialization or Content-Type header modification. Use this when you have pre-formatted body content, such as a raw string, URL-encoded form data, or XML content. You are responsible for setting the appropriate Content-Type header when using body.

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

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

async function sendFormData() {
  const response = await client.request({
    url: "https://api.example.com/submit",
    method: "POST",
    headers: { "Content-Type": "application/x-www-form-urlencoded" },
    body: "username=alice&password=secret123&remember=true"
  });

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

sendFormData();

data Parameter

The data parameter is an alias for body. It behaves identically and exists for compatibility with developers who are accustomed to HTTP client libraries that use data as the body property name. If both body and data are provided in the same options object, body takes precedence and data is ignored.

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

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

async function sendWithDataAlias() {
  const response = await client.request({
    url: "https://api.example.com/submit",
    method: "POST",
    headers: { "Content-Type": "text/plain" },
    data: "This is a plain text body sent using the data parameter"
  });

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

sendWithDataAlias();

json Parameter

The json parameter is the most convenient way to send JSON data. When you provide a value for json, the SDK automatically serializes it using JSON.stringify() and sets the Content-Type header to application/json. This eliminates the need to manually serialize your data and set the correct header. The json parameter accepts any value that is serializable by JSON.stringify(), including objects, arrays, strings, numbers, and booleans.

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

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

async function sendJsonData() {
  const response = await client.request({
    url: "https://api.example.com/users",
    method: "POST",
    json: {
      name: "Alice Johnson",
      email: "[email protected]",
      role: "developer",
      preferences: {
        theme: "dark",
        notifications: true
      }
    }
  });

  console.log("Status:", response.statusCode);
  console.log("Created user:", response.data);
}

sendJsonData();

files Parameter

The files parameter handles file upload data for multipart form submissions. When you provide file data, the BBRE engine constructs a multipart/form-data request body with the appropriate boundaries and Content-Type headers. This is useful for uploading images, documents, or other binary files to target servers.

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

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

async function uploadFile() {
  const response = await client.request({
    url: "https://api.example.com/upload",
    method: "POST",
    files: {
      document: {
        filename: "report.pdf",
        content: "base64-encoded-file-content",
        contentType: "application/pdf"
      }
    }
  });

  console.log("Upload status:", response.statusCode);
  console.log("Upload result:", response.data);
}

uploadFile();

Body Priority Order

When multiple body parameters are provided in the same options object, the SDK applies the following priority order to determine which one to use. Only one body source is sent with the request.

Priority Parameter Behavior
1 (highest) json Serialized with JSON.stringify(), Content-Type set to application/json
2 files Formatted as multipart/form-data with appropriate boundaries
3 body Sent as-is without modification
4 (lowest) data Alias for body, used only when body is not provided

Fingerprint Merging

When you provide a fingerprint object in the request options, it is merged with the default fingerprint configured in the client constructor. The merging follows a shallow merge strategy where request-level values override constructor-level values for matching keys. Keys that exist only in the constructor default are preserved. Keys that exist only in the request options are added. This allows you to set a base fingerprint identity in the constructor and selectively override specific attributes for individual requests without repeating the entire fingerprint configuration.

Merge Behavior

The following table illustrates how fingerprint merging works with a concrete example. The constructor sets a base fingerprint with platform, timezone, and language. The request overrides the timezone and adds a screen attribute. The final merged fingerprint contains all four attributes.

Attribute Constructor Default Request Override Final Merged Value
platform "Win32" not specified "Win32" (from constructor)
timezone "America/New_York" "Europe/London" "Europe/London" (request overrides)
language "en-US" not specified "en-US" (from constructor)
screen not specified { width: 1920, height: 1080 } { width: 1920, height: 1080 } (from request)
JavaScript
const BBREClient = require("mydisctsolver-bbre");

const client = new BBREClient({
  apiKey: "YOUR_API_KEY",
  fingerprint: {
    platform: "Win32",
    timezone: "America/New_York",
    language: "en-US"
  }
});

async function requestWithMergedFingerprint() {
  const response = await client.request({
    url: "https://geo-restricted.example.com/content",
    method: "GET",
    fingerprint: {
      timezone: "Europe/London",
      screen: { width: 1920, height: 1080 }
    }
  });

  console.log("Status:", response.statusCode);
  console.log("Profile used:", response.profile);
}

requestWithMergedFingerprint();

Complete Fingerprint Override

If you need to completely replace the constructor fingerprint for a specific request, provide all the attributes you want in the request-level fingerprint object. Since the merge is shallow, any constructor-level attributes that you do not include in the request-level object will still be present in the final merged fingerprint. To ensure a clean override, include every attribute you want and set unwanted attributes to null or an empty value.

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

const client = new BBREClient({
  apiKey: "YOUR_API_KEY",
  fingerprint: {
    platform: "Win32",
    timezone: "America/New_York",
    language: "en-US"
  }
});

async function requestWithFullOverride() {
  const response = await client.request({
    url: "https://jp-site.example.com/content",
    method: "GET",
    fingerprint: {
      platform: "MacIntel",
      timezone: "Asia/Tokyo",
      language: "ja-JP",
      screen: { width: 2560, height: 1440 }
    }
  });

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

requestWithFullOverride();

Code Examples

The following examples demonstrate common usage patterns for the request() method. Each example is a complete, runnable code snippet that shows a specific use case with the appropriate request options and response handling.

Simple GET Request

The most basic usage of request() fetches a URL with the default GET method. Only the url parameter is required. All other options use their default values.

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

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

async function simpleGet() {
  const response = await client.request({
    url: "https://api.example.com/products"
  });

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

simpleGet();

GET Request with Query Parameters

Use the params option to append query parameters to the URL. The SDK automatically URL-encodes the parameter values and appends them to the URL.

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

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

async function getWithParams() {
  const response = await client.request({
    url: "https://api.example.com/search",
    method: "GET",
    params: {
      query: "wireless headphones",
      category: "electronics",
      minPrice: 50,
      maxPrice: 200,
      sort: "price_asc",
      page: 1,
      limit: 20
    }
  });

  console.log("Status:", response.statusCode);
  console.log("Search results:", response.data);
}

getWithParams();

POST Request with JSON Body

Use the json option to send a JSON request body. The SDK automatically serializes the object and sets the Content-Type header.

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

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

async function postWithJson() {
  const response = await client.request({
    url: "https://api.example.com/orders",
    method: "POST",
    json: {
      productId: "PROD-12345",
      quantity: 2,
      shippingAddress: {
        street: "123 Main Street",
        city: "New York",
        state: "NY",
        zip: "10001"
      },
      paymentMethod: "credit_card"
    }
  });

  console.log("Order status:", response.statusCode);
  console.log("Order ID:", response.data.orderId);
}

postWithJson();

Synchronous Mode Request

Set sync: true to use the synchronous execution flow. The request is sent to POST /request/execute and the response is returned directly without polling.

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

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

async function syncModeRequest() {
  const response = await client.request({
    url: "https://api.example.com/quick-data",
    method: "GET",
    sync: true,
    timeout: 60
  });

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

syncModeRequest();

Request with Proxy Override

Override the client default proxy for a specific request by providing a proxy object in the request options. This is useful when you need to route specific requests through a different proxy server than the default.

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

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

async function requestWithProxy() {
  const response = await client.request({
    url: "https://geo-restricted.example.com/content",
    method: "GET",
    proxy: {
      host: "us-residential.proxy.com",
      port: 8080,
      username: "proxyuser",
      password: "proxypass"
    },
    sensibility: "high"
  });

  console.log("Status:", response.statusCode);
  console.log("Content:", response.body.substring(0, 200));
}

requestWithProxy();

Request with Cookies

Pass cookies to maintain session state or replay a specific browser session. This example shows the object format for cookies.

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

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

async function requestWithCookies() {
  const response = await client.request({
    url: "https://dashboard.example.com/profile",
    method: "GET",
    cookies: {
      auth_token: "eyJhbGciOiJIUzI1NiIsInR5cCI6IkpXVCJ9",
      session_id: "sess_abc123def456",
      preferences: "lang=en;theme=dark"
    },
    headers: {
      "Accept": "application/json"
    }
  });

  console.log("Profile status:", response.statusCode);
  console.log("Profile data:", response.data);
  console.log("Updated cookies:", response.cookies);
}

requestWithCookies();

Request with HTTP Authentication

Use the auth option to send HTTP Basic authentication credentials with the request. The BBRE engine encodes the credentials and includes them in the Authorization header.

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

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

async function requestWithAuth() {
  const response = await client.request({
    url: "https://api.example.com/protected/resource",
    method: "GET",
    auth: {
      username: "api_user",
      password: "api_secret_key"
    }
  });

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

requestWithAuth();

Adaptive Mode with High Sensibility

Override the client defaults to use adaptive mode with high sensibility for a specific request targeting a heavily protected website. This combination provides full browser rendering with maximum detection evasion.

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

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

async function adaptiveHighSensibility() {
  const response = await client.request({
    url: "https://heavily-protected-site.com/data",
    method: "GET",
    mode: "adaptive",
    sensibility: "high",
    timeout: 240,
    fingerprint: {
      platform: "Win32",
      timezone: "America/New_York",
      language: "en-US",
      screen: { width: 1920, height: 1080 }
    }
  });

  console.log("Status:", response.statusCode);
  console.log("Body length:", response.body.length);
  console.log("Profile:", response.profile);
  console.log("Processing time:", response.processingTime, "ms");
}

adaptiveHighSensibility();

Redirect Control

Control redirect behavior using the allowRedirects and maxRedirects options. Disabling redirects is useful when you need to inspect redirect responses or track redirect chains.

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

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

async function inspectRedirect() {
  const response = await client.request({
    url: "https://short.example.com/abc123",
    method: "GET",
    allowRedirects: false
  });

  console.log("Status:", response.statusCode);
  console.log("Location:", response.headers["location"]);
}

async function limitRedirects() {
  const response = await client.request({
    url: "https://chain.example.com/start",
    method: "GET",
    allowRedirects: true,
    maxRedirects: 3
  });

  console.log("Final status:", response.statusCode);
  console.log("Final URL body:", response.body.substring(0, 100));
}

inspectRedirect();
limitRedirects();

Session-Bound Request

Use the sessionId option to execute a request within an existing BBRE session. Session-bound requests share cookies, browser state, and profile information with other requests in the same session.

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

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

async function sessionBoundRequest() {
  const session = await client.createSession({
    mode: "adaptive",
    sensibility: "high"
  });

  const loginResponse = await client.request({
    url: "https://app.example.com/login",
    method: "POST",
    json: { username: "alice", password: "secret123" },
    sessionId: session.sessionId
  });

  const dashboardResponse = await client.request({
    url: "https://app.example.com/dashboard",
    method: "GET",
    sessionId: session.sessionId
  });

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

  await client.closeSession(session.sessionId);
}

sessionBoundRequest();

PUT Request for Resource Update

Use the PUT method to update an existing resource on the target server. This example demonstrates updating a user profile with JSON data.

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

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

async function updateResource() {
  const response = await client.request({
    url: "https://api.example.com/users/12345",
    method: "PUT",
    json: {
      name: "Alice Johnson",
      email: "[email protected]",
      bio: "Software developer and open source contributor"
    },
    headers: {
      "Authorization": "Bearer eyJhbGciOiJIUzI1NiJ9.eyJ1c2VyIjoiYWxpY2UifQ"
    }
  });

  console.log("Update status:", response.statusCode);
  console.log("Updated user:", response.data);
}

updateResource();

DELETE Request

Use the DELETE method to remove a resource from the target server.

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

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

async function deleteResource() {
  const response = await client.request({
    url: "https://api.example.com/users/12345",
    method: "DELETE",
    headers: {
      "Authorization": "Bearer eyJhbGciOiJIUzI1NiJ9.eyJ1c2VyIjoiYWxpY2UifQ"
    }
  });

  console.log("Delete status:", response.statusCode);
  console.log("Deleted:", response.data);
}

deleteResource();

SSL Verification Disabled

Set verify: false to disable SSL certificate verification. This is useful for development environments with self-signed certificates or for accessing internal services with expired certificates. Do not disable SSL verification in production unless you understand the security implications.

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

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

async function requestWithoutSslVerification() {
  const response = await client.request({
    url: "https://internal-dev.example.local/api/data",
    method: "GET",
    verify: false
  });

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

requestWithoutSslVerification();

Error Handling

The request() method throws errors when the BBRE API returns an error response, when the request times out, or when a network-level failure occurs. Errors are thrown as standard JavaScript Error objects with additional properties that provide context about the failure. Always wrap your request() calls in try-catch blocks to handle errors gracefully and implement appropriate retry or fallback logic.

Error Response Structure

When the BBRE API returns an error, the thrown error object contains the following properties that help you diagnose and handle the failure.

Property Type Description
message string Human-readable error message describing the failure.
code string Machine-readable error code from the BBRE API (e.g., INSUFFICIENT_BALANCE, URL_REQUIRED).
statusCode number HTTP status code from the BBRE API response (e.g., 400, 401, 403, 408, 500).

Basic Error Handling

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

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

async function safeRequest() {
  try {
    const response = await client.request({
      url: "https://api.example.com/data",
      method: "GET"
    });

    console.log("Status:", response.statusCode);
    console.log("Data:", response.data);
  } catch (error) {
    console.error("Request failed:", error.message);
    console.error("Error code:", error.code);
    console.error("HTTP status:", error.statusCode);
  }
}

safeRequest();

Retry Logic with Error Handling

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

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

async function requestWithRetry(options, maxRetries, delayMs) {
  let lastError;

  for (let attempt = 1; attempt <= maxRetries; attempt++) {
    try {
      const response = await client.request(options);
      return response;
    } catch (error) {
      lastError = error;

      const isRetryable = error.code === "SERVICE_UNAVAILABLE"
        || error.code === "SERVICE_TIMEOUT"
        || error.statusCode === 503
        || error.statusCode === 408;

      if (!isRetryable || attempt === maxRetries) {
        throw error;
      }

      const waitTime = delayMs * Math.pow(2, attempt - 1);
      await new Promise(resolve => setTimeout(resolve, waitTime));
    }
  }

  throw lastError;
}

async function fetchWithRetry() {
  try {
    const response = await requestWithRetry(
      { url: "https://api.example.com/data", method: "GET" },
      3,
      1000
    );
    console.log("Status:", response.statusCode);
  } catch (error) {
    console.error("All retries failed:", error.message);
  }
}

fetchWithRetry();

Common Error Codes

The following table lists the most common error codes you may encounter when using the request() method, along with their causes and recommended solutions.

Error Code HTTP Status Cause Solution
URL_REQUIRED 400 The url parameter was not provided in the request options. Ensure the options object includes a valid url string with the full protocol (http or https).
INVALID_MODE 400 The mode parameter contains an invalid value. Use "passive" or "adaptive" as the mode value. Values are case-sensitive.
INVALID_SENSIBILITY 400 The sensibility parameter contains an invalid value. Use "low", "medium", or "high" as the sensibility value.
INSUFFICIENT_BALANCE 402 Your account balance is too low to process the request. Add funds to your account through the MyDisct Solver dashboard before making additional requests.
API_KEY_REQUIRED 401 No API key was provided in the client configuration. Ensure the apiKey parameter is set in the BBREClient constructor.
INVALID_API_KEY 403 The provided API key is not valid or has been revoked. Verify your API key in the MyDisct Solver dashboard. Generate a new key if necessary.
TASK_NOT_FOUND 404 The task ID returned by the create endpoint was not found during polling. This is typically a transient error. Retry the request. If persistent, contact support.
SERVICE_TIMEOUT 408 The request exceeded the configured timeout duration. Increase the timeout value in the request options or client constructor. Consider using sync mode for faster response.
SERVICE_UNAVAILABLE 503 The BBRE engine is temporarily unavailable due to high load or maintenance. Implement retry logic with exponential backoff. Wait a few seconds before retrying.

Best Practices

Use the json Option for JSON Bodies

When sending JSON data, always use the json option instead of manually serializing with JSON.stringify() and setting the Content-Type header. The json option handles both serialization and header management automatically, reducing the chance of formatting errors and making your code cleaner and more readable.

Prefer Async Mode for Production Workloads

Use the default asynchronous execution mode (sync: false) for production applications. Async mode uses short-lived polling connections that are more resilient to network interruptions and better suited for high-concurrency workloads. Reserve synchronous mode for simple scripts, testing, and scenarios where you need the simplest possible request flow.

Always Implement Error Handling

Wrap every request() call in a try-catch block. Network requests can fail for many reasons including timeout, insufficient balance, invalid parameters, and temporary service unavailability. Implement retry logic with exponential backoff for transient errors like SERVICE_UNAVAILABLE and SERVICE_TIMEOUT. Log error codes and messages for debugging.

Override Settings Per Request When Needed

Set sensible defaults in the client constructor and override them at the request level only when specific requests need different behavior. For example, keep the default mode as "passive" for most requests and override to "adaptive" only for targets that require full browser rendering. This approach minimizes configuration duplication while maintaining flexibility.

Use Consistent Fingerprints for Multi-Request Workflows

When making multiple requests to the same target website, use a consistent fingerprint configuration. Set the base fingerprint in the constructor and avoid changing fingerprint attributes between requests to the same domain. Inconsistent fingerprints across requests can trigger bot detection systems that track browser identity consistency.

Check the Response statusCode Before Processing Data

Always check response.statusCode before processing the response body. A successful BBRE request (where success is true) means the BBRE engine received a response from the target server, but the target server may have returned a 403, 404, or 500 status code. Validate the status code to ensure the target server returned the expected response before parsing the body.

Use Sessions for Stateful Workflows

For workflows that require maintaining state across multiple requests (login, form submission, multi-page navigation), use BBRE sessions with the sessionId option instead of manually managing cookies. Sessions automatically maintain cookies, browser state, and profile consistency across all requests within the session, providing a more reliable and simpler approach to stateful workflows.

Common Issues

Missing URL Parameter

Symptom: Request fails immediately with URL_REQUIRED error.
Cause: The url property was not included in the options object, or it was set to undefined, null, or an empty string.
Solution: Ensure the options object always includes a valid url string with the full protocol prefix (https:// or http://). Check that any dynamic URL construction produces a valid result before passing it to request().

JSON Body Not Being Parsed by Target Server

Symptom: The target server returns a 400 Bad Request or ignores the request body when sending JSON data using the body parameter.
Cause: When using body with a JSON string, the Content-Type header is not automatically set to application/json. The target server does not know to parse the body as JSON.
Solution: Use the json parameter instead of body for JSON data. The json option automatically handles serialization and sets the correct Content-Type header. If you must use body, manually set the Content-Type header to application/json in the headers object.

Timeout Errors on Long-Running Requests

Symptom: Requests to certain websites consistently fail with timeout errors, even though the websites are accessible from a regular browser.
Cause: The default timeout of 120 seconds may be insufficient for adaptive mode requests with high sensibility, especially on websites with complex JavaScript rendering or aggressive bot detection that triggers additional processing steps.
Solution: Increase the timeout value in the request options. For adaptive mode with high sensibility, use 180 to 240 seconds. You can also try switching to synchronous mode (sync: true) to eliminate polling overhead, though this holds a connection open for the entire duration.

Cookies Not Being Sent to Target Server

Symptom: The target server does not recognize the session or authentication state despite providing cookies in the request options.
Cause: The cookie format may be incorrect, or the cookie values may contain special characters that need encoding. When using the array format, the domain property may not match the target URL domain.
Solution: Use the simple object format for cookies when possible. Verify that cookie values are correctly formatted strings. When forwarding cookies from a previous response, pass the response.cookies object directly without modification. For complex cookie scenarios, consider using BBRE sessions which handle cookie management automatically.

Fingerprint Merging Producing Unexpected Results

Symptom: The browser profile used for a request contains unexpected fingerprint attributes that do not match the request-level fingerprint configuration.
Cause: The request-level fingerprint is merged with the constructor default fingerprint using a shallow merge. Constructor-level attributes that are not overridden in the request options are preserved in the final merged fingerprint.
Solution: Review both the constructor fingerprint and the request-level fingerprint to understand the merge result. If you need a completely different fingerprint for a specific request, include all desired attributes in the request-level fingerprint object. Check the response.profile property to see the actual fingerprint used for each request.