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
WKNavigationDelegatefunctionwebView(_:decidePolicyFor:decisionHandler:)is called for the original URL request.WKWebView'sURLproperty is set to the original URL.The
WKNavigationDelegatefunctionwebView(_:didStartProvisionalNavigation:)is called for the original URL request.WKWebView'sURLproperty is set to the original URL.The
WKWebView'sURLproperty is updated by WebKit to the redirection URL. (You'll only know about this if you are key-value observing the property.)The
WKNavigationDelegatefunctionwebView(_:decidePolicyFor:decisionHandler:)is called for the redirected URL request.WKWebView'sURLproperty is then redirection URL.The
WKNavigationDelegatefunctionwebView(_:didReceiveServerRedirectForProvisionalNavigation:)is called.WKWebView'sURLproperty 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