> ## Documentation Index
> Fetch the complete documentation index at: https://docs.heylua.ai/llms.txt
> Use this file to discover all available pages before exploring further.

# LuaBrowser

> Named browser class with its own engine, allowed domains, confirmations, session limits, file and page-script settings

`LuaBrowser` is a named browser with its own rules. Attach one or more to the agent with [`browsers`](https://docs.heylua.ai/reference/sdk/luaagent), then pick one per call with `browser: '<name>'`. Use named browsers when different pieces of work need different rules: one browser locked to a supplier portal that asks for approval before it submits anything, another that may read any public page, a third that may download invoices.

The agent's own [`browser`](https://docs.heylua.ai/reference/sdk/luaagent) option takes the same settings without a name, and `browser: true` takes the defaults. A `LuaBrowser` is those settings under a name you can select per call. For what the browser does once it is on, see [`Browser`](https://docs.heylua.ai/reference/sdk/browser).

*Verified against lua-cli 3.58.0.*

```ts theme={null}
import { LuaBrowser, defineBrowser } from 'lua-cli';
```

## Quick example

```ts src/browsers/supplier.ts theme={null}
import { LuaBrowser } from 'lua-cli';

export const supplierPortal = new LuaBrowser({
  name: 'supplier-portal',
  description: 'Checks stock and places restock orders on the supplier site',
  allowedDomains: ['ikea.com'],
  confirmActions: ['submit'],
  fallback: 'none',
  maxSessionMinutes: 30,
});
```

```ts src/index.ts theme={null}
import { LuaAgent } from 'lua-cli';
import { supplierPortal } from './browsers/supplier';

export default new LuaAgent({
  name: 'stock-checker',
  persona: 'You check stock levels for the store team.',
  browsers: [supplierPortal],
});
```

```ts theme={null}
const page = await Browser.read('https://www.ikea.com/gb/en/p/billy-bookcase-white-00263850/', {
  browser: 'supplier-portal',
  waitFor: 'networkidle',
});
```

Attaching at least one browser turns the browser on, so `browser: true` is not needed as well.

## Constructor

```ts theme={null}
new LuaBrowser(config: LuaBrowserConfig)
defineBrowser(config: LuaBrowserConfig): LuaBrowser
```

`defineBrowser({ … })` and `new LuaBrowser({ … })` produce the same thing; use whichever reads better in your project. Pass the config as an object literal so the compiler can read it.

**name** `string` *required*

The name you select this browser by. It starts with a letter or digit and then uses only letters, digits, `_` and `-`, up to 64 characters. The constructor throws on any other name, and `lua compile` fails on it too.

**description** `string`

One sentence about what this browser is for. It appears in listings.

**engine** `'auto' | 'agent-browser' | 'browser-use'` (default: auto)

Which browser runs the commands. `'auto'` uses the user's desktop browser when it is online and the Lua cloud browser otherwise; `'agent-browser'` uses those two and never Browser-Use; `'browser-use'` uses Browser-Use only. See [Where pages open](https://docs.heylua.ai/reference/sdk/browser.md#where-pages-open).

**fallback** `'browser-use' | 'none'` (default: browser-use)

What happens when the Lua cloud browser cannot get past a page. `'browser-use'` retries that command once on Browser-Use; `'none'` keeps every page on the Lua cloud browser. Browser-Use is never used when `engine` is `'agent-browser'` or when `allowedDomains` is set.

**proxyCountry** `string`

A two-letter country code, such as `'gb'` or `'de'`, for the country Browser-Use browses from. It applies only to work that runs on Browser-Use.

**allowedDomains** `string[]`

Hosts this browser may open. List each host the pages need, or use a wildcard such as `*.ikea.com` for a domain and its subdomains. The list is checked before every command that opens a URL; a blocked URL fails with `BROWSER_DOMAIN_NOT_ALLOWED`. On the Lua cloud browser it also applies to redirects and to everything a page loads, so include the hosts a page loads its content from. Empty or unset allows all public sites.

**confirmActions** `string[]`

Actions a person has to approve before they run: `navigate`, `click`, `fill`, `type`, `select`, `press`, `scroll`, `submit`, and for the step-by-step commands `download`, `upload`, `pdf` and `eval`. `submit` covers clicking a button such as Buy, Pay, Place order, Sign in or Send, and pressing Enter. See [`confirmActions`](https://docs.heylua.ai/reference/sdk/browser#configuration) for how a held action is approved.

**maxSessionMinutes** `number` (default: 10)

How long one Lua cloud browser session may stay open, in whole minutes. `lua compile` accepts 1 to 60.

**idleTimeoutSeconds** `number` (default: 120)

How long a Lua cloud browser session may go without a command before it closes, in whole seconds. `lua compile` accepts 1 to 900.

**maxConcurrentSessions** `number` (default: 3)

How many Lua cloud browser sessions this agent may have open at once for one person. A command that would open one more fails with `BROWSER_SESSION_LIMIT`. `lua compile` accepts 1 to 100; the platform allows at most 10, and your plan may allow fewer, so the lowest of the three applies.

**screenshots** `'always' | 'onError' | 'never'` (default: onError)

When a browser log row carries a screenshot reference. On the Lua cloud browser a screenshot comes back in the command result and is not stored, so its log rows carry no reference.

**logContent** `'summary' | 'full' | 'none'` (default: summary)

How much page content the browser log rows keep. `'summary'` keeps titles and sizes, `'full'` also keeps page text (shortened), `'none'` keeps neither.

**maxDownloadMb** `number`

Turns on `Browser.download`, `Browser.pdf` and `Browser.upload` for this browser, and caps each file, in whole megabytes from 1 to 500. The cap is lowered to your plan's per-file limit. Unset, the three methods fail with `files_disabled`. See [Files](https://docs.heylua.ai/reference/sdk/browser.md#files).

**allowedMimeTypes** `string[]`

The types a download may have, such as `['application/pdf', 'image/*']`, up to 50 entries. Each entry is `type/subtype` or `type/*`. The type is read from the file's own bytes, not from what the site says it is; a file of any other type is refused with `mime`. Empty or unset allows any type.

**allowScripts** `boolean` (default: false)

Lets your own code run page scripts with `Browser.eval` on this browser. It needs an `allowedDomains` list naming at least one real domain; `lua compile` fails otherwise. The chat model never runs scripts, and neither does `Browser.execute`. See [Page scripts](https://docs.heylua.ai/reference/sdk/browser.md#page-scripts).

**persist** `boolean`

Accepted and stored, not enforced yet.

**credentials** `string[]`

Accepted and stored, not enforced yet. To sign a browser in, use a [saved login](https://docs.heylua.ai/reference/sdk/browser.md#saved-logins) with `Browser.login` instead.

## Selecting a browser

Every `Browser` method takes the name. `Browser.read` takes it in its options; the others take it in their input object.

```ts theme={null}
await Browser.read('https://example.com', { browser: 'research' });
await Browser.execute({ task: 'Find the current price', browser: 'research' });
await Browser.navigate({ browser: 'supplier-portal', sessionKey: 'restock', url: 'https://www.ikea.com/' });
await Browser.login({ browser: 'supplier-portal', credential: 'supplier' });
```

* **A call without `browser`** uses the agent's `browser` settings when the agent sets `browser`, and the first entry in `browsers` when it does not.
* **A name the agent does not have** fails with `BROWSER_PROFILE_NOT_FOUND`. `Browser.read` throws it; the other methods return it in `code`.
* **Settings do not merge.** The browser you name supplies every setting; the agent's `browser` settings do not fill in its gaps.

## Pushing and listing

```bash theme={null}
lua push browser --name supplier-portal   # push one browser
lua push agent                            # so the agent picks up its browsers list
lua push all                               # browsers with everything else
lua browsers                               # list the browsers on the agent
lua browsers delete --browser-name supplier-portal
```

A new browser needs both pushes: the browser itself, and the agent that lists it. See [`lua browsers`](https://docs.heylua.ai/reference/cli/browser#lua-browsers).

## Compile-time checks

`lua compile` (and `lua push`, which compiles first) refuses a browser it cannot trust:

| What you wrote | What the compile says |
| - | - |
| A `name` outside the allowed characters, or longer than 64 | `Browser name "…" must start with a letter or digit and use only letters, digits, underscores or hyphens (max 64)` |
| An unknown `engine`, `fallback`, `screenshots` or `logContent` | ``Browser "…" has an invalid `engine`: it must be one of auto, agent-browser, browser-use`` (and the same shape for the other three) |
| A `proxyCountry` that is not two letters | `… it must be a two-letter country code, like "de"` |
| A limit that is not a whole number in range | `… it must be a whole number of minutes from 1 to 60` (and the same shape for seconds and sessions) |
| A `maxDownloadMb` outside 1 to 500, or not a whole number | `… it must be a whole number of megabytes from 1 to 500` |
| More than 50 `allowedMimeTypes`, or an entry that is not a MIME type | `… it must be a list of at most 50 MIME types like "application/pdf" or "image/*"` |
| `allowScripts: true` with no real domain in `allowedDomains` | ``Browser "…": `allowScripts: true` needs an `allowedDomains` list naming at least one real domain, like "shop.example.com"`` |
| Two browsers with the same `name` | `Browser name "…" is already used by <file>; each LuaBrowser needs its own name` |
| An entry in `browsers` that is not a `LuaBrowser` | ``Agent "…" lists `<ref>` in `browsers`, but it is not a LuaBrowser`` |

A real domain means a hostname with a public suffix, such as `shop.example.com`; a wildcard such as `*.shop.example.com` counts too. A single word with no dot, or an IP address, does not.

## Examples

**Read-only research**

No writes, no files, no scripts: a browser for reading public pages. Setting `allowedDomains` also keeps every page on the Lua cloud browser, because the list cannot be enforced on a remote one.

```ts src/browsers/research.ts theme={null}
import { defineBrowser } from 'lua-cli';

export const research = defineBrowser({
  name: 'research',
  description: 'Reads public documentation and pricing pages',
  allowedDomains: ['*.heylua.ai', 'docs.example.com'],
  maxSessionMinutes: 5,
  idleTimeoutSeconds: 60,
  logContent: 'summary',
});
```

**Supplier portal**

Locked to one site, and nothing that submits runs without a person approving it.

```ts src/browsers/supplier.ts theme={null}
import { LuaBrowser } from 'lua-cli';

export const supplierPortal = new LuaBrowser({
  name: 'supplier-portal',
  description: 'Checks stock and places restock orders on the supplier site',
  engine: 'agent-browser',
  allowedDomains: ['supplier.example.com'],
  confirmActions: ['submit', 'fill'],
  maxSessionMinutes: 30,
  maxConcurrentSessions: 1,
  screenshots: 'always',
});
```

**Files**

`maxDownloadMb` turns on downloads, PDFs and uploads, and `allowedMimeTypes` keeps the browser to the two types this work needs.

```ts src/browsers/invoices.ts theme={null}
import { defineBrowser } from 'lua-cli';

export const invoices = defineBrowser({
  name: 'invoices',
  description: 'Saves invoices from the billing portal',
  allowedDomains: ['billing.example.com'],
  maxDownloadMb: 10,
  allowedMimeTypes: ['application/pdf', 'image/png'],
});
```

```ts theme={null}
const saved = await Browser.download({ browser: 'invoices', ref: '@e7', name: 'march-invoice.pdf' });
if (saved.error) throw new Error(`${saved.code}: ${saved.error}`);
```

**Page scripts**

`allowScripts` lets your own code read a value off the page with one script instead of a dozen commands. It needs a real domain in `allowedDomains`.

```ts src/browsers/dashboard.ts theme={null}
import { defineBrowser } from 'lua-cli';

export const dashboard = defineBrowser({
  name: 'dashboard',
  description: 'Reads totals off our internal reporting dashboard',
  allowedDomains: ['reports.example.com'],
  allowScripts: true,
});
```

```ts theme={null}
const rows = await Browser.eval({
  browser: 'dashboard',
  sessionKey: 'reports',
  js: 'document.querySelectorAll("table tbody tr").length',
});
```

## Types

`LuaBrowserConfig` and `LuaBrowserSettings` are exported from `lua-cli`. `LuaBrowserConfig` is `LuaBrowserSettings` plus `name` and `description`; `BrowserSwitchConfig` is the shape the agent's `browser` option takes.

```ts theme={null}
import type { LuaBrowserConfig, LuaBrowserSettings, BrowserProfileOption } from 'lua-cli';
```

## See also

* [`Browser`](https://docs.heylua.ai/reference/sdk/browser) — the methods, saved logins, files, page scripts, limits and error codes
* [Use the browser](https://docs.heylua.ai/build/use-the-browser.md) — which method to reach for, and the settings worth having from the start
* [`LuaAgent`](https://docs.heylua.ai/reference/sdk/luaagent) — the `browser` and `browsers` options
* [`lua browser`](https://docs.heylua.ai/reference/cli/browser) — try a page or a task from the terminal, list or delete browsers
* [`lua push`](https://docs.heylua.ai/reference/cli/push) — push a browser and the agent that lists it


This documentation is built and hosted on [Mintlify](https://mintlify.com), a developer documentation platform.