How do I capture the redirection url in when using WKWebView like if a webpage redirects to another page on submitting the username and password or some other data. I need to capture the redirected url. Is there any method in WKNavigationDelegate to override?
7 Answers
Use this WKNavigationDelegate
method
public func webView(_ webView: WKWebView, decidePolicyFor navigationAction: WKNavigationAction, decisionHandler: @escaping (WKNavigationActionPolicy) -> Swift.Void) {
if(navigationAction.navigationType == .other) {
if let redirectedUrl = navigationAction.request.url {
//do what you need with url
//self.delegate?.openURL(url: redirectedUrl)
}
decisionHandler(.cancel)
return
}
decisionHandler(.allow)
}
Hope this helps

- 670
- 1
- 11
- 25

- 20,519
- 3
- 38
- 55
-
2it's not working anymore now navigationAction.navigationType => .other for redirect – Sheshnath Jul 18 '18 at 11:02
-
-
-
ok @ShauketSheikh I will review it again, anyway check for the another answer maybe can help you, let me know – Reinier Melian Oct 08 '18 at 07:24
-
Thanks but i am facing very wierd issue for wkwebview ios 9 cookie are not updating for redirect uri – Muhammad Shauket Oct 08 '18 at 07:37
-
WKWebView doesn't automatically set the Content-Type header to application/x-www-formurlencoded for POST requests You can add request.addValue("application/x-www-form-urlencoded", forHTTPHeaderField: "Content-Type"). to headers manually – Vijay Patidar Mar 12 '21 at 17:51
-
(This answers the slightly more general question of how to detect a URL redirection in WKWebView, which is the search that lead me to this page.)
Short answer
Use WKNavigationDelegate
's webView(_:didReceiveServerRedirectForProvisionalNavigation:)
function and examine WKWebView
's URL
property.
Longer answer
There are a couple of places you could detect a server-side redirect.
On iOS 10.3.3 and iOS 11.0, the sequence of events I observe when loading a URL that gets redirected by the server is:
The
WKNavigationDelegate
functionwebView(_:decidePolicyFor:decisionHandler:)
is called for the original URL request.WKWebView
'sURL
property is set to the original URL.The
WKNavigationDelegate
functionwebView(_:didStartProvisionalNavigation:)
is called for the original URL request.WKWebView
'sURL
property is set to the original URL.The
WKWebView
'sURL
property is updated by WebKit to the redirection URL. (You'll only know about this if you are key-value observing the property.)The
WKNavigationDelegate
functionwebView(_:decidePolicyFor:decisionHandler:)
is called for the redirected URL request.WKWebView
'sURL
property is then redirection URL.The
WKNavigationDelegate
functionwebView(_:didReceiveServerRedirectForProvisionalNavigation:)
is called.WKWebView
'sURL
property is the redirection URL.
(Note: On the iOS 11.0 simulator I have seen steps 3 and 4 reversed, with the URL
property unchanged in webView(_:decidePolicyFor:decisionHandler:)
, which actually seems like a sensible ordering, but I haven't observed this on a device.)
It seems like the webView(_:didReceiveServerRedirectForProvisionalNavigation:)
is built explicitly for the purpose of detecting redirects so is probably the preferred option, although the redirect could be possibly be inferred at steps 3 or 4 but only if you can be sure that there are no other causes of navigational change.

- 4,399
- 37
- 44
-
Underrated answer. The `didReceiveServerRedirectForProvisionalNavigation` should be the way to go in this case. – Rexam Sep 23 '22 at 08:04
After trying all the solutions, finally this one works for me using Swift 5 and WKWebView.This solution implements KVO for Swift
var webView: WKWebView?
var webViewObserver: NSKeyValueObservation?
override func viewDidAppear(_ animated: Bool) {
super.viewDidAppear(animated)
webView = WKWebView(frame: self.view.bounds)
webViewObserver = webView?.observe(\.url, options: .new, changeHandler: {
(currentWebView, _) in
// Here you go the new path
currentWebView.url
})
}
override func viewWillDisappear(_ animated: Bool) {
super.viewWillDisappear(animated)
webViewObserver?.invalidate()
}

- 151
- 1
- 4
-
This was the only solution that worked for me with my Vue 2 website where the page is not fully reloaded when pushing new paths to the Router – RyanG Feb 06 '23 at 16:09
Swift 5 Boom
Very easy way
func webView(_ webView: WKWebView, didReceiveServerRedirectForProvisionalNavigation navigation: WKNavigation!) {
if let url = webView.url?.absoluteString{
print("url = \(url)")
}
}

- 5,361
- 1
- 43
- 34
For me, using decidePolicyFor
navigation delegate's method didn't work.
It didn't work because WKNavigationDelegate's method
func webView(_ webView: WKWebView, decidePolicyFor navigationAction: WKNavigationAction, decisionHandler: @escaping (WKNavigationActionPolicy) -> Void)
will only be called when there is a full-page reload. To be able to catch all WKWebView's request URL changes, a Key-Value observer will have to be placed on the WKWebView's URL property.
First, in viewDidLoad add:
webView.addObserver(self, forKeyPath: "URL", options: .new, context: nil)
Second, add observeValue method
override func observeValue(forKeyPath keyPath: String?, of object: Any?, change: [NSKeyValueChangeKey : Any]?, context: UnsafeMutableRawPointer?) {
if keyPath == #keyPath(WKWebView.url) {
// Whenever URL changes, it can be accessed via WKWebView instance
let url = webView.url
}
}

- 3,838
- 28
- 26
-
-
1This answer actually helped me a lot! My delegate method are not called either because the web view is not doing a full page reload, but its url did change. Also refer to @fmnavarretem answer's KVO syntax, it is in my opinion easier to understand. Also don't forget removing the observer on `deinit` or `viewWillDisappear` – Daniel Hu Sep 16 '22 at 21:24
Credits to Sven: https://forums.developer.apple.com/thread/117073
If you are facing a situation that your WebView doesn't open a PDF file or simply the url resolves to nothing, because the WebView's redirect URL doesn't come through you can use WKUIDelegate
function webView(_:createWebViewWith:for:windowFeatures:)
to capture the failed call and load the request again like:
extension WebViewWrapper: WKUIDelegate {
func webView(_ webView: WKWebView, createWebViewWith configuration: WKWebViewConfiguration, for navigationAction: WKNavigationAction, windowFeatures: WKWindowFeatures) -> WKWebView? {
if navigationAction.targetFrame == nil || navigationAction.targetFrame?.isMainFrame == false {
webView.load(navigationAction.request)
}
return nil
}
}

- 1,048
- 2
- 14
- 22
Use this WKNavigationDelegate method. I got redirect url from sourceFrame.request
public func webView(_ webView: WKWebView, decidePolicyFor navigationAction: WKNavigationAction, decisionHandler: @escaping (WKNavigationActionPolicy) -> Swift.Void) {
let urlString = navigationAction.sourceFrame.request.url?.absoluteString ?? ""
print("\(urlString)")
decisionHandler(.allow)
}

- 77
- 10