BLOG
Browser-Hours Once: How Session Time Is Metered
Browser-hours once explained: how hosted Chromium meters agent session time, what counts toward it, and how to budget it for production.
# Browser-Hours Once: How Session Time Is Metered
A browser-hours once question usually means one of two things: how a single browser-hour is counted, or what happens when a session runs once and then stops. Both matter when you run AI agents against hosted Chromium, because the meter is the difference between a predictable bill and a surprise invoice. This guide explains how browser-hours are measured, which parts of an agent run consume them, and how to design workloads so you pay for work, not idle time. It also covers where Remote Browser fits and how to check current rates on the pricing page.
The short version: a browser-hour is one hosted browser session running for sixty minutes. A session that starts, does its work, and stops cleanly is billed for the wall-clock time it existed, not the number of actions it took. Everything below is about controlling that wall-clock window.
What a browser-hour actually measures
Hosted browser providers meter on session duration. When you call the API to create a browser, the clock starts. When you stop it, or when it hits a configured timeout, the clock stops. The unit is usually billed in seconds and aggregated into hours, so a 90-second task costs roughly 0.025 browser-hours, not a full hour.
That model has three consequences worth internalizing:
- Idle time is billable. A session waiting on an LLM to decide its next click is still a running Chromium process. If your agent thinks for 40 seconds between actions, you pay for those 40 seconds.
- Concurrency multiplies the meter. Ten parallel sessions for six minutes each is one browser-hour total, but ten parallel sessions for six hours each is sixty. Parallelism is a throughput lever and a cost lever at the same time.
- Cleanup is part of the cost. Sessions that are never explicitly stopped rely on provider-side timeouts. If your worker crashes and the session lingers, the meter keeps running until the timeout fires.
Providers differ in how they round and what they include. Some bill per-second with a minimum, some round up to the minute. Check the specifics before you model costs; Remote Browser publishes current terms on /pricing.
The lifecycle of a single session
Understanding the phases of one session makes the meter legible. A typical agent run looks like this:
- Provision. The API call returns a session with a CDP endpoint. Provisioning latency varies by provider and is usually not billed separately, but the session clock may start at creation rather than at first connection.
- Connect. Your Playwright, Puppeteer, or Selenium client attaches over CDP. This is fast, but it is not free in wall-clock terms.
- Work. The agent navigates, reads the DOM, clicks, types, and waits. This is where most of the time goes, and where most of the waste hides.
- Teardown. You close the browser or call the stop endpoint. The session ends and the meter stops.
The "once" in browser-hours once is the teardown step. A session that is created once, used once, and stopped once is the cleanest billing shape. Long-lived sessions that stay open across many tasks are convenient for stateful workflows but accumulate hours whether or not the agent is doing anything.
If you need persistent state, use persistent profiles rather than keeping a browser open. A profile stores cookies and storage state so a new session can resume where the last one left off, and you only pay for the sessions that actually run.
What counts toward the meter
Not every second of a session is equally productive. Here is how the common phases break down:
| Phase | Billable? | Typical share of a run | Notes |
|---|---|---|---|
| Session provisioning | Usually yes (clock starts at creation) | 1–5% | Varies by provider; check docs |
| CDP connect | Yes | <1% | Negligible if you connect once |
| Navigation and page load | Yes | 20–40% | Network-bound; caching helps |
| LLM reasoning between actions | Yes | 20–50% | The biggest hidden cost for agent loops |
| Waiting on selectors or timeouts | Yes | Variable | Fixed sleeps are pure waste |
| Screenshot and DOM extraction | Yes | 5–15% | Large payloads slow the loop |
| Teardown | Yes, until stop completes | <1% | Always stop explicitly |
| Provider-side timeout after crash | Yes | Up to the timeout limit | The most expensive failure mode |
The two rows that deserve attention are LLM reasoning and timeout-after-crash. Both are cases where the browser is running but nothing is happening in it.
Reducing reasoning time inside the session
The cleanest fix is to move reasoning outside the session window. Have the agent plan the next batch of actions, then execute them in one connected burst. Instead of connect → think → click → think → click, do connect → execute five steps → disconnect. Each think cycle then happens while no browser is running.
This is a design change, not a provider feature. It works with any hosted runtime, including Remote Browser, and it typically cuts browser-hours per task by a meaningful margin because the dominant cost in agent loops is often the model, not the page.
Avoiding timeout-after-crash
Always stop sessions in a finally block or equivalent. If your worker dies, the provider's timeout is your only backstop, and that timeout is usually generous. Set the shortest session timeout your workload can tolerate, and treat the stop call as mandatory cleanup.
import { chromium, Browser, Page } from "playwright";
interface SessionHandle {
cdpUrl: string;
stop: () => Promise<void>;
}
// Replace with your provider's session-creation call.
declare function createSession(timeoutSeconds: number): Promise<SessionHandle>;
async function runTask(url: string): Promise<string> {
const session = await createSession(120); // short timeout = cheap failure
let browser: Browser | undefined;
try {
browser = await chromium.connectOverCDP(session.cdpUrl);
const context = browser.contexts()[0] ?? (await browser.newContext());
const page: Page = context.pages()[0] ?? (await context.newPage());
await page.goto(url, { waitUntil: "domcontentloaded", timeout: 30_000 });
await page.waitForSelector("main", { timeout: 10_000 });
// Batch extraction in one round trip instead of many small calls.
return await page.evaluate(() => document.body.innerText.slice(0, 5_000));
} finally {
// Stop the browser before the session so the meter ends promptly.
await browser?.close().catch(() => {});
await session.stop().catch(() => {});
}
}The finally block is the whole point. It guarantees the meter stops even when the task throws, and it stops the browser before the session so the provider sees a clean teardown rather than a timeout.
Browser-hours once vs. always-on sessions
The phrase "browser-hours once" contrasts with always-on browser infrastructure. The trade-off is straightforward:
- Once-per-task sessions cost less per unit of work, isolate failures, and scale horizontally. The cost is state management: you need profiles or external storage to carry context between runs.
- Always-on sessions are simpler for stateful workflows and long-running agents that need to stay logged in. The cost is that idle hours are billable hours, and a stuck agent can burn a full day of budget without producing anything.
For most AI agent workloads, once-per-task is the right default. Reserve long-lived sessions for cases where the workflow genuinely requires a live browser between steps, such as interactive approval flows or real-time monitoring. Even then, set an aggressive timeout and a watchdog that stops the session when the agent goes quiet.
Choosing a runtime with a predictable meter
Pricing models across hosted browser providers fall into a few shapes: per browser-hour with a subscription floor, per browser-hour with prepaid credits, and per-request or per-action metering. Each has different failure modes.
| Model | Predictable when | Risky when |
|---|---|---|
| Subscription + overage | Volume is steady and known | Bursty workloads pay for idle capacity |
| Prepaid credits, per-hour | Usage is spiky and you want a hard cap | Credits expire or minimums apply |
| Per-request / per-action | Tasks are short and uniform | Long agent loops with many small actions |
| Self-hosted | You have ops capacity and steady load | You underestimate maintenance and scaling |
Remote Browser uses session-based metering with usage controls, so you can cap concurrency and session length rather than discovering the bill after the fact. The documentation covers session creation, CDP endpoints, and stop semantics. For a broader look at how hosted runtimes compare for agent workloads, see Remote Browser for AI agents.
If you are evaluating providers, ask three questions before you commit:
- When does the clock start? At API creation or at first CDP connection? The difference matters for slow-provisioning providers.
- What is the default session timeout? A long default is a hidden cost multiplier for crashed workers.
- Is there a hard concurrency cap you control? Unbounded concurrency is unbounded spend.
Practical budgeting for agent workloads
A rough model helps you sanity-check a workload before you ship it. Estimate:
- Actions per task. Count the navigation, click, and extraction steps your agent typically performs.
- Seconds per action. Include model latency, not just page latency. This is usually the dominant term.
- Session overhead. Provisioning, connect, and teardown, typically a few seconds.
- Failure rate. Retries multiply browser-hours. A 20% retry rate is a 20% cost increase.
Multiply actions by seconds per action, add overhead, and divide by 3,600 to get browser-hours per task. Multiply by task volume and by your rate to get a monthly estimate. Then add a buffer for retries and stuck sessions.
Two optimizations consistently pay off:
- Batch actions per connection. Fewer connect/disconnect cycles and fewer model round trips inside the session window.
- Replace fixed sleeps with event waits.
waitForSelectorandwaitForResponsereturn as soon as the condition is met;waitForTimeoutalways burns the full duration.
For a deeper look at running Chromium without local setup, see Remote Browser online and remote web browser. If you are driving sessions interactively during development, remote control browser covers the live viewer workflow.
Where the meter meets the protocol
Browser-hours are a billing abstraction over a real process. The Chrome DevTools Protocol is what actually connects your client to that process, and the CDP documentation is the authoritative reference for what you can do once connected. Playwright's connectOverCDP is the standard entry point for TypeScript and Python clients.
Because the meter tracks the process, anything that keeps the process alive keeps the meter running. That includes:
- Open WebSocket connections that never close
- Pages with pending network requests that block teardown
- Background tabs the agent opened and forgot
- Service workers or extensions holding the browser open
Closing the browser context and then the browser is usually enough. If a page hangs, browser.close() with a timeout, followed by the provider's stop call, is the reliable pattern.
Summary
A browser-hour is one hosted session running for sixty minutes, billed on wall-clock time from creation to stop. The "once" pattern — create once, work once, stop once — is the cheapest and most predictable shape for AI agent workloads. The biggest cost drivers are model reasoning inside the session window, fixed sleeps, and sessions that outlive their workers.
Design for short sessions, batch actions per connection, stop in finally, and set timeouts you can afford. Then check current rates and limits on /pricing and wire your client against the documentation so the meter stops when the work does.