Browser automation cost at scale: the unit economics of headless browsers vs a network API, with a worked cost table from 10K to 1M calls a month.

Below a few hundred calls a month, browser automation cost rounds to nothing: Playwright and Selenium are free, and a spare box or a cheap container runs them. The math only turns against you at volume. Every browser call spins up a Chromium process, loads full pages over the wire, and — if there's an agent driving it — burns LLM round-trips deciding what to click. A network call to the same backend does none of that. This article works through the unit economics, reproduces a cost table from 10,000 to 1,000,000 calls a month, and marks the point where a paid API vendor becomes the cheaper line item.
At low volume, a headless browser's $0 license beats any paid vendor, and you should keep using it. At 10,000+ calls a month the per-call floor of a hosted browser session (~$0.15) and the realistic per-workflow cost (~$1.00) start to dominate, and failed-call retries inflate the real cost per completed action further. That compute bill is what scales against you — which is why, past a certain volume, teams look hard at what they're actually paying to run a browser at all.
| Browser automation | Supergood | |
|---|---|---|
| Cost per call at scale | ~$0.15 hosted-session floor; ~$1.00 for a realistic multi-step workflow | One backend request — none of the per-session compute the browser column pays for |
| Latency per call | Seconds; page loads + LLM planning round-trips | Milliseconds; one network call |
| Compute / memory per call | A full Chromium process — hundreds of MB RAM per session | A single HTTP request; no browser process |
| Bandwidth per call | Full page render: HTML, JS, CSS, images, fonts, trackers | Request + response payload only |
| Maintenance model | You own the selectors and fix them when the UI changes | Maintained for you; a maintenance agent detects backend changes and ships fixes |
| MFA / CAPTCHA handling | You build and babysit it | Automatic — real service-account email + phone per agent |
| Observability | Screenshots, flaky logs, pixel diffs | Full audit logs (request, response, timing, status), structured errors |
| Best for | Testing your own app, one-offs, prototyping, low-volume scraping | Production, high-volume automation against third-party portals |
A browser exists so a human can see a page. When you automate one, you pay for every part of that human-shaped experience even though no human is watching.
A Chromium process, per session. Each headless browser session is a real Chromium process holding a DOM tree, a JavaScript heap, a rendering pipeline, and a network stack — commonly hundreds of MB of RAM per session. You can't pack many onto a box, so concurrency is bounded by memory, and memory is what you rent. This is why hosted-browser vendors price per session-minute rather than per request: the process, not the work, is the unit of cost.
Bandwidth, per page. A network call transfers a request and a response. A browser call transfers an entire page: HTML, JavaScript bundles, CSS, images, fonts, and whatever analytics and ad tags the vendor ships. To submit one form you may download several MB of assets you never look at. That's egress and ingress you pay for on every call.
LLM round-trips, per step. If an agent is driving the browser — a computer-use agent reading screenshots and deciding what to click — each step is a billable model call. The research here is unkind. On real web tasks, agents spend the overwhelming majority of their time not acting but planning: one benchmark found 75–94% of task time went to LLM planning and reflection, with the best of 16 agents still using 1.4–2.7x more steps than a competent human needed (arXiv:2506.16042). A task a person finishes in two minutes can take an agent 20+ minutes of billable steps. If you want the background on why these agents behave the way they do, see what is agentic AI.
Stack these together and you get two useful numbers. The floor — the cheapest a hosted browser session runs when you're not paying an LLM to think — is roughly $0.12–0.24 per session. The realistic figure for a multi-step workflow that logs in, navigates, and submits — with the LLM round-trips and retries that implies — is closer to $1.00–1.50 per completed call. Which number applies to you depends entirely on whether an agent is in the loop, but even the floor is orders of magnitude above a network call. The antibrowser argument is exactly this: you're paying a full page render to do work that is, underneath, a single HTTP request.
Here is the table. Every number below is either a stated assumption or arithmetic on those assumptions — nothing else.
Assumptions. Cheapest hosted browser session: $0.15. Realistic multi-step completed workflow: $1.00/call. No retries included yet — this is the optimistic case for the browser.
| Monthly volume | Browser (floor, $0.15/session) | Browser (realistic, $1.00/call) |
|---|---|---|
| 10,000 | $1,500 | $10,000 |
| 100,000 | $15,000 | $100,000 |
| 1,000,000 | $150,000 | $1,000,000 |
Annualized at 1M calls/month. Browser floor ≈ $1.8M/yr. Browser realistic ≈ $12M/yr.
Read the 1M row both ways. Even in the most generous framing — the bare session floor, no LLM, no retries — you're at $150K a month, $1.8M a year, to click buttons a machine is only clicking because a browser was in the way. In the realistic framing, where an agent actually drives multi-step flows, it's $1M a month. At a million calls a month — a realistic enterprise volume — that's $1M+ a year for the same actions, taking the expensive scenic route to a backend endpoint the browser was talking to all along.
The crossover is the honest part of this table. At a few hundred calls a month, even the realistic column is a few hundred dollars, and a free open-source browser you already run beats a paid vendor with a minimum. At 10,000 calls the floor column is already $1,500/mo, and it only climbs from there. Somewhere between those two rows the license being free stops mattering, because you're no longer paying for the license — you're paying for the compute the license runs on.
The table above is optimistic in two ways that matter more than the per-call rate.
Retries multiply the real cost per completed action. The per-call figures assume calls succeed. On complex multi-step flows they often don't. A recent benchmark reports success rates of 67–85% on simple tasks but only 9–19% on complex multi-step tasks (arXiv:2511.17131). If one in ten complex attempts completes, your true cost per completed action is nearly ten times the per-call rate — a $1.00 workflow becomes ~$10 per success. Retries don't just cost money; the same paper documents "trajectory degradation," where an agent silently submits the wrong record at step 14. That's worse than a failed call, because you pay for it and then pay again to clean it up.
Engineering babysitting is a standing cost. Selectors break on redesigns. Waits get flaky. MFA prompts change shape. Every one of these is an on-call page and an afternoon of an engineer's time, and unlike compute it doesn't show up on the cloud bill — it shows up in headcount and in margin. When a vendor ships a frontend change, browser automation breaks loudly and your team fixes it; a network-layer tool hits the backend, so the frontend redesign is a non-event. This is the deeper reason a portal without a public API is worth automating carefully rather than brute-forcing — see what is an unofficial API for how the network layer stays stable when the UI doesn't.
Here is a realistic Playwright login-and-submit flow — the kind you'd write to post a charge in a portal that has no public API — next to the equivalent Supergood REST call.
Browser automation (Playwright):
const { chromium } = require('playwright');
async function submitCharge(tenantId, amount) {
const browser = await chromium.launch(); // spins up a Chromium process
const context = await browser.newContext();
const page = await context.newPage();
// Log in
await page.goto('https://portal.example.com/login');
await page.fill('#username', process.env.PORTAL_USER);
await page.fill('#password', process.env.PORTAL_PASS);
await page.click('button[type="submit"]');
// MFA: read the one-time code and enter it — you build and babysit this
const code = await fetchMfaCodeFromSomewhere();
await page.fill('#mfa-code', code);
await page.click('#mfa-submit');
await page.waitForNavigation();
// Navigate to the charges screen
await page.goto('https://portal.example.com/tenants/' + tenantId + '/charges');
await page.click('#new-charge');
await page.waitForSelector('#charge-amount'); // selectors break on redesigns
// Fill and submit the form
await page.fill('#charge-amount', String(amount));
await page.click('#save-charge');
await page.waitForSelector('.charge-confirmation'); // hope the click did the right thing
await browser.close();
}Supergood (REST):
# 1. Authenticate once — Supergood handles login, MFA, and CAPTCHAs
curl -X POST https://api.supergood.ai/v1/yardi/auth \
-H "Authorization: Bearer $SUPERGOOD_KEY" -d '{"account": "acme-co"}'
# → { "session": "sg_sess_9f2..." }
# 2. Call the backend action directly (milliseconds, no browser)
curl -X POST https://api.supergood.ai/v1/yardi/charges \
-H "Authorization: Bearer $SUPERGOOD_KEY" \
-d '{"session": "sg_sess_9f2...", "tenant_id": "t_123", "amount": 2150.00}'Both do the same thing: authenticate, then submit a charge. The left column boots a browser, downloads a login page, renders it, drives MFA, waits on selectors that a redesign can invalidate, and downloads a charges page — a full page render per side of the flow. The right column is two POSTs to the same backend those pages were talking to all along. If you use MCP tooling rather than raw REST, npx supergood-mcp init generates the tools for Claude, OpenAI, LangChain, n8n, or Zapier; the underlying call shape is identical. The portal-specific endpoints — for example the Yardi API — are documented in the docs.
This is a genuine trade-off, not a one-sided one, and the honest cases for the browser are real:
Supergood is a paid vendor, and adopting it means a one-time walkthrough of the target portal so the underlying network calls can be captured. That overhead only pays off at production volume — which is the point of the table above. The tool is aimed at teams running high-volume, high-value automation against third-party portals, not at someone scripting a login for the weekend. If your automation is small, cheap, and against an app you control, browser automation is the correct and cheaper answer.
How much does browser automation cost at scale? It's dominated by per-session compute, not license. At a hosted-session floor of ~$0.15 and a realistic multi-step figure of ~$1.00 per completed call, 1,000,000 calls a month runs roughly $150,000/mo (floor) to $1,000,000/mo (realistic) — about $1.8M to $12M annualized, before retries. Those are the stated-assumption figures from the table above.
How much does a headless browser session cost? The cheapest hosted browser infrastructure runs around $0.12–0.24 per session, because each session is a full Chromium process consuming hundreds of MB of RAM. A realistic multi-step workflow with an agent in the loop is closer to $1.00–1.50 per completed call once LLM planning round-trips are counted.
Is it cheaper to build my own scraper or use an API vendor? At low volume, build your own — the license is free and the compute is trivial. At scale, the picture flips: per-session compute plus retries plus engineering babysitting (selectors, waits, MFA) add up faster than a maintained API. The crossover in the worked table sits well below 10,000 calls a month for realistic workflows.
Why do failed calls make browser automation more expensive? You pay per attempt, not per success. When complex multi-step success rates fall to 9–19% (arXiv:2511.17131), most attempts fail and get retried, so the real cost per completed action is several times the per-call rate — and silent wrong-submissions cost extra to detect and fix.
Does a network-layer API break when the portal is redesigned? A frontend redesign changes selectors and layout, which breaks browser automation. A network-layer tool hits the backend, so a UI redesign is a non-event; Supergood's maintenance agent watches telemetry and ships fixes for backend API changes before customers notice. See MCP for software without a public API for how those tools are generated and maintained.
If you're past 10,000 calls a month and the browser column is the one you're paying, it's worth pricing the network-layer alternative against your own volume. Supergood generates and maintains REST and MCP APIs for enterprise software that has no public API — same backend, without the page render. The docs show how a workflow is recorded once and turned into deployed endpoints.