Cost control
What a run costs, how the real-cost engine prices it from actual token usage, and how maxCostUsd and CLOUD_MAX_COST_FACTOR enforce a hard stop-loss.
OpenBrowse charges nothing itself. A run's cost is the LLM tokens it consumes at your provider's list prices, plus the per-solve fee of any CAPTCHA sent to CapSolver. The published benchmark puts a full 14-record extraction between $0.22 and $1.62 depending on model and reasoning effort.
How cost is computed
After every step, the run's cost is recomputed from the real token usage the provider reported, priced per model: uncached input, cache reads, cache writes and output are each priced at their own rate, so the figure tracks what your provider bills rather than an estimate. Screenshots, tool schemas, fetched page content and sandbox output are all inside the API-returned token totals, so nothing needs adding on top.
Prompt caching is always on and provider-managed: the system prompt and the latest state message are cache-marked for Anthropic, and OpenAI caches automatically server-side. This is a large part of why like-for-like token counts come out well under the hosted service's; the benchmark's matched pairing (same model, same reasoning) used 3.55x fewer tokens.
Two pricing details the engine gets right that a naive estimate would not:
- OpenAI's
gpt-5.6models have a higher tariff for requests whose prompt exceeds 272,000 tokens; the engine applies the long-context rate exactly when the provider does. - CapSolver solves are priced from the cost field CapSolver itself returns per task, not a flat guess, and are folded into
totalCostUsd.CAPTCHA_MAX_COST_USD(default$0.03) caps what a single run may spend on solving in total, not what one solve may cost; see solving CAPTCHAs.
Costs surface in three places: the session record's llmCostUsd, totalCostUsd and token counts (updated after every step, not just at the end), the per-step costs in the dashboard, and the run exports. Displayed dashboard figures round up to the whole cent, the amount actually charged.
The hard cap: maxCostUsd
const session = await client.sessions.create({
task: "Capture every open vacancy and return the full schema for each.",
model: "gpt-5.6-terra",
reasoningEffort: "none",
maxCostUsd: 3.0,
outputSchema: mySchema,
});maxCostUsd must be a finite number above zero. The cap is checked at the end of every step against the running total; when it is reached the run stops with failureKind budget_exceeded and a completion message of the form Stopped: Cost $3.0121 exceeded budget $3.00. The status is stopped, or idle on a keepAlive session, which stays addressable for follow-ups rather than ending. A caller polling a budgeted keep-alive session for stopped will wait for ever. It is a stop-loss, not a pre-flight reservation: the step that crosses the line completes, so the final figure can exceed the cap by up to one step's cost.
A capped run keeps what it produced
A budget stop resolves its output the same way an ordinary finish does, rather than discarding the work and charging you for nothing. The answer store's contents stand when the store holds them, result.json otherwise, and the run is recorded a success only when that output both validates against the schema and passes the completeness gate. Either way the output is written, so a partial is visible instead of vanishing, and a caller can see what was recovered before deciding whether to escalate.
The salvage never calls the LLM. The budget that ended the run is the same budget schema repair would spend.
One consequence worth knowing: a capped run whose store was complete is recorded successful and still carries failureKind: "budget_exceeded". The two fields answer different questions, so read them together.
On a keep-alive session, the cap is per dispatch
Holding one agent across turns makes maxCostUsd a session-lifetime total, which would let a long conversation slowly strangle itself. Each dispatch therefore tops the pot back up by the allowance the session was created with. A session created with maxCostUsd: 3 that has spent $2.40 runs its next task with a $5.40 ceiling, rounded up to the whole cent.
Naming maxCostUsd on the follow-up itself overrides that for one dispatch, as an absolute ceiling rather than an increment. A session created without a budget stays unbudgeted. The bound is per task, not per conversation.
Scaling caps written for hosted pricing
If your callers were written against Browser Use Cloud, their maxCostUsd values are priced for a service that charges platform fees on top of tokens. CLOUD_MAX_COST_FACTOR scales every incoming cap without touching the clients: set it above 0 and at most 1, and an incoming $6 cap with a factor of 0.5 becomes a local $3 budget. The scaled value is rounded up to the whole cent so a small cap can never collapse to zero, which would read as no budget at all. The session record echoes the local, scaled budget in maxCostUsd.
The variable is validated at startup; an out-of-range or non-numeric value stops the server with a clear error rather than being silently ignored.
What actually moves the bill
In benchmark order of leverage:
- Reasoning effort, on OpenAI models.
gpt-5.6-terraatnonecost $0.24; the same model athighcost $0.66 for the same 14 records. SetreasoningEffortexplicitly; see choosing a model. - Model choice. The spread between the cheapest and dearest full extraction was 7.4x, with no difference in records recovered.
- Prompt scope. A tight prompt finishes in fewer steps, and steps are where tokens go. The 36-step budget run and the 11-step focused run recovered identical data.
- Schema design. Nullable fields and enums let the store settle absent data quickly instead of sending the agent hunting for values the site never publishes.
Token-heavy behaviour inside a run is already managed for you: repeated large tool outputs are deduplicated into back-references, oversized dumps are capped to previews with the data saved to files, and steps that only do store or file work skip the screenshot and DOM re-serialisation entirely.
Concurrency is a cost control too
MAX_CONCURRENT_SESSIONS (default 1) bounds how many runs can spend at once. At the cap a session is still accepted, and its run queues for a slot rather than failing, so a burst of submissions cannot multiply your worst-case spend; it serialises it.
The live view and debugging
Watching a run over VNC, reading the step feed's entry types, following sandbox code in the code tab, and exporting a run as JSON for diagnosis.
Profiles
Keep agents logged in across sessions, and import your existing Browser Use Cloud profiles so profileId references keep working unchanged.