Command reference
Complete reference for all Device Tunnel CLI commands
This section provides a comprehensive reference for all Device Tunnel CLI commands, including their syntax, options, examples, and expected outputs. Use this as your go-to guide for mastering the Device Tunnel command set and effectively managing your BrowserStack dedicated devices through the CLI.
In all examples below, device-tunnel represents the full command. When using the shared binary directly, prefix with ./binary-macos-arm64 (e.g., ./binary-macos-arm64 device-tunnel start). When using the SDK binary, use browserstack-sdk device-tunnel.
Session vs tunnel
A session allocates a device on BrowserStack and keeps it reserved. A tunnel is the local connection to that device. You can disconnect the tunnel while keeping the session and device allocated, then reconnect later without losing your device allocation.
When you have multiple devices, you can specify them using comma-separated device IDs (--device-id "UDID1,UDID2,UDID3") or device names (--device-name "Device1,Device2"). Each device will get its own session, build ID, and local port for parallel testing. If a device name exists on both Android and iOS platforms, you must specify --platform android or --platform ios to avoid ambiguity. Always prefer using --device-id over --device-name when you know the UDID, as it’s deterministic and avoids potential conflicts.
Command overview
Commands organized by intent:
| Category | Commands | Purpose |
|---|---|---|
| Lifecycle |
start, stop, status
|
Manage the orchestrator process |
| Connection |
connect, disconnect
|
Establish and break tunnels to devices |
| Discovery |
devices, sessions, list-tunnels, plans
|
Inspect devices, sessions, and account info |
Orchestrator management
These commands control the background orchestrator process that enables all tunnel operations.
start
Starts the orchestrator server. Must run before any connect or disconnect commands.
stop
Stops active sessions. Can target a specific device, a session, or stop everything. With no arguments, stops all active sessions and frees all devices.
status
Checks whether the orchestrator is running and shows its configuration.
Options
| Command | Option | Description |
|---|---|---|
| start | --username <user> |
BrowserStack username |
| Â | --access-key <key> |
BrowserStack access key |
| Â | --config <file> |
Path to YAML config file (alternative to username/access-key flags) |
| Â | --device-id <id> |
Optional: Auto-connect to device(s) after orchestrator starts. Comma-separated for multiple devices |
| Â | --device-name <name> |
Optional: Auto-connect by device name after orchestrator starts. Comma-separated for multiple devices |
| Â | --platform <android\|ios> |
Optional: Platform filter when using --device-name (required if device name exists on both platforms) |
| Â | --enable-ios |
Optional: To connect to iOS devices, pass this flag or set enable_ios: true in config.yml
|
| Â | --local-identifier <id> |
Optional: Local identifier for multi-instance BrowserStack Local setups |
| Â | --json |
Return JSON output instead of plain text |
| stop | --device-id <id> |
Stop session for specific device(s). Comma-separated for multiple devices |
| Â | --device-name <name> |
Stop session by device name. Comma-separated for multiple devices |
| Â | --platform <android\|ios> |
Platform filter when using --device-name
|
| Â | --session-id <id> |
Stop specific session by session ID |
| Â | --json |
Return JSON output instead of plain text |
| status | --verbose |
Show detailed orchestrator configuration |
| Â | --json |
Return JSON output instead of plain text |
Common usage examples
Start orchestrator with credentials:
Start orchestrator with auto-connect to a device:
Start with auto-connect to multiple devices:
Check orchestrator status:
Stop all sessions:
Stop specific device session:
Stop multiple devices:
Behavior notes
Auto-connect with start
When --device-id or --device-name is passed with start:
- Orchestrator starts and becomes healthy
- CLI waits 5 seconds for local port binding
- CLI tries to reconnect to any existing session for each device, then falls back to creating a new session if not found
- Failures in auto-connect are non-fatal, and the orchestrator continues running regardless
Failure scenarios
| Scenario | Outcome |
|---|---|
| Orchestrator already running | Error with PID/port info + hint to run stop
|
| Invalid credentials | 401 error, orchestrator exits |
| BrowserStack Local instances detected | Error with instructions to stop local instances |
--device-id device not found |
Error per device; orchestrator keeps running |
Device operations
Action-oriented commands for establishing and managing connections to devices.
connect
Creates a tunnel to a device. Supports --device-id, --device-name, or legacy --session-id.
disconnect
Disconnects the tunnel for a device. The session keeps running and the device stays allocated.
Options
| Command | Option | Description |
|---|---|---|
| connect | --device-id <id> |
Connect to device(s) by UDID. Comma-separated for multiple devices. Mutually exclusive with --device-name
|
| Â | --device-name <name> |
Connect to device(s) by name. Comma-separated for multiple devices. Mutually exclusive with --device-id
|
| Â | --platform <android\|ios> |
Platform filter when using --device-name (required if device name exists on both platforms) |
| Â | --new-connection |
Force a new session (stop existing session first, then create fresh) |
| Â | --session-id <id> |
(Legacy) Connect using existing session ID |
| Â | --json |
Return JSON output instead of plain text |
| disconnect | --device-id <id> |
Disconnect device(s) by UDID. Comma-separated for multiple devices. Mutually exclusive with --device-name
|
| Â | --device-name <name> |
Disconnect device(s) by name. Comma-separated for multiple devices. Mutually exclusive with --device-id
|
| Â | --platform <android\|ios> |
Platform filter when using --device-name
|
| Â | --session-id <id> |
(Legacy) Disconnect using session ID |
| Â | --json |
Return JSON output instead of plain text |
--device-id and --device-name are mutually exclusive.
Common usage examples
Connect to a single device:
Connect to multiple devices (parallel):
Connect by device name:
Connect with platform specification:
Connect to multiple devices by name:
Force a new session:
Legacy session-ID connect:
Disconnect a device:
Disconnect multiple devices:
Behavior notes
Connect decision tree
connect --device-id <UDID> resolves as follows:
Connect output states
| Header | Meaning |
|---|---|
TUNNEL CONNECTED SUCCESSFULLY |
Local port is live; ADB connected (Android) or WDA Port available (iOS) |
TUNNEL REQUEST ACCEPTED (PENDING) |
API accepted the request but the local tunnel port is not yet bound. Check with list-tunnels
|
Disconnect compared to stop
| Action | disconnect | stop |
|---|---|---|
| Closes local tunnel port | Yes | Yes |
| Calls API | POST /disconnect (tunnel only) | POST /stop (full session) |
| Device freed | No, device stays allocated | Yes, device returned to pool |
| Session kept | Yes, session remains running | No, session is fully torn down |
What disconnect does internally:
- Looks up the active session for the device ID via the unified session list
- Unregisters the local tunnel from TunnelStore (Android) or IosTunnelStore (iOS)
- For Android: runs
adb disconnect localhost:<port>if ADB is available - For iOS: sends a
cleanup_ios_sessionmessage to the orchestrator socket - Calls
POST /device_tunnel/v2/builds/:bid/sessions/:sid/disconnect. The tunnel is disconnected, but the session stays running - Updates tunnel status to
disconnectedin DeviceMappingStore
After disconnecting you can reconnect at any time with:
Failure scenarios
Connect:
| Scenario | Error code | Resolution |
|---|---|---|
| Orchestrator not running | UNEXPECTED |
Run start first |
Empty --device-id value |
INVALID_ARGS |
Provide a valid UDID |
Both --device-id and --device-name provided |
INVALID_ARGS |
Use only one |
| Device not in your dedicated fleet | NOT_FOUND |
Run devices to verify |
| Device name ambiguous across platforms | INVALID_ARGS |
Add --platform android or --platform ios
|
| Multiple sessions found for device name | INVALID_ARGS |
Use --device-id instead |
| 401 from API | AUTH_FAILED |
Check credentials |
| 403 from API | ACCESS_DENIED |
Account lacks Device Tunnel subscription |
| 409 from API | CONFLICT |
Tunnel may already exist; run list-tunnels
|
| Network timeout | NETWORK_TIMEOUT |
Retry; check network connectivity |
Disconnect:
| Scenario | Error code | Resolution |
|---|---|---|
| No active session found for device ID | NOT_FOUND |
Run sessions to verify |
| No connected tunnel found | NOT_FOUND |
The tunnel may already be disconnected |
| 401 from API | AUTH_FAILED |
Check credentials |
| Multiple sessions for the same device name |
INVALID_ARGS / prompt |
Use --device-id
|
Discovery and metadata
Read-only commands to inspect available devices, active sessions, and account information.
devices
Lists all dedicated or private devices on your BrowserStack account.
Options for devices
| Flag | Description |
|---|---|
--platform <android\|ios> |
Filter by platform |
--json |
Output as JSON |
Examples of devices
Sample output of devices
Device status values
| Status | Meaning |
|---|---|
available |
Ready to connect |
in use |
Currently allocated by a session |
cleaning |
Post-session cleanup in progress |
offline |
Wait for some time ~5-10 mins the device should come back online, if not then reach out to BrowserStack support |
Failure scenarios for devices
| Scenario | Outcome |
|---|---|
| Orchestrator has not started yet |
AUTH_FAILED, no stored credentials |
| Account has no dedicated devices | Message to contact BrowserStack support |
| 403 response | Account lacks Bridge Cloud subscription |
sessions
Queries the active BrowserStack sessions for your account. Shows cloud-side session status.
Options for sessions
| Flag | Description |
|---|---|
--json |
NEW: Output as JSON |
Sample output of sessions
Framework column values:
-
DEVICETUNNEL: standalone device tunnel session -
APPIUM: legacy Appium-based session
For iOS, the WDA port is used with the iproxy command while running Appium sessions. Building WDA remotely on the machine is not supported, so Device Tunnel provides the WDA port for use with the iproxy command: iproxy 8100 <WDA-PORT> -u <DEVICE-UUID>.
All requests on port 8100 are then proxied to WDA on the remote device. To verify this, run curl http://localhost:8100/status, which returns a 200 response.
list-tunnels
Lists all locally registered active tunnels. Data is sourced from the local tunnel stores (authoritative for liveness).
Options for list-tunnels
| Flag | Description |
|---|---|
--json |
NEW: Output as JSON |
--verbose, -v |
Enable verbose logging |
Sample output of list-tunnels
This command checks local tunnel liveness (what’s active on your machine), whereas sessions checks cloud session liveness (what’s allocated on BrowserStack).
plans
Retrieves BrowserStack plan/subscription data for the account.
Options for plans
| Flag | Description |
|---|---|
--json |
Output as JSON (default is pretty-printed JSON) |
Examples of plans
Sample output of plans
Failure scenarios for plans
- Requires the orchestrator to be running (credentials are sourced from its stored auth).
- Returns
AUTH_FAILEDif no credentials are stored. - Returns
SERVICE_UNAVAILABLEon 5xx errors.
New flags reference
The following flags were introduced with the Device Tunnel CLI MVP and are supported across the commands listed:
| Flag | Commands | Description |
|---|---|---|
--device-id <UDID> |
start, connect, disconnect, stop
|
Hardware device UDID. Comma-separate for multiple devices |
--device-name <name> |
start, connect, disconnect, stop
|
Device name in Model-OSVersion format |
--platform <android\|ios> |
start, connect, disconnect, stop, devices
|
Platform filter or disambiguator |
--enable-ios |
start |
Enables connecting to iOS devices for the session |
--new-connection |
connect |
Forces a fresh session, stopping the existing one if present |
--local-identifier <id> |
start, connect
|
BrowserStack Local identifier for multi-instance setups |
--json |
connect, disconnect, stop, status, sessions, devices, plans, list-tunnels
|
Machine-readable JSON output |
We're sorry to hear that. Please share your feedback so we can do better
Contact our Support team for immediate help while we work on improving our docs.
We're continuously improving our docs. We'd love to know what you liked
We're sorry to hear that. Please share your feedback so we can do better
Contact our Support team for immediate help while we work on improving our docs.
We're continuously improving our docs. We'd love to know what you liked
Thank you for your valuable feedback!