URL Scheme — is a custom URI protocol that a mobile app registers in the operating system to be opened via links like myapp://path. According to RFC 3986, the URI scheme defines the syntax and semantics of all subsequent address components. When navigating to such a link, the system identifies the registered application by its unique identifier and launches it with the parameters extracted from the link. Deep link based on URL Scheme remains the basic mechanism of inter-app navigation on mobile platforms, despite the emergence of more modern alternatives.
Key Takeaways
URL Scheme — is a unique protocol identifier that an application registers in the operating system to receive calls via custom links. When a user clicks a link like myapp://profile/123, the system identifies the application that registered the myapp scheme and passes control to it with the full URI. This mechanism allows applications to exchange data and open each other without server infrastructure involvement.
The concept of URL Scheme is directly borrowed from web standards RFC 3986, where the URI scheme is the first component of any universal resource identifier. In mobile development, this idea is adapted for inter-app communication, where instead of an HTTP server, the application itself acts as the link handler.
Many popular applications register their own URL Schemes for integration with third-party services. For example, Spotify uses the spotify:// scheme, Telegram uses tg://, and Instagram uses instagram://. Developers also often create appname:// schemes for internal navigation and end-to-end screen testing.
URL Schemes are still widely used in push notifications, email newsletters and QR codes where instant navigation to a specific app section is required. However, starting with iOS 9 and Android 6, alternative mechanisms emerged that gradually complement and replace bare schemes.
The structure of a custom URI follows the general RFC 3986 specification and consists of several components. The scheme is specified first and separated by a colon from the rest of the address. After the scheme, host, port, path, query parameters and fragment may follow, each of which is optional.
The full syntax looks like scheme://host/path?key=value#fragment. The scheme is the only mandatory element; the rest are determined by the needs of the specific implementation. The double slash after the scheme is historically borrowed from HTTP and is not strictly required by the specification, but is universally used as a convention.
For a visual representation of the URI structure, a component table is used. Each element has its purpose and level of mandatory requirement.
| Component | Example | Mandatory |
|---|---|---|
| Scheme | myapp | Yes |
| Host | profile | No |
| Path | /user/42 | No |
| Query | ?id=42&tab=main | No |
| Fragment | #section2 | No |
Developers can arbitrarily choose the URI structure, which creates flexibility but generates compatibility issues between different versions of the application. It is recommended to document the URL Scheme format as part of the application’s public API and version it when changes occur.
iOS requires explicit registration of each URL Scheme in the project’s Info.plist file. The developer adds a CFBundleURLTypes array, each element of which contains an identifier (CFBundleURLName) and a list of supported schemes (CFBundleURLSchemes). After registration, the system automatically directs all incoming calls on registered schemes to the application.
Handling an incoming URL Scheme occurs in the app delegate through the application(_:open:options:) method. This method receives a URL object from which the path and query parameters are extracted to make navigation decisions. The handler must return a Bool value indicating the success of the operation.
Below is an example implementation of a URL Scheme handler in Swift. The code demonstrates extracting the host and query parameters from an incoming URI using URLComponents.
func application(
_ app: UIApplication,
open url: URL,
options: [UIApplication.OpenURLOptionsKey: Any]
) -> Bool {
let host = url.host
let params = URLComponents(
url: url,
resolvingAgainstBaseURL: false
)?.queryItems
if host == "profile" {
navigateToProfile(params)
}
return true
}
The method uses URLComponents for safe parsing of query parameters. This approach is preferable to manual string parsing as it automatically handles percent encoding and decoding of special characters in parameter values.
Android uses the Intent Filter system to route deep links based on URL Scheme. The developer declares a filter in AndroidManifest.xml inside the Activity tag that should handle the link. The filter contains the VIEW action, BROWSABLE and DEFAULT categories, and a data tag specifying the scheme, host and pathPrefix.
When a user clicks a link with a custom scheme, the system checks the Intent Filter of all installed applications. If multiple matching applications are found, the user is presented with a chooser dialog. The BROWSABLE category allows the link to be processed from the browser.
Example of declaring an Intent Filter in AndroidManifest.xml to handle the myapp scheme on an Activity. The combination of action and category is mandatory for correct deep link routing.
<activity android:name=".MainActivity">
<intent-filter>
<action android:name="android.intent.action.VIEW" />
<category
android:name="android.intent.category.DEFAULT" />
<category
android:name="android.intent.category.BROWSABLE" />
<data
android:scheme="myapp"
android:host="profile"
android:pathPrefix="/user" />
</intent-filter>
</activity>
After configuring the filter in the Activity, you must call intent.getData() to obtain the URI. It is important to check intent and data for null, as the Activity may be launched without an incoming deep link, for example during standard launch from the launcher.
Query parameters in URL Scheme are passed after the question mark in key=value format, separated by ampersands. This format is identical to HTTP requests and is easily processed by standard platform tools. Parameters must be encoded using percent encoding for all characters not in the allowed URI character set.
Example of a full link with parameters: myapp://profile?userId=42&source=email&ref=abc123. After extracting the URL, the application sequentially parses all query-items and based on their values makes a navigation decision to the target screen.
When passing complex data, it is important to consider the URI length limitation. In iOS, the maximum URL Scheme length is limited to 2 KB, after which the system truncates the link. In Android, the limit is about 8 KB, but the exact value depends on the OS version and device manufacturer. For large amounts of data, it is recommended to pass only a session identifier via URL Scheme and load the rest of the data from the server.
The main drawback of URL Scheme is the inability to handle a link if the application is not installed on the device. The browser displays an error, and the user loses the navigation context. To solve this problem, Apple introduced Universal Links in iOS 9, and Google introduced App Links in Android 6. Both mechanisms are registered through a web domain associated with the application.
Universal Links and App Links work like regular HTTPS links, but when the application is installed, they open it without a chooser dialog. If the application is not installed, the link opens a web page on the same domain, preserving the user experience. This makes them the preferred alternative for production environments.
For URL Scheme on iOS and Android, there is no built-in fallback mechanism. Developers use intermediate server solutions: the link leads to a web page that checks if the application is installed via JavaScript and redirects either to the scheme or to the app store. Firebase Dynamic Links and Branch.io offer ready-made solutions to this problem with support for deferred deep links that automatically determine the installation status and route the user without needing to develop a custom server pipeline.
Additional complexity arises when using URL Scheme in iOS 15+ and Android 12+, where privacy rules have been tightened. Safari blocks attempts to open an unregistered scheme without prior confirmation, and Android 12 restricts visibility of installed applications through PackageManager. These changes make using URL Scheme for inter-app communication less reliable than in earlier platform versions.
Frequently Asked Questions
URL Scheme uses a custom protocol without encryption, while Universal Links work via HTTPS with domain verification. Universal Links do not trigger an app chooser dialog and are handled correctly when the application is not installed on the device.
Yes, but all non-ASCII characters must be encoded using percent-encoding according to RFC 3986. It is recommended to avoid Cyrillic in URL Scheme to ensure compatibility with older OS versions and browsers.
There are no limits on the number of schemes in either iOS or Android. In practice, applications use one to five schemes. For example, Telegram registers the schemes tg://, t.me/, telegram:// and telegram.me://.
In iOS, the canOpenURL(_:) method is used, which returns true if the scheme is registered. In Android, the check is performed via PackageManager.queryIntentActivities(). Both platforms require the scheme to be pre-specified in the configuration.
No, URL Scheme does not encrypt data. Any application that registers the same scheme can intercept the link. For security, use Universal Links with HTTPS or end-to-end data encryption at the protocol level.
Summary
We will develop a mobile application turnkey
IT Sectr creates iOS and Android applications for startups and businesses since 2017. We will advise you and propose the best solution.
Read also