TestKase
TestKase
|Docs
Automate

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 useAddress
Seleniumhttps://x:<accessKey>@hub.testkase.com/wd/hub
Appium, for phonesThe same address
Playwrightwss://hub.testkase.com/playwright?capabilities=<url-encoded JSON>
Espresso, for Androidhttps://hub.testkase.com/espresso/v1 — a REST API, same access key
XCUITest, for iPhones and iPadshttps://hub.testkase.com/xcuitest/v1 — a REST API, same access key
A setting we don't recognise is dropped in silence. Anything in 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:

RuleWhenWhy it exists
Total time2 hours from the startA ceiling you cannot raise
Going quiet5 minutes with no command from your codeCatches a hung test, or Ctrl+C without quit()
We lose the machine90 seconds with no signal from itThe 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 plans1 to 20 threads. Enterprise can go higher
Free tierNo thread limit. Your free minutes are the only ceiling
Over your limitWaits 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.

On Playwright, your wait can be spent twice. It happens in two steps: first waiting for a matching device, then waiting for the machine holding it. Each step gets the full budget. Six minutes can mean twelve minutes of real waiting before you get an error, so set your CI step's own timeout with that in mind.

Why machines run out

Each machine holds a fixed number of sessions, shared with every other customer:

MachineSessions at once
macOS2. Apple does not allow more than two macOS guests on one host
Linux, which hosts the Windows machinesHowever many slots that machine is set up for
Windows, and anything that has not reported its system1
A phone1

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 withWhat to do
bad capabilitiesSomething is missing or misspelled. Retrying will not help
invalid testkase:options.accessKeyThe key is wrong. Get a new one from Access keys
free-tier minutes exhaustedYour 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 connectedStart your tunnel, or drop the tunnel setting
Multiple local tunnels are connectedYou 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

CodeMeans
429 / 4429You are already using every session your plan allows
402 / 4402No usable plan, or your free minutes are spent
4503We 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 output30 days after the session
Uploaded app builds90 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:options is 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 and singleRunnerInvocation: false are each refused with a 400. Only a single universal .apk is accepted (not .aab or .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 a 400. 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.