Deep Linking in Flutter: Handling URL Routes the Smart Way
Aug 22, 2025



Summary
Summary
Summary
Summary
This tutorial covers Flutter deep linking: setting up URL strategies in Android, iOS, and web; integrating with Navigator 2.0 via RouteInformationParser and RouterDelegate; listening to URI streams with uni_links; and testing links on mobile and web. By mapping URIs to typed route configs, you create seamless navigation paths for users arriving via custom schemes or HTTPS URLs.
This tutorial covers Flutter deep linking: setting up URL strategies in Android, iOS, and web; integrating with Navigator 2.0 via RouteInformationParser and RouterDelegate; listening to URI streams with uni_links; and testing links on mobile and web. By mapping URIs to typed route configs, you create seamless navigation paths for users arriving via custom schemes or HTTPS URLs.
This tutorial covers Flutter deep linking: setting up URL strategies in Android, iOS, and web; integrating with Navigator 2.0 via RouteInformationParser and RouterDelegate; listening to URI streams with uni_links; and testing links on mobile and web. By mapping URIs to typed route configs, you create seamless navigation paths for users arriving via custom schemes or HTTPS URLs.
This tutorial covers Flutter deep linking: setting up URL strategies in Android, iOS, and web; integrating with Navigator 2.0 via RouteInformationParser and RouterDelegate; listening to URI streams with uni_links; and testing links on mobile and web. By mapping URIs to typed route configs, you create seamless navigation paths for users arriving via custom schemes or HTTPS URLs.
Key insights:
Key insights:
Key insights:
Key insights:
Understanding Deep Linking in Flutter: Use custom schemes and HTTPS fallback to parse incoming URIs and map them to routes.
Setting Up URL Strategies: Configure PathUrlStrategy for web and register custom schemes in AndroidManifest.xml and Info.plist.
Integrating with Navigator 2.0: Leverage RouteInformationParser and RouterDelegate to declaratively convert URLs to navigation stacks.
Handling Incoming Links: Use the uni_links package to listen for URI streams and navigate based on path and query parameters.
Testing Deep Links: Validate link handling with adb and xcrun commands on Android and iOS, and test direct URL navigation in Flutter Web.
Introduction
Deep linking lets mobile apps respond to incoming URLs and route users directly to specific screens. In Flutter, handling URL routes smartly enhances user experience by reducing navigation friction. This tutorial explores core techniques—URL strategies, Navigator 2.0 integration, link listeners, and testing—to implement deep links effectively.
Understanding Deep Linking in Flutter
Flutter’s navigation system can map URL paths to widget routes. On the web, the browser URL bar drives navigation, but on mobile, you need to parse incoming URIs. A deep link typically follows a custom scheme (myapp://) or an HTTPS fallback (https://example.com/page). When the OS receives a link, it launches your Flutter app and forwards the URI. Inside your app, you inspect the URI and translate its path and query parameters into routing instructions.
Setting Up URL Strategies
For web and mobile consistency, configure URL strategies in your pubspec.yaml and main.dart.
import 'package:flutter_web_plugins/flutter_web_plugins.dart';
void main() {
setUrlStrategy(PathUrlStrategy());
runApp(MyApp());
}
On mobile, register custom schemes in AndroidManifest.xml and Info.plist. For Android:
<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="example.com"/>
</intent-filter>
iOS requires CFBundleURLTypes entries with URL schemes matching your app ID.
Integrating with Navigator 2.0
Navigator 2.0 exposes a declarative approach to routing using Router, RouteInformationParser, and RouterDelegate. Create a custom RouteInformationParser to convert RouteInformation (location) into a typed configuration:
class MyRouteInfoParser extends RouteInformationParser<RouteConfig> {
@override
Future<RouteConfig> parseRouteInformation(
RouteInformation info) async {
final uri = Uri.parse(info.location!);
if (uri.pathSegments.contains('product')) {
return ProductConfig(id: uri.queryParameters['id']);
}
return HomeConfig();
}
}
The RouterDelegate responds to that configuration by updating the Navigator.pages stack.
Handling Incoming Links
Use the uni_links package to listen for incoming URIs at runtime. Inside a stateful widget’s initState, register a link stream:
StreamSubscription _sub;
@override
void initState() {
super.initState();
_sub = uriLinkStream.listen((Uri? uri) {
if (uri != null) handleDeepLink(uri);
});
}
void handleDeepLink(Uri uri) {
// Parse path and params, then navigate
if (uri.path == '/profile') {
Navigator.pushNamed(context, '/profile',
arguments: uri.queryParameters);
}
}
Remember to cancel the subscription in dispose().
Testing Deep Links
Testing deep links ensures reliability across platforms. On Android, use adb:
adb shell am start -W -a android.intent.action.VIEW \
-d "myapp://example.com/product?id=42" com.example.myapp
On iOS Simulator, use xcrun:
xcrun simctl openurl booted "myapp://example.com/profile?user=alice"
For Flutter Web, navigate directly to https://localhost:5000/product?id=42. Verify that your RouteInformationParser and RouterDelegate update the displayed page accordingly.
Vibe Studio

Vibe Studio, powered by Steve’s advanced AI agents, is a revolutionary no-code, conversational platform that empowers users to quickly and efficiently create full-stack Flutter applications integrated seamlessly with Firebase backend services. Ideal for solo founders, startups, and agile engineering teams, Vibe Studio allows users to visually manage and deploy Flutter apps, greatly accelerating the development process. The intuitive conversational interface simplifies complex development tasks, making app creation accessible even for non-coders.
Conclusion
Deep linking in Flutter involves configuring URL strategies, integrating Navigator 2.0, listening for incoming URIs, and rigorous testing. By mapping URL segments to typed route configurations, you streamline navigation and deliver targeted content. Implement these patterns to provide seamless entry points into your app, whether users click web links, QR codes, or in-app banners.
Introduction
Deep linking lets mobile apps respond to incoming URLs and route users directly to specific screens. In Flutter, handling URL routes smartly enhances user experience by reducing navigation friction. This tutorial explores core techniques—URL strategies, Navigator 2.0 integration, link listeners, and testing—to implement deep links effectively.
Understanding Deep Linking in Flutter
Flutter’s navigation system can map URL paths to widget routes. On the web, the browser URL bar drives navigation, but on mobile, you need to parse incoming URIs. A deep link typically follows a custom scheme (myapp://) or an HTTPS fallback (https://example.com/page). When the OS receives a link, it launches your Flutter app and forwards the URI. Inside your app, you inspect the URI and translate its path and query parameters into routing instructions.
Setting Up URL Strategies
For web and mobile consistency, configure URL strategies in your pubspec.yaml and main.dart.
import 'package:flutter_web_plugins/flutter_web_plugins.dart';
void main() {
setUrlStrategy(PathUrlStrategy());
runApp(MyApp());
}
On mobile, register custom schemes in AndroidManifest.xml and Info.plist. For Android:
<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="example.com"/>
</intent-filter>
iOS requires CFBundleURLTypes entries with URL schemes matching your app ID.
Integrating with Navigator 2.0
Navigator 2.0 exposes a declarative approach to routing using Router, RouteInformationParser, and RouterDelegate. Create a custom RouteInformationParser to convert RouteInformation (location) into a typed configuration:
class MyRouteInfoParser extends RouteInformationParser<RouteConfig> {
@override
Future<RouteConfig> parseRouteInformation(
RouteInformation info) async {
final uri = Uri.parse(info.location!);
if (uri.pathSegments.contains('product')) {
return ProductConfig(id: uri.queryParameters['id']);
}
return HomeConfig();
}
}
The RouterDelegate responds to that configuration by updating the Navigator.pages stack.
Handling Incoming Links
Use the uni_links package to listen for incoming URIs at runtime. Inside a stateful widget’s initState, register a link stream:
StreamSubscription _sub;
@override
void initState() {
super.initState();
_sub = uriLinkStream.listen((Uri? uri) {
if (uri != null) handleDeepLink(uri);
});
}
void handleDeepLink(Uri uri) {
// Parse path and params, then navigate
if (uri.path == '/profile') {
Navigator.pushNamed(context, '/profile',
arguments: uri.queryParameters);
}
}
Remember to cancel the subscription in dispose().
Testing Deep Links
Testing deep links ensures reliability across platforms. On Android, use adb:
adb shell am start -W -a android.intent.action.VIEW \
-d "myapp://example.com/product?id=42" com.example.myapp
On iOS Simulator, use xcrun:
xcrun simctl openurl booted "myapp://example.com/profile?user=alice"
For Flutter Web, navigate directly to https://localhost:5000/product?id=42. Verify that your RouteInformationParser and RouterDelegate update the displayed page accordingly.
Vibe Studio

Vibe Studio, powered by Steve’s advanced AI agents, is a revolutionary no-code, conversational platform that empowers users to quickly and efficiently create full-stack Flutter applications integrated seamlessly with Firebase backend services. Ideal for solo founders, startups, and agile engineering teams, Vibe Studio allows users to visually manage and deploy Flutter apps, greatly accelerating the development process. The intuitive conversational interface simplifies complex development tasks, making app creation accessible even for non-coders.
Conclusion
Deep linking in Flutter involves configuring URL strategies, integrating Navigator 2.0, listening for incoming URIs, and rigorous testing. By mapping URL segments to typed route configurations, you streamline navigation and deliver targeted content. Implement these patterns to provide seamless entry points into your app, whether users click web links, QR codes, or in-app banners.
Build Flutter Apps Faster with Vibe Studio
Build Flutter Apps Faster with Vibe Studio
Build Flutter Apps Faster with Vibe Studio
Build Flutter Apps Faster with Vibe Studio
Vibe Studio is your AI-powered Flutter development companion. Skip boilerplate, build in real-time, and deploy without hassle. Start creating apps at lightning speed with zero setup.
Vibe Studio is your AI-powered Flutter development companion. Skip boilerplate, build in real-time, and deploy without hassle. Start creating apps at lightning speed with zero setup.
Vibe Studio is your AI-powered Flutter development companion. Skip boilerplate, build in real-time, and deploy without hassle. Start creating apps at lightning speed with zero setup.
Vibe Studio is your AI-powered Flutter development companion. Skip boilerplate, build in real-time, and deploy without hassle. Start creating apps at lightning speed with zero setup.











