Limits & Billing
Billing model, rate limits, idle timeout, and known limitations
Billing
Browser API sessions are billed at 1 credit per 2 minutes, rounded up. A session that lasts 3 minutes costs 2 credits. A session that lasts 4 minutes 1 second also costs 2 credits (you're billed at the start of each 2-minute window).
| Rate | 1 credit / 2 min |
| First credit | Charged on connect (covers minutes 0-2) |
| Subsequent credits | Charged at the start of each new 2-minute window |
| Recording | Free — included in the per-minute rate |
| Geo-targeting | Free — no per-country surcharge |
| Saved-session load | Free — no extra charge for loading cookies |
| Auto-disconnect | When your credit balance reaches 0 |
Limits
| Parameter | Value | Notes |
|---|---|---|
| Max session duration | 2 hours | Hard cap; session ends automatically |
| Idle timeout | 120 seconds | No CDP messages from client → disconnect |
| Max message size | 50 MB | Per CDP frame |
| Concurrent connections | per-account plan limit | See pricing |
| Authentication | X-API-Key header or ?api_key= query param | Header preferred; query param needed for clients that can't set custom WS headers |
Avoiding the idle timeout
The connection is closed if your script is silent for 120 seconds. Long workflow pauses (MFA wait, slow API polls, OAuth callbacks) need a keepalive — call any cheap browser API every ~60 seconds:
import asyncio
# during a long wait...
while waiting_for_mfa():
await page.evaluate("() => 0") # cheap keepalive
await asyncio.sleep(60)Playwright's page.wait_for_function() and page.wait_for_selector() also keep the session alive while they're polling — preferred for any "wait until X appears" loop.
The cleanest practice is browser.close() as soon as you're done — don't leave idle connections open just because you can.
Not supported
- Selenium / ChromeDriver — only CDP-native clients (Playwright, Puppeteer, chromedp) are supported.
Error responses
Browser API errors come back as standard HTTP responses before the WebSocket upgrade, so your CDP client receives them as connection failures:
| Status | Error | Cause |
|---|---|---|
| 401 | unauthorized | Missing or invalid X-API-Key |
| 402 | insufficient credits | Credit balance is 0 |
| 404 | session not found | ?session_id / ?session_name doesn't resolve |
| 409 | session is being automated | The session you're loading is in use by another job |
| 422 | session has no stored data | Session was created but never saved |
| 429 | Rate-limited | Too many active connections for this account |
| 503 | browser service unavailable | Transient — retry with backoff |
| 503 | session saving not configured | Saved sessions temporarily unavailable (contact support) |