In Appium, what does POST /session/:sessionId/url do in a native Android or iOS session?
answer
- a standard route, reused
- spelled with sessionId, not id
- the body carries one key only
- nothing names the receiving app
- the OS resolves it either way
basics
~20 sIt performs deep-link entry. Both mobile drivers answer WebDriver's navigation route from a native session by handing the URL to the device: Android starts an android.intent.action.VIEW intent, Apple platforms open the URL through simctl or WebDriverAgent.
solid answer
~40 s`POST /session/:sessionId/url` is WebDriver's navigation command, and the mobile drivers reuse it rather than inventing a mobile-only route. From a native session it means deep-link entry: on Android the driver asks the system for an `android.intent.action.VIEW` intent carrying the URL, and on Apple platforms it hands the URL to the operating system — `simctl` on a Simulator, WebDriverAgent on a real device. The body carries only `url`, which is the practical difference from `mobile: deepLink`: the route has nowhere to name a receiving app, so the system resolves the URL itself. Prefer the execute method when more than one installed app could claim the URL, and keep the route for the simple case where the scheme is unambiguously yours.
code
bash · 3 linescurl -sS -X POST "http://127.0.0.1:4723/session/${SESSION_ID}/url" \
-H 'Content-Type: application/json' \
-d '{"url": "ferrytimetable://booking/8821"}'go deeper
Be ready to say that this is WebDriver's ordinary navigation route and that Appium reuses it, so a URL posted to it in a native session opens a deep link rather than a web page.
Be ready to describe both platform mechanisms behind the one route and to name its practical limit: the body carries only url, so nothing in the request names the receiving application.
Be ready to explain how you read this route in a server log during triage, and why a successful response is not evidence that the app under test received the URL.
Be ready to set a suite-wide convention for which spelling teams use, and to justify the cost of that consistency against the flexibility of choosing per case.
## The route, and why it is not a mobile invention `POST /session/:sessionId/url` is WebDriver's own navigation command — the one a browser session uses to go to a page. Appium's mobile drivers did not invent a parallel route for deep links; they answer this one. From a native session on either platform, sending a URL to it means "hand this URL to the device and let the system route it", which is exactly deep-link entry. Two notational points are worth getting right, because they surface in every discussion of this route: - The path segment is spelled `:sessionId`. That is how it appears in the sources. - The body is JSON carrying `url`. There is no second key for a target application. ## What each platform does with it | | Android | Apple platforms | |---|---|---| | driver | UiAutomator2 | XCUITest | | what the OS is asked for | an `android.intent.action.VIEW` intent carrying the URL | the URL opened by its registered handler | | how the driver reaches the OS | `adb` on the host | `simctl` on a Simulator, WebDriverAgent on a real device | | who decides the receiving app | the system's own intent resolution | the system's registered scheme handler | The important line is the last one. Because the route's body carries only `url`, nothing in the request names an application. On both platforms the operating system makes that choice, using whatever happens to be installed on that particular device. That is fine for a custom scheme only your app claims, and genuinely risky for an `https` URL. ## Route versus execute method Both spellings reach the same behaviour, so the choice is about how much control you need. 1. `POST /session/:sessionId/url` — terse, protocol-standard, one key in the body, no way to name a target. 2. `mobile: deepLink` on `POST /session/:sessionId/execute/sync` — a parameter map that also names the receiving app: `package` on Android, `bundleId` on Apple platforms, plus Android's `waitForLaunch`. A short decision rule: - If exactly one installed application can claim the scheme, either spelling works and the route is the shorter one. - If the URL is an `https` link, or a second app registers the same scheme, use the execute method so the target is explicit. - If you need Android's `waitForLaunch` behaviour, the execute method is the only place it exists. - If a client wrapper already exposes navigation as a first-class call, the route may simply read better in your suite. ## What the route does not do - It does not wait for your destination screen; it returns once the device has been given the URL. - It does not report which application ended up handling the URL. - It does not install anything: the target app must already be on the device. - It carries no target argument, so it cannot resolve an ambiguous URL for you. Each of those is a place where a suite goes quietly wrong rather than failing loudly. The characteristic symptom is a find that times out on a screen looking nothing like the one the test expected, because a different application answered the URL. ## Reading it in a log When you are staring at a server log, this route is easy to overlook precisely because it looks like ordinary browser navigation. On a native mobile session it is not navigation of a page at all — it is a request to the operating system, and everything after it depends on how that system resolved the URL. Reading it that way turns a confusing trace into an obvious one: the request succeeded, the URL was delivered, and the next question worth asking is which application received it, not whether the command worked. ## Saying it well A strong answer names the route with its real spelling, says that both mobile drivers answer it from a native session as deep-link entry, gives the two mechanisms — a view intent on Android, the URL handed to the OS through `simctl` or WebDriverAgent on Apple platforms — and then draws the distinction that matters day to day: the route has no argument for the receiving app, and `mobile: deepLink` does.
- When would you choose mobile: deepLink over this route?Whenever more than one installed application could claim the URL. The route's body carries only `url`, so the system resolves the target; `mobile: deepLink` adds `package` on Android or `bundleId` on Apple platforms and pins it. Android's `waitForLaunch` is also only available on the execute method.
- The route returns success but the expected screen never appears. What does that tell you?That the URL was delivered, not that your app received it. Success here means the device took the URL; the operating system then resolved it, possibly to a browser or to another app. The next check is which application is in the foreground, not whether the request worked.
saying these in an interview costs you the question
- Believing this route only ever navigates a web page
- Writing the path with :id instead of :sessionId
- Expecting the body to accept a package or bundle identifier
- Reading a successful response as proof the right app opened
- Assuming Appium added a mobile-only endpoint for deep links