In Appium, which command opens a deep link on Android, and which one on iOS?
answer
- one name, two mechanisms
- an execute method, not a new route
- the W3C url route also does it
- a view intent on one side only
- same method on UiAutomator2 and XCUITest
basics
~20 sAppium uses one name on both: the execute method mobile: deepLink, declared by Android's UiAutomator2 driver and by Apple's XCUITest driver. The plain WebDriver route POST /session/:sessionId/url does the same job from a native session.
solid answer
~50 sBoth platforms answer the same execute method, `mobile: deepLink` — Android's UiAutomator2 driver declares it and Apple's XCUITest driver declares it, and like every `mobile:` method it travels as a script name plus one parameter map on `POST /session/:sessionId/execute/sync`. The plain W3C navigation route `POST /session/:sessionId/url` performs the same entry from a native session, so there are two spellings of one idea. What differs is underneath and in the arguments: on Android the driver asks the system for an `android.intent.action.VIEW` intent carrying the URL and you name the receiving app with `package`; on Apple platforms the driver hands the URL to the operating system — through `simctl` on a Simulator, through WebDriverAgent on a real device — and you name the app with `bundleId`. Treat the shared name as a convenience, not as one mechanism.
code
java · 20 linesimport io.appium.java_client.AppiumDriver;
import java.util.Map;
public final class DeepLinkEntry {
private DeepLinkEntry() {
}
public static void openOnAndroid(AppiumDriver driver, String url, String androidPackage) {
driver.executeScript("mobile: deepLink", Map.of(
"url", url,
"package", androidPackage));
}
public static void openOnIos(AppiumDriver driver, String url, String bundleId) {
driver.executeScript("mobile: deepLink", Map.of(
"url", url,
"bundleId", bundleId));
}
}go deeper
Be ready to name the command and to say it is the same on both platforms: mobile: deepLink, sent as an execute method rather than a dedicated endpoint. Knowing that a URL can replace a tap sequence is the point.
Be ready to explain the divergence under the shared name: an android.intent.action.VIEW intent through adb on Android, the URL handed to the OS through simctl or WebDriverAgent on Apple platforms, with package versus bundleId naming the app.
Be ready to say why a deep-link step still needs a wait afterwards, and how you keep one helper honest when the argument map, the resolution rules and the failure modes all differ per platform.
Be ready to argue when deep-link entry is worth standardising across a suite at all, and what it costs once entry URLs become an interface the app teams must keep stable for tests.
## What deep-link entry means to the driver A deep link is a URL that the operating system routes to an installed application, which reads it as an instruction to open one particular screen. For an automated run it is a shortcut through the front of the app: instead of tapping a splash screen, a sign-in, a list and a detail view to reach one booking, the test hands the device a single URL and the app opens on that booking. Appium models this as a driver command, so the whole entry is one round trip from the client to the server to the device. ## One command name, declared by both native drivers Both native mobile drivers declare the same execute method, and that is the first thing to say out loud. - Android's **UiAutomator2** driver declares `mobile: deepLink` in its own execute-method map. - Apple's **XCUITest** driver declares `mobile: deepLink` as well. - Like every `mobile:` method it is not a new endpoint: the client posts a script name plus one parameter map to `POST /session/:sessionId/execute/sync`. - In `java-client` or the Python client you call it through `executeScript`, passing the method name and a map — there is no special typed helper to hunt for. The shared name is genuinely useful: a cross-platform suite can keep a single deep-link helper and branch only on the parameter map it builds. It is also the trap the question is testing, because the name is very nearly the only thing the two platforms share here. ## The two mechanisms, side by side | | Android (UiAutomator2) | Apple (XCUITest) | |---|---|---| | execute method | `mobile: deepLink` | `mobile: deepLink` | | argument naming the app | `package` | `bundleId` | | what the OS is asked for | an `android.intent.action.VIEW` intent carrying the URL | the URL opened by its registered scheme handler | | how the driver reaches the OS | `adb` on the host | `simctl` on a Simulator, WebDriverAgent on a real device | | optional tuning | `waitForLaunch` | none of the same shape | On Android the driver is not doing anything the platform does not already do for a tapped link: it asks the system to start a view intent for that URL. Naming `package` is what pins the intent to the app under test instead of letting the system resolve it, which for an `https` URL commonly means a browser. On Apple platforms the driver hands the URL to the operating system and lets the registered handler take it; on a Simulator that path runs through `simctl`, and on a real device it runs through WebDriverAgent — a different code path with different failure modes. ## The second spelling: the plain W3C route `POST /session/:sessionId/url` is WebDriver's navigation command, and both mobile drivers answer it from a native session by performing the same deep-link entry. So there are two ways to write one intention: 1. `mobile: deepLink` with a parameter map — the richer form, because it can name the receiving app. 2. `POST /session/:sessionId/url` with a body carrying only `url` — the terser form, which leaves the target to the system's own resolution. Reach for the execute method whenever more than one installed app could claim the URL, which on Android is most `https` links and on Apple platforms is anything a second app also registers. ## What the command promises, and what it does not - It returns once the URL has been handed off, not once your screen has finished rendering. - It does not guarantee which application receives the URL unless you name one. - It does not install or sign anything for you; the target app has to be on the device already. - It does not validate the URL, so a scheme no installed app claims tends to fail quietly rather than raise a useful error. - On Android, `waitForLaunch` governs only whether the driver waits for the started component to hand control back — it is not a wait for your content. Because of the first bullet, a deep-link step is always followed by an ordinary wait on an element of the destination screen. Treating the command's return as the arrival is the most common way this step turns flaky. ## How to say it in an interview Lead with the shared name, then split the answer immediately: same execute method, same W3C route, a different argument for the target app, and a completely different mechanism underneath — an intent on Android, a URL handed to the OS on Apple platforms. An answer that stops at "you call `mobile: deepLink`" is half an answer, because the half that matters when a run misbehaves is the half that differs between the platforms.
- If the command name is the same on both platforms, what actually has to branch in a cross-platform helper?Only the parameter map. Android's `mobile: deepLink` names the receiving app with `package` and also takes `waitForLaunch`; Apple's names it with `bundleId`. The URL itself is usually the same string, so a helper takes the URL plus a per-platform identifier and builds the map that matches the running session.
- Why does Appium expose deep-link entry as a mobile: execute method rather than a dedicated endpoint?Because `mobile:` methods are how drivers add commands without inventing routes. The client posts a script name plus one parameter map to `POST /session/:sessionId/execute/sync`, so a driver can ship a richer, platform-specific signature — Android's `package`, Apple's `bundleId` — with no change to the shared protocol surface.
A deep link is the building's side door: rather than walking the whole corridor from reception, you hand the porter an address and are let straight into the room.
saying these in an interview costs you the question
- Claiming Appium needs a differently named command for deep links on each platform
- Saying deep-link entry only works against a browser, not a native app
- Assuming the same argument names the target app on Android and on iOS
- Believing mobile: deepLink waits until the destination screen has rendered
- Thinking the driver invents a new HTTP endpoint for every mobile: method