Runtimes

View as Markdown

A Runtime is the durable resource that performs automation. It represents the thing being automated: a browser today, with computers and spreadsheets as other runtime types in the same model.

A Runtime belongs to a Space and owns its configuration and identity. Tools, Agents, and browser connections all operate through a Runtime.

The API currently exposes one runtime type:

TypeMeaning
browserA managed browser Runtime.

The Runtime response exposes its generated identifier as id (RuntimeId). When another resource or request refers to the Runtime, the field is named runtimeId. Treat the ID as opaque; create it through the API rather than constructing one yourself.

Starting a Runtime opens a Run and returns its runId.

Choose the Runtime lifecycle

The profile option determines whether the browser identity persists:

Runtime shapeprofileStarts by defaultWhat happens when it stops
EphemeralOmitted or falseYesThe session is single-use; create a new Runtime for the next session.
Profile-backedtrueNoThe Runtime can be started again with the same browser identity.

Use an ephemeral Runtime for isolated jobs. Use a profile-backed Runtime when cookies, logins, or local storage should survive a stop and restart.

Create an ephemeral Runtime

1const runtime = await bctrl.runtimes.create({
2 name: "checkout-job",
3});
4
5console.log(runtime.id, runtime.activeRunId);
6console.log(runtime.connection?.cdpUrl);

Ephemeral Runtimes start during creation unless you pass start: false. Their response includes the active Run and run-scoped connection URLs.

If you do not need a label, the minimal request is valid too:

1const runtime = await bctrl.runtimes.create({});

Create a profile-backed Runtime

Profile-backed Runtimes are reusable and start stopped by default. Pass start: true when you want a one-call create-and-start flow.

1const runtime = await bctrl.runtimes.create({
2 name: "customer-portal",
3 profile: true,
4});
5
6const started = await bctrl.runtimes.start(runtime.id);
7console.log(started.runId, started.connection.cdpUrl);
8
9await bctrl.runtimes.stop(runtime.id);
10
11// Start the same Runtime later. Its browser identity is retained.
12await bctrl.runtimes.start(runtime.id);

Runtime ID and Run ID

Use the Runtime object’s id when operating on the Runtime. Use the Run’s runId when inspecting one execution:

FieldWhere it appearsUse it for
idRuntime response (runtime.id)Create, configure, start, and stop the Runtime.
runtimeIdRun, Tool, and related resource fieldsRefer to the Runtime from another resource.
idRun response (run.id)Identify the returned Run object.
runIdRun-scoped method arguments and start responsesTrace, events, recordings, streaming, and audits.

Runtime lifecycle

The Runtime owns the lifecycle; each start opens a Run:

1const current = await bctrl.runtimes.get(runtime.id);
2const runtimes = await bctrl.runtimes.list({ spaceId: "default" });
3
4await bctrl.runtimes.update(runtime.id, {
5 name: "customer-portal-prod",
6});
7
8await bctrl.runtimes.stop(runtime.id);

Runtime status is active, stopped, or failed. Read the associated Run to understand what happened during an active or completed session.

Configure the browser

Runtime creation has two kinds of options:

  • Lifecycle options decide where the Runtime belongs, whether its browser identity persists, and when it starts.
  • Browser configuration decides how the browser behaves once it starts.

Creation parameters

ParameterTypeRequiredDescription
type"browser"NoRuntime type. Defaults to "browser".
spaceIdstring | "default"NoSpace whose environment the Runtime inherits. Defaults to the caller’s default Space.
profilebooleanNofalse or omitted for ephemeral; true for profile-backed. Defaults to false.
startbooleanNoStart during creation or leave the Runtime stopped. Defaults to true for ephemeral and false for profile-backed.
recordingbooleanNoEnable recording for the Run opened by the Runtime. Defaults to true. Set to false to disable it.
namestringNoHuman-readable label. Defaults to the generated Runtime ID.
metadataRecord<string, unknown>NoCaller-owned metadata stored with the Runtime.
configBrowserRuntimeCreateConfigNoBrowser settings applied when the Runtime starts.

Browser configuration parameters

Pass browser-specific settings in config:

1const runtime = await bctrl.runtimes.create({
2 name: "research-session",
3 config: {
4 headless: true,
5 stealth: "best",
6 proxy: "proxy_123",
7 extensionIds: ["ext_123"],
8 idleTimeoutSeconds: 900,
9 webRtcProxyOnly: true,
10 networkTraffic: {
11 saver: "medium",
12 blockAds: true,
13 },
14 },
15});
ParameterTypeRequiredDescription
headlessbooleanNoWhether the browser runs without a visible window. Defaults to the platform setting.
stealth"normal" | "best" | "experimental"NoBrowser hardening level. Defaults to the platform setting.
proxyRuntimeProxyInputNoSaved proxy, proxy URL, or inline proxy configuration. Omit it on create to use the BCTRL-managed proxy; on update, omission preserves the existing setting. Use { type: "managed-rotating" } to explicitly reset to managed defaults.
fingerprintRuntimeFingerprintCreateConfigNoBrowser and viewport constraints.
extensionIdsstring[]NoExtensions to load at browser start.
idleTimeoutSecondsnumberNoStop the Runtime after inactivity.
autoUpgradebooleanNoUse the latest compatible browser version on start.
webRtcProxyOnlybooleanNoRoute WebRTC through the proxy. Defaults to false.
forceOpenShadowRootsbooleanNoMake closed shadow roots available to automation. Defaults to false.
networkTrafficBrowserNetworkTrafficConfigNoSave bandwidth or block selected traffic.

Network traffic parameters

ParameterTypeRequiredDescription
saver"none" | "light" | "medium" | "high"NoTraffic-saving preset.
blockAdsbooleanNoBlock known advertising requests.
blockTrackersbooleanNoBlock known tracker requests.
blockResourceTypes("media" | "texttrack" | "font" | "image" | "ping" | "prefetch" | "beacon")[]NoResource types to block.
urlAllowliststring[]NoURLs that remain allowed.
urlBlockliststring[]NoURLs that should be blocked.
1type BrowserRuntimeCreateConfig = {
2 autoUpgrade?: boolean;
3 extensionIds?: string[];
4 fingerprint?: {
5 browser?: "chrome";
6 viewport?: {
7 height: number;
8 width: number;
9 };
10 };
11 forceOpenShadowRoots?: boolean;
12 headless?: boolean;
13 idleTimeoutSeconds?: number;
14 networkTraffic?: BrowserNetworkTrafficConfig;
15 proxy?: RuntimeProxyInput;
16 stealth?: "normal" | "best" | "experimental";
17 webRtcProxyOnly?: boolean;
18};

Profile-backed Runtimes retain browser identity. Keep their configuration focused on settings that should apply to every start:

1const runtime = await bctrl.runtimes.create({
2 profile: true,
3 name: "customer-portal",
4 config: {
5 proxy: "proxy_123",
6 idleTimeoutSeconds: 900,
7 },
8});

Use the Stealth browsing cookbook, Load browser extensions cookbook, and Trim network traffic cookbook for complete recipes. This page is the option map; the cookbooks show the combinations.

Next