← Blog

BLOG

Billable Browser-Hours: What You Actually Pay For

Billable browser-hours explained: how hosted Chromium meters agent time, what counts toward the meter, and how to cut waste in production.

October 18, 20269 min readRemote Browser

# Billable Browser-Hours: What You Actually Pay For

A billable browser-hour is one hosted browser session running for sixty minutes of wall-clock time, rounded or prorated by the provider's policy. Billable browser-hours sound trivial until you run agents in production and discover that most of your spend is not the work — it is the idle time between steps, the retries after a failed selector, and the sessions nobody closed. Understanding billable browser-hours is the difference between a predictable line item and a bill that doubles when a model gets slower. This guide covers how the meter works, what counts toward it, and how to design agent loops that spend browser-hours on tasks instead of waiting.

If you are still choosing a runtime, read remote browsers for AI agents first. This post assumes you have one and want to control cost.

How a browser-hour is actually counted

Hosted browser providers meter the lifetime of a session, not the number of actions inside it. The clock starts when the session is created and stops when it is released. Everything in between — page loads, LLM inference between tool calls, human review in a live viewer, retry backoff — is billable.

That has three consequences worth internalizing:

  • Model latency is browser cost. If your agent takes 40 seconds to decide the next click, the browser sits open for those 40 seconds. A slower model is a more expensive agent even at identical token prices.
  • Idle sessions are the silent leak. A crashed worker that never calls the stop endpoint leaves a session running until a provider-side timeout fires. Multiply that by a fleet and it becomes real money.
  • Concurrency and duration are separate axes. Ten sessions for one minute each and one session for ten minutes each are the same number of browser-hours but very different infrastructure loads. Providers price and limit them differently.

Most providers publish a per-hour rate and a monthly plan with included hours. Remote Browser publishes current rates and included usage on the pricing page; check there rather than relying on numbers in a blog post, since plans change.

What the meter typically includes

ComponentUsually billableNotes
Session wall-clock timeYesFrom create to release
Page loads and navigationYesAlready inside session time
LLM/tool-call latency between actionsYesThe browser is open and reserved
Live viewer attachedYesSame session, same clock
Retry backoff and error handlingYesOften the largest hidden cost
Persistent profile storageSometimesMay be metered separately
Proxy bandwidthSometimesOften a separate line item
Queued-but-not-started sessionsRarelyConfirm with the provider

The practical takeaway: anything that keeps a session alive without doing work is a cost you can engineer away.

Why browser-hours, not requests or tokens

Per-request pricing fits stateless APIs. Browser automation is stateful — a login, a multi-step checkout, a paginated scrape all depend on the session surviving between calls. Metering by time is the honest unit because the provider is holding a real Chromium process, memory, and often an egress IP for you the whole time.

Token pricing does not capture this. An agent that loads a heavy SPA and then thinks for two minutes consumes almost no tokens but occupies a browser slot. Conversely, a fast agent doing many DOM reads on one page is cheap in browser-hours and expensive in tokens. The two meters measure different things, and a production budget needs both.

This is also why "free tier" comparisons mislead. A plan with generous included hours but slow session startup pushes you toward longer-lived sessions to amortize cold starts — which increases billable time. Session startup latency is a cost input, not just a UX detail.

The cost model, written out

A rough monthly estimate:

monthly_browser_hours ≈ tasks_per_day × avg_session_minutes × 30 / 60 × (1 + retry_rate)

Plug in your own numbers. The variable that surprises teams is retry_rate. If 15% of agent runs fail on a flaky selector and retry from scratch, you are paying 15% overhead on every task, forever, until you fix the selector. Instrumenting retries is usually a bigger cost win than negotiating a rate.

Two more multipliers:

  • Cold-start padding. If sessions take several seconds to become CDP-ready and your code retries the connection, that padding is billable. Connect once, wait for the target, then act.
  • Parallel fan-out. Running 20 sessions to scrape 20 pages in parallel costs the same browser-hours as sequential runs but finishes 20x faster. Wall-clock time and browser-hours are not the same optimization target.

Cutting billable time without cutting capability

The highest-leverage changes are architectural, not pricing negotiations.

Close sessions deterministically. Wrap every session in try/finally and call the stop endpoint in the finally. Do not rely on provider timeouts. A leaked session is pure waste.

Separate reasoning from browsing. If your agent plans for 30 seconds between actions, either run the plan before opening the browser or accept that the plan is billable. Some teams pre-compute a task plan, open the session, execute the plan, and close — collapsing a 10-minute session into 90 seconds.

Reuse profiles instead of re-authenticating. Persistent profiles let a session start already logged in. Re-authenticating on every run adds page loads and often a CAPTCHA round-trip, both billable. See the documentation for profile lifecycle.

Fail fast on selectors. A 30-second timeout on a missing element costs 30 billable seconds. Use short timeouts with explicit waits on the specific condition you need, and let the agent see the failure quickly.

Batch work per session. If ten tasks hit the same site with the same login, one session doing ten tasks is cheaper than ten sessions doing one each — provided the tasks do not need isolation. Isolation is a real requirement for multi-tenant workloads; do not trade it away for cost without thinking.

Watch the viewer. A live viewer is invaluable for debugging, but leaving it attached to a long-running session does not reduce cost — the session was already billable. The waste is human attention, not browser-hours. Close sessions when debugging is done.

A quick comparison of metering models

ModelUnitPredictable?PunishesRewards
Per browser-hourSession timeYes, if sessions are shortIdle time, slow modelsFast, deterministic agents
Per request/actionAPI callsModerateChatty agentsBatched operations
Per tokenModel usageNo (varies by task)Verbose reasoningConcise agents
Flat subscriptionSeat/monthYesNothingSteady, high-volume use

Most production teams end up on a hybrid: a subscription or committed plan for baseline load plus per-hour overage for spikes. Remote Browser's current structure is on /pricing.

Implementation: measuring your own browser-hour burn

You cannot optimize what you do not measure. The snippet below connects to a hosted Chromium session over CDP, times the session, and logs the duration alongside the task outcome. It uses Playwright's connectOverCDP, which is the standard way to attach to a remote browser — see the Playwright CDP documentation for the full API.

import { chromium, Browser, Page } from 'playwright';

interface SessionResult {
  taskId: string;
  outcome: 'success' | 'failure';
  durationMs: number;
  billableMinutes: number;
}

async function runTask(
  taskId: string,
  cdpEndpoint: string,
  stopSession: (id: string) => Promise<void>,
  sessionId: string,
  work: (page: Page) => Promise<void>,
): Promise<SessionResult> {
  const startedAt = Date.now();
  let browser: Browser | undefined;
  let outcome: 'success' | 'failure' = 'failure';

  try {
    browser = await chromium.connectOverCDP(cdpEndpoint);
    const context = browser.contexts()[0] ?? (await browser.newContext());
    const page = context.pages()[0] ?? (await context.newPage());

    await work(page);
    outcome = 'success';
  } catch (err) {
    console.error(`task ${taskId} failed`, err);
  } finally {
    // Disconnect the CDP client; this does not stop the hosted session.
    await browser?.close().catch(() => {});

    // Always release the session so the meter stops.
    await stopSession(sessionId).catch((e) =>
      console.error(`failed to stop session ${sessionId}`, e),
    );

    const durationMs = Date.now() - startedAt;
    return {
      taskId,
      outcome,
      durationMs,
      billableMinutes: Math.ceil(durationMs / 60_000),
    };
  }
}

Two details matter here. First, browser.close() on a CDP connection disconnects your client; it does not necessarily terminate the remote browser. You must call the provider's stop endpoint explicitly. Second, rounding to the minute is illustrative — check your provider's actual rounding policy, because some round up per session and some prorate by the second.

Log durationMs and outcome to your observability stack. After a week you will see which task types dominate spend and which fail often enough to warrant a fix.

Production criteria beyond the rate

When comparing providers on browser-hours, the headline rate is one input. Ask:

  • What is the rounding policy? Per-second proration favors short tasks; per-minute rounding penalizes them.
  • What is the session startup time? Cold starts are billable if your code waits on them.
  • Is there a hard session timeout? A provider that kills sessions at, say, 30 minutes protects you from runaway cost but may interrupt long tasks.
  • How are profiles and proxies metered? Storage and egress can be separate line items.
  • Can you cap concurrency? A per-account concurrency limit is a cost control, not just a scaling limit.
  • What happens on worker crash? Does the session linger, or is there a heartbeat that releases it?

Remote Browser exposes session lifecycle controls and configurable browser settings; the specifics are in the documentation. The point is to read the metering contract, not just the price.

Common ways teams overpay

  • Retrying the whole task on a single failed step. Fix the step, not the retry.
  • Holding a session open for human review. If a human needs to inspect, do it in a separate short session or use recordings.
  • Running a browser for work that needs no browser. Fetching a JSON API through Chromium is the most expensive way to make an HTTP request.
  • Ignoring cold starts in benchmarks. A provider that starts sessions faster may cost less per completed task even at a higher hourly rate.
  • Not separating dev and prod sessions. Debug sessions with attached viewers and long timeouts should not share a budget with production traffic.

Where this leaves you

Billable browser-hours are a clean unit once you accept that the meter runs on wall-clock time. The work is in keeping sessions short, closing them deterministically, and measuring duration per task so you can see where the time goes. Start with the try/finally pattern above, log durations for a week, and fix the top two sources of waste before you renegotiate anything. For the runtime itself, see remote browser online and remote web browser, and check /pricing for current rates.