The pilot ran on a laptop for weeks without a hiccup. Then the team handed it the whole supplier list, and by morning the queue was full of timeouts, the proxy bill had jumped and a stack of jobs sat frozen on a sign-in page nobody had watched.
The worst mistakes running browser agents at scale are rarely exotic: reusing browsers, leaving sessions open, sizing workers to the wrong limit, signing in on every run, using stealth everywhere and recording the wrong jobs. Solari runs every agent's browser as a session started by API, and each fix is a setting or a few lines of code on that session. Here are the six, in the order they usually appear.
Reusing a Browser Across Tasks
The earliest mistake is the most tempting, because keeping a browser warm feels faster than starting another. A long-lived headless browser carries the last job's tabs and storage into the next, so a job that passes alone fails when it runs after another. Playwright's guide to browser contexts says the same of tests: starting from scratch means a failure is debugged inside its own run.
The fix is a fresh session per task. Every session option on Solari is opt-in, so launch() returns a clean headless browser with no profile, recording, proxy or stealth unless the job asks for them. A fresh session only helps if the old one goes away, which is the next mistake.
Leaving Sessions Open
Sessions nobody releases are the quiet cost of a fleet. A worker that crashes before cleanup leaves its browser open, and Solari bills browsers per hour while a session is open, so the orphan keeps costing money and keeps holding a slot.
Call browser.close() from a finally block so it runs even when the job throws. Code that uses sessions.create() directly should call releaseAndWait(id), which also has to finish before a replay can be read.
The connection URLs need the same care. A session's cdpEndpoint and wsEndpoint are credentials: anyone holding one can drive the browser until it is released, so they stay out of logs and error reports. Released sessions also free the capacity the next mistake gets wrong.
Sizing Workers to the Wrong Limit
Concurrency is set by the plan, not by the machine running the agent. A worker pool sized to CPU cores will request more browsers than the account allows, and the overflow fails.
The plan limits set the real ceiling. Starter runs 20 concurrent browsers with a separate stealth cap of 10 counted on top, so an extra stealth session gets a 429 even with browser slots free. Size the pool to both caps and retry session creation with exponential backoff, so a burst waits instead of failing.
Session length is a limit too: 5 hours on Starter and 24 hours on Professional. A longer crawl should save its progress and continue in a new session. Once capacity holds, the failures move to the sites themselves, starting with the login.
Signing in on Every Run
Every fresh sign-in is another chance to meet a 2FA prompt or a challenge page, and a fleet signs in far more often than a person does. Solari profiles save a login, its cookies and site data in Playwright's storageState format, and a session started with a profileId opens already signed in.
The trap is the context. A profile seeds only the session's default context, so use session.context or session.newPage(); a context created later starts empty unless session.storageState is applied to it. When a login expires, profiles.edit() returns a link a person opens to sign in again.
A valid login still will not get past every bot defense, which tempts teams into the next mistake.
Turning on Stealth and Proxies Everywhere
Stealth looks like insurance, so teams turn it on for every session and pay for it on every session. Solari's stealth mode makes the browser look like an ordinary person's, but it is slightly slower and bills at a higher per-second rate than the default mode. Start in the default mode and switch the moment challenge pages appear.
Proxies require stealth and bill by traffic, at $4.00 per GB on Professional. A proxy that carries every video and large image burns that budget, so set blockHeavy when the session is created and those requests never cross it. For multi-step logins, a shared proxy.session label keeps related sessions on the same exit IP.
Some runs fail whatever the settings, and the last mistake decides whether anyone can tell why.
Recording Everything, or Nothing
A failed run without a recording leaves a timeout in the logs and little else. Session recording is a flag at launch; after the session closes, getReplayUrl() returns a temporary replay link and downloadReplay() returns a line-by-line log of what happened on the page.
The opposite mistake is recording everything. Recording captures input values by default, so sessions that type passwords or payment details stay unrecorded, or have their replays restricted and purged on a schedule. With all six covered, the fixes fit in a short table.
Choosing the Right Setup
Each mistake has a fix that takes a setting or a few lines of code:

The rule underneath is the same throughout: start clean, release on purpose, plan capacity in code and turn on each extra only where a job needs it. A fleet built that way fails less often, and when it does fail, the replay shows why. The launch overview explains how sandboxes and desktops join browsers in the same account when a job outgrows the browser.
Get Started With Solari
Start with the job that fails most often: run it in a fresh, recorded session with a profile attached and read the replay of its next failure. Solari is built to be the fastest and cheapest place to run that fleet, with browsers ready in 8 ms, and the Free plan includes $3 of monthly credits, so the early runs cost nothing. Create a free Solari account and move your flakiest job over tonight.
