Your Appium tests run perfectly on your laptop. Your Maestro flows work flawlessly on the phone at your desk. Everything passes.

Then you try to run them on a cloud device lab.

Suddenly you need API keys. Special capabilities. Their URLs. Their SDK. Their upload process. Your code that worked perfectly now needs modifications just to run on someone else’s infrastructure.

Why?

The Cloud Device Lab Bargain

Every cloud device lab makes the same implicit deal:

“Give us your test code, your app binary, and your test data. We’ll run it on our devices. Trust us.”

To accept this deal, you adapt:

Your code changes:

java
// Before: Works locally
caps.setCapability("app", "./app.apk");
driver = new AndroidDriver(new URL("http://localhost:4723"), caps);

// After: Adapted for their platform
caps.setCapability("cloud.user", "USERNAME");
caps.setCapability("cloud.key", "API_KEY");
caps.setCapability("cloud.app", "cloud://uploaded-app-hash");
caps.setCapability("cloud.device", "Samsung Galaxy S23");
caps.setCapability("cloud.region", "us-west-1");
driver = new AndroidDriver(new URL("https://their-cloud-url/wd/hub"), caps);

Your workflow changes:

  1. Upload APK to their servers
  2. Wait for processing
  3. Configure their specific capabilities
  4. Debug through their logs
  5. Trust their security

Your data moves:

  • Your APK: on their servers
  • Your test data: on their infrastructure
  • Your screenshots: in their cloud
  • Your credentials: in their logs

This is the price of convenience.


The Question Nobody Asks

Here’s what’s strange: your local setup already works.

  • Your machine connects to your phone
  • Your tests run against your app
  • Results stay on your machine
  • No API keys, no uploads, no trust required

The only thing missing is more devices and remote access.

So why does getting more devices require rebuilding everything?


What If It Didn’t?

Imagine this:

bash
# Your tests, your devices, your network
# Nothing changes except which device runs the test

For Maestro:

bash
# Local
maestro test flow.yaml

# Remote (your devices, anywhere)
curl -fsSL https://app.devicelab.dev/test-node/KEY | sh -s -- \
  --framework maestro \
  --app ./app.apk \
  --tests ./flows/

Same YAML. Same flow. Different device.

For Appium:

java
// Local
caps.setCapability("app", "./app.apk");
driver = new AndroidDriver(new URL("http://localhost:4723"), caps);

// Remote (remove ONE line)
// caps.setCapability("app", "./app.apk");  // DELETE - DeviceLab handles it
driver = new AndroidDriver(new URL("http://localhost:4723"), caps);

Then run:

bash
curl -fsSL https://app.devicelab.dev/test-node/KEY | sh -s -- \
  --framework appium \
  --app ./app.apk

Same test code. Same localhost URL. The tunnel handles the rest.


The Architecture That Makes This Possible

Cloud device labs work like this:

┌──────────────┐     ┌──────────────────┐     ┌──────────────┐
│  Your Tests  │────▶│  Their Cloud     │────▶│ Their Devices│
│              │     │  (sees everything)│    │ (shared)     │
└──────────────┘     └──────────────────┘     └──────────────┘
                            │
                     Your data lives here

Your code, your APK, your test data—all passing through infrastructure you don’t control.

DeviceLab works differently:

┌──────────────┐                              ┌──────────────┐
│  Your Tests  │◀────── WebRTC P2P ──────────▶│ Your Devices │
│  (your machine)                             │(your network)│
└──────────────┘                              └──────────────┘
         │                                            │
         └────────────── Your Network ────────────────┘

       DeviceLab sees: connection metadata only
       DeviceLab never sees: your app, tests, data

Peer-to-peer. Your tests talk directly to your devices. We route the connection; we never see the content.


“We Promise Not to Look” vs “We Can’t Look”

Every cloud provider has security policies. They promise:

  • “Your data is encrypted”
  • “We don’t access your content”
  • “Your tests are isolated”

These are policy promises. Someone could look if they chose to.

DeviceLab makes an architectural promise:

We can’t look because we never receive your data.

What Cloud Labs DeviceLab
Your APK Uploaded to their servers Stays on your network
Your test data Passes through their infra Direct to your device
Your screenshots Stored in their cloud Stays on your machine
Your credentials In their logs Never transmitted
Trust model Policy-based Architecture-based

This isn’t a feature. It’s a fundamental design decision.


Your Devices, Everywhere

That phone on your desk? That tablet in the QA lab? The devices in your Tokyo office?

They’re already yours. You already paid for them. They’re already on your network.

bash
# NYC Office Mac Mini
curl -fsSL https://app.devicelab.dev/device-node/KEY | sh -s -- \
  --name "NYC-QA-Lab"

# SF Engineer's Desk
curl -fsSL https://app.devicelab.dev/device-node/KEY | sh -s -- \
  --name "SF-John-Desk"

# Tokyo Office
curl -fsSL https://app.devicelab.dev/device-node/KEY | sh -s -- \
  --name "Tokyo-Office"

Now you have a distributed device lab:

  • 15 devices across 3 continents
  • All accessible from anywhere
  • All tests run on your devices
  • All data stays on your network

No hardware to buy. No cloud rental. No monthly per-device fees for devices you already own.


The Real Comparison

Cloud Device Labs Your Device Lab
Your code Must adapt to their platform Stays exactly the same
Your data On their servers Never leaves your network
Your devices Theirs (shared with strangers) Yours (owned, controlled)
Trust model “We promise not to look” “We architecturally can’t look”
Cost Per-device rental fees Devices you already own
Setup SDKs, configs, learning curve One curl command

What This Enables

Parallel testing on your devices:

bash
curl ... --device-count 10  # Run on 10 of your devices simultaneously

Maestro on iOS physical devices:

Maestro doesn’t officially support physical iOS devices. DeviceLab does.

bash
curl ... --framework maestro --platform ios --device-names "John's iPhone"

CI/CD without data exposure:

yaml
- name: Run Tests
  run: |
    curl -fsSL https://app.devicelab.dev/test-node/${{ secrets.KEY }} | sh -s -- \
      --framework appium \
      --app ./app.apk

Your CI runs tests. Your devices execute them. Your data never leaves your infrastructure.


The Setup

Step 1: Connect your devices (once)

bash
curl -fsSL https://app.devicelab.dev/device-node/KEY | sh

Devices appear in your dashboard. That’s it.

Step 2: Run your tests (unchanged)

bash
# Maestro
curl -fsSL https://app.devicelab.dev/test-node/KEY | sh -s -- \
  --framework maestro \
  --app ./app.apk \
  --tests ./flows/

# Appium
curl -fsSL https://app.devicelab.dev/test-node/KEY | sh -s -- \
  --framework appium \
  --app ./app.apk
# Then run: pytest / mvn test / npm test

Your tests. Your devices. Your network. No code changes.


Who This Is For

Teams with devices sitting idle:

“We have 20 test phones. They’re only used a few hours a day. The rest of the time they sit in a drawer.”

For teams managing multiple devices, see our guide on scaling mobile test infrastructure.

Teams with security requirements:

“We can’t upload our APK to third-party servers. Compliance won’t allow it.”

Teams with existing tests:

“Our Appium suite works. We just need more devices, not more complexity.”

Teams tired of cloud costs:

“We’re paying $300/device/month to rent devices we could buy for $500.”


The Bottom Line

Your tests already work.

Cloud device labs made you believe you needed to adapt your code, upload your data, and trust their infrastructure to scale your testing.

You don’t.

Your devices. Your network. Your code unchanged.

That’s DeviceLab.


Get Started

bash
# Connect your first device
curl -fsSL https://app.devicelab.dev/device-node/KEY | sh

# Run your first test
curl -fsSL https://app.devicelab.dev/test-node/KEY | sh -s -- \
  --framework maestro \
  --app ./app.apk \
  --tests ./flows/

Or talk to us if you have questions.