Logo of Lexmount
DocsTemplatesBlogHelp Center
GitHub
Logo of LexmountLexmount Browser

Get started

Lexmount Documentation
Console guide

Browser

OverviewQuickstartCapabilitiesExamples

Web Fetch

OverviewQuick Start
Common Errors

Web Search

OverviewQuick StartSearch API

Runtime

OverviewQuickstartCapabilitiesExamples

Help and billing

Capability FAQ
ChangelogContact support
Node.js SDK

Node.js Capabilities

Current client, session, context, extension, download, CDP, Browser Agent, error, and logging APIs.

Client and regions

import { Lexmount } from "lexmount";

const client = new Lexmount({
  region: "<region-id>",
  timeout: 60_000,
});

console.log(await client.regionInfo());
console.log(await client.catalogInfo());

The client reads credentials from constructor options or environment variables. Region catalog discovery is best effort: an unavailable catalog or probe falls back to the configured base URL.

Sessions

Create options

const session = await client.sessions.create({
  browserMode: "normal",
  windowSize: "1920,1080",
  downloads: { enabled: true },
  recording: { persistent: true },
});
OptionPurpose
browserModenormal for Chromium or light for Moli
context / contextDescriptionReuse or create persistent browser state
extensionIdsMount uploaded extensions
proxy / officialProxySelect a local, external, or official proxy
downloadsEnable or disable stored session downloads
recordingEnable or disable persistent replay; forced off for Moli
customImageIdStart an approved custom browser image
windowSizeSet ACE browser size as width,height
enableLightmountLayoutEnable the LightMount layout integration; defaults to true
enableLightmountResourceOverride layout-resource integration for this session
enableCaptchaRequest automatic CAPTCHA processing for this session; disabled by default
asyncCreateUse async create and wait for active; defaults to true
pollIntervalMs / pollTimeoutMsControl activation polling

officialProxy: true and proxy are mutually exclusive. Plan capabilities determine whether contexts, extensions, proxies, and custom images are available.

Automatic CAPTCHA processing

Use SDK 0.6.1 or later and explicitly opt in when creating a session:

const session = await client.sessions.create({
  browserMode: "normal",
  enableCaptcha: true,
});
try {
  console.log(session.id);
} finally {
  await session.close();
}

The default is false. This preference applies only to the new session; other sessions in the same project can remain disabled. The SDK sends the top-level enable_captcha boolean in both synchronous and asynchronous create requests.

The service automatically detects and processes CAPTCHAs for opted-in sessions with eligible project access. Availability and usage depend on the project's plan and remaining CAPTCHA allowance. Continue controlling the browser with the existing SDK or CDP connection.

See session lifecycle for the corresponding console option.

Read, list, targets, and close

const current = await client.sessions.get(session.id);
const sessions = await client.sessions.list({ status: "active" });

console.log(sessions.pagination.totalCount);
for (const item of sessions) {
  console.log(item.id, item.status, item.regionId, item.browserType);
}

for (const target of await client.sessions.listTargets(session.id)) {
  console.log(target.title, target.url, target.inspectUrl);
}

await session.close();
// Equivalent when only the ID is available:
await client.sessions.delete({ sessionId: session.id });

Downloads

const result = await client.sessions.downloads.list(session.id);
console.log(result.summary.count, result.summary.totalSize);

const file = await client.sessions.downloads.get(session.id, "<download-id>");
const archive = await client.sessions.downloads.archive(session.id);
const deleted = await client.sessions.downloads.delete(session.id);
console.log(file.length, archive.length, deleted.deletedCount);

Stored downloads are enabled by default. Configure the remote browser download behavior as shown in the quickstart repository so files reach the persistent download directory.

Local Proxy Tunnels

SDK 0.6.0 introduced client.tunnels.open(); use 0.6.1 or later. Once ready, create a normal session with proxy: { type: "local", tunnelId: tunnel.id } to use the SDK machine's network and DNS. This requires custom_proxy, the same project/Key/region, and excludes official or external proxy. Close the session before the tunnel. See the local proxy guide for complete examples and options.

Contexts

const context = await client.contexts.create({
  description: "Authenticated storefront",
  metadata: { owner: "agent-a" },
});

const session = await client.sessions.create({
  context: { id: context.id, mode: "readWrite" },
});

const contexts = await client.contexts.list({ status: "available", limit: 20 });
const details = await client.contexts.get(context.id);
const forked = await client.contexts.fork(context.id);

await client.contexts.forceRelease(context.id);
await client.contexts.delete(forked.id);

A context used by an active read-write session is locked. Current fork behavior copies an offline available context; hot fork, copy-on-write, and lineage tracking are not supported.

Extensions

const extension = await client.extensions.upload(
  "/absolute/path/to/extension.zip",
  {
    name: "demo-extension",
  },
);

const extensions = await client.extensions.list({ limit: 20, offset: 0 });
const details = await client.extensions.get(extension.id);

const session = await client.sessions.create({ extensionIds: [extension.id] });
await session.close();
await client.extensions.delete(extension.id);

The service accepts .zip and .crx archives. An extension cannot be deleted while an active session uses it.

CDP helpers and integrated authentication

import { connectOverCDP, Lexmount } from "lexmount";

const client = new Lexmount();
const session = await client.sessions.create();
const cdp = await connectOverCDP(session);

console.log(await cdp.send("Browser.getVersion"));

await cdp.close();
await session.close();
client.close();

The package also exports registerIntegratedAuthCallback and deregisterIntegratedAuthCallback for application-provided authentication handling.

Errors and logs

import {
  APIError,
  AuthenticationError,
  ContextLockedError,
  NetworkError,
  TimeoutError,
  setLogLevel,
} from "lexmount";

setLogLevel("INFO");

try {
  await client.sessions.create();
} catch (error) {
  if (error instanceof AuthenticationError) {
    console.error("Check API Key and Project ID");
  } else if (error instanceof ContextLockedError) {
    console.error(error.activeSessionId, error.retryAfter);
  } else if (error instanceof NetworkError || error instanceof TimeoutError) {
    console.error("Check whether a session was reserved before retrying");
  } else if (error instanceof APIError) {
    console.error(error.statusCode);
  } else {
    throw error;
  }
}

Logging helpers are setLogLevel, enableLogging, disableLogging, and getLogger.

Browser Agent

Browser Agent executes a browser task from a natural-language instruction. A Run is one execution; a saved Agent holds a reusable instruction and optional output schema. Use client.browserAgent with SDK 0.7.0.

Setup

npm install lexmount@0.7.0
export LEXMOUNT_API_KEY='<your-api-key>'
export LEXMOUNT_PROJECT_ID='<your-project-id>'
# Optional: SDK 0.7.0 defaults to this global COM origin.
export LEXMOUNT_BASE_URL=https://api.lexmount.com

Use an API Key and Project ID from the same project, with Browser Agent enabled in the selected environment. Set the HTTPS origin, without /v1/browser-agent; the SDK adds that path. Set https://api.lexmount.cn explicitly for CN. Playwright is not required for these Agent API calls.

Run a task

Choose and persist a new RUN_IDEMPOTENCY_KEY for one logical task before running this example. Reuse it with the identical request when recovering that task; use a new key for an intentionally new task.

export RUN_IDEMPOTENCY_KEY='<persistent-unique-key-for-this-task>'

Save as agent.mjs and run node agent.mjs:

import { APIError, Lexmount, RunWaitTimeout } from 'lexmount';

const key = process.env.RUN_IDEMPOTENCY_KEY;
if (!key) throw new Error('Set a persistent RUN_IDEMPOTENCY_KEY first');
const client = new Lexmount();
try {
  const receipt = await client.browserAgent.runs.create(
    {
      query: 'Read the page title and summarize the page.',
      start_url: 'https://example.com/',
    },
    { idempotencyKey: key }
  );
  console.log('Accepted:', receipt.id); // Save this Run ID before waiting.
  const run = await client.browserAgent.runs.wait(receipt.id, {
    timeoutMs: 300_000,
  });
  console.log(run.id, run.status, run.output);
  if (run.status !== 'succeeded') {
    console.error(run.stop_reason, run.error);
    process.exitCode = 1;
  }
} catch (error) {
  if (error instanceof RunWaitTimeout) {
    console.error('Resume with runs.get/wait:', error.run_id);
  } else if (error instanceof APIError) {
    console.error(error.status_code, error.code, error.request_id);
  } else {
    throw error;
  }
  process.exitCode = 1;
} finally {
  client.close();
}

A create response is a queued receipt, not a completed result. Save receipt.id and use runs.get(id) or runs.wait(id) to recover after a process restart. Closing the SDK client does not cancel an active Run.

Reuse a saved Agent

Set two additional persistent keys, AGENT_IDEMPOTENCY_KEY for the Agent creation and SAVED_RUN_IDEMPOTENCY_KEY for this Run. Save the returned Agent ID and use it for later Runs; creating the Agent is a one-time setup step.

import { Lexmount } from 'lexmount';

const agentKey = process.env.AGENT_IDEMPOTENCY_KEY;
const runKey = process.env.SAVED_RUN_IDEMPOTENCY_KEY;
if (!agentKey || !runKey)
  throw new Error('Set both persistent idempotency keys');
const client = new Lexmount();
try {
  const agent = await client.browserAgent.agents.create(
    {
      name: 'Page summary',
      instruction: 'Summarize the page in {{language}}.',
      start_url: 'https://example.com/',
      output_schema: {
        type: 'object',
        properties: { summary: { type: 'string' } },
        required: ['summary'],
        additionalProperties: false,
      },
    },
    { idempotencyKey: agentKey }
  );
  const receipt = await client.browserAgent.runs.create(
    {
      agent_id: agent.id,
      variables: { language: 'English' },
      metadata: { source: 'docs' },
    },
    { idempotencyKey: runKey }
  );
  console.log('Agent:', agent.id, 'Run:', receipt.id);
  // Recover this Run later with runs.get(receipt.id) or runs.wait(receipt.id).
} finally {
  client.close();
}

Supply exactly the instruction's template variables. The accepted Run freezes the Agent revision, expanded instruction and schema; later Agent edits do not change that Run. metadata is returned to your application and is not sent to the model. A successful schema-based output is an object; free-form output is text.

Manage resources

All methods below are on client.browserAgent. Await each call.

OperationCall
Read / list Agentsagents.get(id) / agents.list()
Edit an Agentagents.update(id, { revision: current.revision, name: "Updated name" })
Delete an Agentagents.delete(id)
Read / list Runsruns.get(id) / runs.list()
Request cancellationruns.cancel(id)
Wait for terminal stateruns.wait(id)

Read the current Agent first and pass its revision when updating. A revision conflict requires reading it again; updates are not automatically retried. Cancellation can race with completion: inspect the returned state and keep reading until terminal if it is still cancelling.

Recovery and errors

  • The SDK generates an idempotency key if omitted. For recovery across process restarts, supply your own: idempotencyKey in the second options argument. Persist the key and request body before sending; use 1–128 visible ASCII characters without spaces. Same key/body replays the original receipt for at least seven days; a different body conflicts. Beyond that window, reconcile through history before creating anything again.
  • succeeded, failed, timed_out, and cancelled are terminal Run results. HTTP success alone does not mean the task succeeded; inspect status, stop_reason, error, and output.
  • RunWaitTimeout only stops local polling. Resume with the known Run ID, or explicitly request cancellation. timeoutMs, pollIntervalMs, and requestTimeoutMs use milliseconds.
  • APIError includes status_code, code, and request_id. Keep the request ID for support. Pass { withResponse: true } to get success response metadata.
  • Keep the API Key used to create a Run valid until execution and cleanup finish. Revoking it can fail an active Run with credential_unavailable; changing the client's key does not replace the original Run's execution credential.
  • usage.credits can be null while metering is pending; it does not mean zero cost. Task execution may have external side effects, so an unknown result must not be blindly resubmitted.

Runnable examples cover basic execution, saved Agents and recovery.

Node.js Quick Start

Create Chromium and Moli sessions and connect to Chromium with Playwright.

Node.js Examples

Choose a runnable Node.js quickstart script by browser task.

Table of Contents

Client and regions
Sessions
Create options
Automatic CAPTCHA processing
Read, list, targets, and close
Downloads
Local Proxy Tunnels
Contexts
Extensions
CDP helpers and integrated authentication
Errors and logs
Browser Agent
Setup
Run a task
Reuse a saved Agent
Manage resources
Recovery and errors

Still need help?