Reference
The rules that are the same however you connect — timeouts, limits, errors, and how long we keep things.
The things that apply to every Automate session, whether you use Selenium, Playwright, Appium, Espresso or XCUITest.
Looking for the list of capabilities? Each connection has its own, because they differ:
Selenium · Playwright · Mobile · Espresso · XCUITest
Where you connect
| You use | Address |
|---|---|
| Selenium | https://x:<accessKey>@hub.testkase.com/wd/hub |
| Appium, for phones | The same address |
| Playwright | wss://hub.testkase.com/playwright?capabilities=<url-encoded JSON> |
| Espresso, for Android | https://hub.testkase.com/espresso/v1 — a REST API, same access key |
| XCUITest, for iPhones and iPads | https://hub.testkase.com/xcuitest/v1 — a REST API, same access key |
testkase:options that we do not read is discarded. No error, no warning, and the session starts normally. So a typo like recordng: true reads as "it ran, but the setting did nothing". If a setting seems to have no effect, check its spelling first.What ends a session
Three rules end one automatically, whatever you are testing:
| Rule | When | Why it exists |
|---|---|---|
| Total time | 2 hours from the start | A ceiling you cannot raise |
| Going quiet | 5 minutes with no command from your code | Catches a hung test, or Ctrl+C without quit() |
| We lose the machine | 90 seconds with no signal from it | The machine dropped off the network or crashed |
Only the middle one is yours to change, with idleTimeout. You can take it up to 20 minutes.
The other two are the same on every plan. There is no setting to extend the 2-hour ceiling — a long run has to be split across workers.
Espresso and XCUITest have no idle timeout. Their tests run on the device and send us no commands, so there is nothing to go quiet. Only the 2-hour ceiling applies, and a build's runTimeout can set a lower one — see how long a run may take for Espresso and XCUITest.
How many sessions at once
Your plan's threads decide it. One session uses one thread.
| Limit | |
|---|---|
| Paid plans | 1 to 20 threads. Enterprise can go higher |
| Free tier | No thread limit. Your free minutes are the only ceiling |
| Over your limit | Waits for one of your threads, then refuses if none frees up |
Going over your limit does not fail straight away. The session waits for one
of your own threads to come free, and only refuses if none does inside your
maxQueueWaitSeconds. That refusal is 429 over HTTP, or close code 4429
on Playwright, and it says how long it waited for.
Both waits come out of the same budget: time spent waiting for a thread is time not left for waiting for a machine.
Size your CI worker count to your threads anyway — waiting is slower than sizing the run correctly, and a queued worker still finishes later than one that never had to queue.
Waiting for a machine
Being under your own limit does not mean a machine is free. Ours are shared, and you wait when every machine matching your request is busy.
maxQueueWaitSeconds sets how long you will wait. Five minutes by default, up to nine — except on Selenium, where the default is 2 minutes 50 because Selenium's own client gives up at 3 minutes. Every connection reads it — Selenium, Playwright and Appium alike.
Waiting is not billed. Charging starts when you get a machine.
Why machines run out
Each machine holds a fixed number of sessions, shared with every other customer:
| Machine | Sessions at once |
|---|---|
| macOS | 2. Apple does not allow more than two macOS guests on one host |
| Linux, which hosts the Windows machines | However many slots that machine is set up for |
| Windows, and anything that has not reported its system | 1 |
| A phone | 1 |
Three things follow from that:
Asking for one specific system narrows you. A named macOS version only exists on the machines carrying that image, and each holds two sessions.
A session holds its machine until it has fully ended. Run twice in a row against the same narrow target and the second waits for the first.
A mix parallelises better than a pile. Chrome, Edge and Firefox across two systems draw on far more machines than the same number of workers all asking for one combination.
These numbers describe our machines today, not your plan. They change as machines are added.
Free minutes
Every account gets 15 free minutes, once.
They do not reset. They belong to the owner's email address, not the organisation — so deleting an organisation and making a new one does not hand you a fresh 15.
A paid plan removes the minute cap, but per product. A Live plan does not lift the Automate cap.
When something is refused
The message tells you which of these it is. Match on the start of it:
| The message starts with | What to do |
|---|---|
bad capabilities | Something is missing or misspelled. Retrying will not help |
invalid testkase:options.accessKey | The key is wrong. Get a new one from Access keys |
free-tier minutes exhausted | Your 15 free minutes are gone. Retrying will not help |
No device matches… | We do not have that combination. The message lists what we do have |
All matching devices… | Everything matching you was busy. Retry, use fewer workers, or wait longer |
Couldn't start the browser… | A real launch failure. Retry, and tell us if it keeps happening |
Couldn't reach the browser host… | The machine went quiet. Retry — it usually comes back within a minute |
Local tunnel … is not connected | Start your tunnel, or drop the tunnel setting |
Multiple local tunnels are connected | You have more than one. Name the one you want |
Your Playwright client is X.Y… | Your Playwright is too old or too new for us |
Codes you can branch on in CI
| Code | Means |
|---|---|
429 / 4429 | You are already using every session your plan allows |
402 / 4402 | No usable plan, or your free minutes are spent |
4503 | We could not check your plan. This is us, not you — retry |
4402 is a statement about your account. 4503 admits we could not check. Retrying helps with the second, not the first.
Screen size
Browsers only. testkase:options.resolution takes one of twelve sizes:
1024x768 · 1280x720 · 1280x800 · 1366x768 · 1440x900 · 1600x900 · 1920x1080 (default) · 1920x1200 · 2560x1080 · 2560x1440 · 3440x1440 · 3840x2160
Anything else is refused. On Windows, anything above 2560×2048 is refused too, so 2560x1440 is the Windows ceiling.
Phones have the screen they have. There is nothing to set.
How long we keep things
| Kept for | |
|---|---|
| Videos, logs and test output | 30 days after the session |
| Uploaded app builds | 90 days after upload |
Deleting the files does not delete the session. Runs stay listed with their result, timing and device, which is why Test history reaches back further than 30 days.
There is no longer-retention plan.
Known limits
- Safari keeps no console or network logs. Apple's driver gives us no way to read them.
- Browser network logs are not HAR files. Only mobile produces a real HAR.
- Testing a site on your own machine needs the tunnel client. It works for browsers. A phone reaches your machine a different way — see Local testing.
testkase:optionsis deliberately small. The proxy and location settings other services ship are not all mirrored.- On iOS, no crash reports. You get the video and the device log.
- Espresso is Android only, and some options are not available yet. Sharding (
shards), Android Test Orchestrator (useOrchestrator,clearPackageData), network logs, Local Tunnel, biometric simulation, camera image injection andsingleRunnerInvocation: falseare each refused with a400. Only a single universal.apkis accepted (not.aabor.apks), there is no upload by URL, and there is no Live view of an Espresso session. See Not available yet. - XCUITest runs on real iPhones and iPads only, re-signed with our certificate. Bundle ids are kept, but push notifications, App Groups, iCloud, universal links and other special entitlements are removed, so features that need them don't work. Sharding, Xcode test plans,
.xctestproducts, network logs, Local Tunnel, biometric simulation and camera image injection are each refused with a400. There is no upload by URL, archives that need zip64 are refused, per-test video arrives after the run, and there is no Live view of an XCUITest session. See XCUITest on real devices.
Questions
▶Does a sleep count as going quiet?
Yes. We measure the gap between commands, and a sleep sends none.
If your test needs a long pause, send something cheap like getCurrentUrl() to reset the clock. Or raise idleTimeout, up to 20 minutes.
Enforcement is approximate. The check runs on an interval, so a session ends shortly after the limit rather than exactly on it. Anything already uploaded is kept.
▶Why didn't my screen size apply?
Two reasons, both on Windows.
The value is accepted and recorded, but the Windows machines do not apply it yet. They keep their built-in size until those images are rebuilt.
Also, resolution sets the screen, not your page. On Playwright, set viewport: null as well so the page fills the window. Anything you set yourself — in playwright.config.ts, test.use() or newContext() — always wins over ours.
▶Am I billed while waiting for a machine?
No. Charging starts when you get one.
Your free minutes are checked before you join the queue, so waiting never gets you past billing.
Waiting for one of your own threads is not billed either — nothing is running yet.
▶How is a machine's capacity counted?
Across everything, not per product. Any session that has not ended counts against the machine holding it, including Live sessions.
So on a machine that hosts both phones and browsers, two phone sessions can make every browser on it unavailable until one ends. It does not work the other way round: a browser session never blocks a phone.
