starti.app
Concepts

User agent

What the app sends as its user agent, how to detect the app, and why some libraries treat the iOS app differently from Safari

User agent

Your site runs in the phone's own embedded browser: WKWebView on iOS and Android System WebView on Android. The app takes that browser's default user agent and adds two tokens to the end. Nothing is removed.

The default itself is not the same as the one Safari or Chrome sends, and that difference is what catches people out.

What your site sees

Examples from an iPhone and an Android phone. The version and device parts vary, so never match on the whole string.

WhereUser agent
Safari on iPhoneMozilla/5.0 (iPhone; CPU iPhone OS 18_7 like Mac OS X) AppleWebKit/605.1.15 (KHTML, like Gecko) Version/26.5 Mobile/15E148 Safari/604.1
The app on iOSMozilla/5.0 (iPhone; CPU iPhone OS 18_7 like Mac OS X) AppleWebKit/605.1.15 (KHTML, like Gecko) Mobile/15E148 starti.app/4.273.1 starti.app-platform/ios
The app on AndroidMozilla/5.0 (Linux; Android 15; Pixel 8; wv) AppleWebKit/537.36 (KHTML, like Gecko) Version/4.0 Chrome/131.0.0.0 Mobile Safari/537.36 starti.app/4.273.1 starti.app-platform/android

On iOS, the app's user agent contains no Safari and no Version/. Every iOS app that embeds a web page has this, with or without starti.app. The engine is still WebKit, so code that looks for the word Safari to mean "WebKit on iOS" gets the wrong answer.

The tokens we add

TokenMeaning
starti.app/<version>The page is running in the app, and this is the app's version
starti.app-dev/<version>The same, in a test build of the app
starti.app-platform/ios or /androidThe platform the app runs on

Detect the app

In the browser, use the SDK rather than reading the string yourself:

startiapp.isRunningInApp(); // true inside the app
startiapp.App.platform;     // "ios" | "android" | "web"

On the server, or before the SDK has loaded, look for the tokens:

const isApp = /starti\.app/.test(userAgent);
const isIosApp = userAgent.includes("starti.app-platform/ios");

The in-app browser is different

Links that open in the in-app browser do not carry the starti.app tokens, so isRunningInApp() is false there. That browser presents itself as an ordinary mobile browser, so login providers and other third-party pages treat it as one.

Libraries that look for "Safari"

Some libraries choose their behaviour from the user agent. They then treat the iOS app as "not Safari", even though it is the same engine. Video players are a common example, because they may pick a different way of playing a stream. If something works in Safari on the iPhone and fails only in the iOS app, check this first.

Prefer feature detection in your own code. If a library decides from the user agent, look for an option that sets the behaviour explicitly, and limit it to the iOS app:

const isIosApp = navigator.userAgent.includes("starti.app-platform/ios");

Test this on a real iPhone, inside the app. The Chrome device profile only imitates the user agent and does not run WebKit, so it cannot show this kind of fault. Use Safari Web Inspector to look inside a test build of the app.

On this page