Body: Hi all, I’m seeing a puzzling discrepancy in behavior between NSURLSession (with multipathServiceType = NSURLSessionMultipathServiceTypeInteractive) and WKWebView when the device is connected to a Wi-Fi SSID that has no internet (e.g., a hardware device’s AP). I have the Multipath entitlement properly enabled, and in this scenario:
- NSURLSession requests automatically fall back to cellular and succeed (no user intervention, fast switch).
- WKWebView loads fail or stall: the web content does not appear, and it seems like the web view is not using the cellular path even though the system network path becomes satisfied and real Internet reachability is confirmed.
Environment:
- iOS version: (e.g., iOS 18.4)
- Device: (e.g., iPhone 15 Pro)
- Multipath entitlement: enabled in the app, using NSURLSessionMultipathServiceTypeInteractive
- Connected SSID: hardware device Wi-Fi with no external internet
- Expected fallback: automatic to cellular once the Wi-Fi has no internet, as observed with NSURLSession
What I’ve done / observed:
- NSURLSession using Multipath works as expected: NSURLSessionConfiguration *cfg = [NSURLSessionConfiguration defaultSessionConfiguration]; cfg.multipathServiceType = NSURLSessionMultipathServiceTypeInteractive; NSURLSession *session = [NSURLSession sessionWithConfiguration:cfg]; NSURLRequest *req = [NSURLRequest requestWithURL:[NSURL URLWithString:@"https://www.apple.com/library/test/success.html"]]; NSURLSessionDataTask *task = [session dataTaskWithRequest:req completionHandler:^(NSData *data, NSURLResponse *resp, NSError *err) { NSLog(@"NSURLSession result: %@, error: %@", resp, err); }]; [task resume]; When connected to the device Wi-Fi (no external internet), the session quietly shifts to cellular and completes successfully.
- WKWebView fails to load under the same conditions: [self.webView loadRequest:[NSURLRequest requestWithURL:[NSURL URLWithString:@"https://www.apple.com/library/test/success.html"]]]; The web view either shows a load failure or just hangs, even though lower-level monitoring reports that the network path is satisfied and real Internet connectivity is available.
- Network path monitoring logic:
- I use the C API nw_path_monitor to watch for nw_path_status_satisfied.
- Once satisfied is observed, I perform a true connectivity check using nw_connection (e.g., connecting tohttps://www.apple.com/library/test/success.html) to verify that real Internet traffic can flow over cellular.
- That check passes, confirming fallback to cellular, but WKWebView still does not load content. Meanwhile, NSURLSession requests in the same condition succeed immediately.
- Sample logging trace: [+] nw_path_status_satisfied=1, hasWiFi=1, hasCellular=1 [+] Internet connectivity test: ready (via nw_connection) [-] WKWebView load failed / stalled [+] NSURLSession request completed successfully
Questions:
- Why does NSURLSession with the multipath service type seamlessly use cellular when the Wi-Fi has no internet, but WKWebView does not exhibit the same fallback behavior? Is WKWebView not honoring the system’s multipath fallback the same way? Does it use a different networking stack or ignore the multipath entitlement in this scenario?
- Is there a supported way to force WKWebView to behave like NSURLSession here?
- For example, can I bridge content through a multipath-enabled NSURLSession and inject it into WKWebView via a custom scheme?
- Are there any WKWebView configuration flags, preferences, or policies that enable the same automatic interface switching?
- Are there known limitations or documented differences in how WKWebView handles network interface switching, path satisfaction, or multipath compared to raw NSURLSession?
What I’ve ruled out / tried:
- Verified the Multipath entitlement is included and active.
- Confirmed network path is “satisfied” and that real Internet reachability succeeds before calling [webView loadRequest:].
- Delayed the WKWebView load until after connectivity verification.
- Observed that NSURLSession requests succeed under identical connectivity conditions.
Any insight into internal differences, recommended workarounds, or Apple-recommended patterns for making web content robust in a “Wi-Fi with no internet” + automatic fallback-to-cellular scenario would be greatly appreciated. Thank you!
Why does NSURLSession with the multipath service type seamlessly use cellular when the Wi-Fi has no internet, but WKWebView does not exhibit the same fallback behavior?
Because Multipath TCP (MPTCP) is something you have to opt in to. You’re doing that with URLSession
by setting the multipathServiceType
property. You can’t do that with WKWebView
because it doesn’t have the equivalent of that property, and thus it uses regular TCP. Regular TCP won’t do this sort of switching.
The fundamental issue here is your Wi-Fi network. It seems like your accessory is publishing a network that claims to provide access to the Internet but doesn’t. This causes iOS to switch the default route, which then triggers this problem.
The best solution to this problem is to change your accessory to not do that. There are other options, as I explain in Working with a Wi-Fi Accessory.
That post in part of my Extra-ordinary Networking series, and the other posts in that series explain a lot of the background to this issue.
If you don’t change your Wi-Fi network, you’re in to workaround territory, which is not much fun.
Are there any WKWebView configuration flags, preferences, or policies that enable the same automatic interface switching?
No.
can I bridge content through a multipath-enabled NSURLSession and inject it into WKWebView via a custom scheme?
Probably not. Custom URL schemes only work for… well… custom URL schemes. That is, they don’t work for http
and https
. That means that they’re rarely useful in this type of scenario, because it’s very common for one part of your website to reference some other part of your website via http
or https
URLs.
There is an alternative option that might work for you: Implement a local proxy within your app and configure the web view to use that. To do the latter, set the proxyConfigurations
property on WKWebsiteDataStore
.
Implementing this sort of proxy is not trivial, but I’ve seen folks use this technique to great effect.
Share and Enjoy
—
Quinn “The Eskimo!” @ Developer Technical Support @ Apple
let myEmail = "eskimo" + "1" + "@" + "apple.com"