23

I am using Xcode 6 for an iOS App with Swift. I have got a simple ViewController with an embedded UIWebView. You can find the code below. Now I want to change the User-Agent HTTP header. I tried to use the setValue method of NSURLRequest but it didn't work (see uncommented line). Does anyone know how to do that?

import UIKit

class WebViewController: UIViewController {

    @IBOutlet weak var webView: UIWebView!

    override func viewDidAppear(animated: Bool) {
        var url = NSURL(string: "https://www.samplepage.com")

        var request = NSMutableURLRequest(URL: url)

        // request.setValue("Custom-Agent", forHTTPHeaderField: "User-Agent")

        webView.loadRequest(request)
    }
}
Pang
  • 9,564
  • 146
  • 81
  • 122
sebbo
  • 2,929
  • 2
  • 20
  • 37

3 Answers3

42

This will change the agent of any call made through the 'normal' stack.

Swift 2:

NSUserDefaults.standardUserDefaults().registerDefaults(["UserAgent": "Custom-Agent"])

Swift 3:

UserDefaults.standard.register(defaults: ["UserAgent": "custom value"])
Kevin R
  • 8,230
  • 4
  • 41
  • 46
sebbo
  • 2,929
  • 2
  • 20
  • 37
  • 4
    One important caveat here: this will modify the user-agent for all http requests generated by your app (at least those that are using the URL Loading System -- NSURLConnection and friends). This includes all UIWebViews in your app, not only a specific one. – noamtm Aug 12 '15 at 09:15
  • 2
    @FarhadMammadli `registerDefaults` is usually called in `didFinishLaunchingWithOptions` within the `AppDelegate` – Daniel May 10 '16 at 12:54
  • 1
    in Swift 3, it's `UserDefaults.standard.register(defaults: ["UserAgent": "whatever"])` – CupawnTae Oct 21 '16 at 13:50
  • 2
    why are we setting `UserAgent` when the HTTP header has a hyphen in it like `User-Agent`? Is there a typo in the answer or does UserDefaults somehow convert this to the correct header name? Edit: tried it out and looks like `UserAgent` is in fact correct. – ae14 Mar 15 '17 at 16:50
  • Is there a way to exclude the custom user-agent for certain hosts or use it explicitly for a certain host? My problem is, that when using it via registerDefaults, the facebook like-button no longer works as it seems to check for the User-Agent. As soon as I comment out the registerDefaults line faceboooks works. My first attempt was to check the request in `webView(UIWebView, shouldStartLoadWith: URLRequest, navigationType: UIWebViewNavigationType)` but it seems that the User-Agent will always set back to the default one. – MatzeLoCal Oct 09 '17 at 10:42
  • Be careful with that one... I just found this line of code to be responsible for preventing Google Mobile Ads to load. You should rather extend the existing user agent as described in @PassKit's answer. – flocbit Aug 28 '19 at 10:37
  • Can someone confirm that this is still working for iOS >= 15. From what I see, the `User-Agent` looks as follow, and cannot globally be changed for the entire app. `/ CFNetwork/ Darwin/` – geohei Mar 06 '22 at 06:59
29

If you want to append to the existing user agent string (useful for helping dynamic webpages that adapt to the user agent), then you can use the following.

let userAgent = UIWebView().stringByEvaluatingJavaScriptFromString("navigator.userAgent")! + " Custom-Agent"
NSUserDefaults.standardUserDefaults().registerDefaults(["UserAgent" : userAgent])
PassKit
  • 12,231
  • 5
  • 57
  • 75
  • 1
    you should not force-unwrap the user agent, using `if let` would be better. Also, creating a UI element to retrieve a property is also not the best approach and will lead to problems (for example when Unit testing) – Daniel May 10 '16 at 12:58
0

To switch between fake user agent and original one, you can use my function:

Swift 4:

var originalUserAgent:String? = nil
let fakeUserAgent = "Mozilla/5.0 (Windows NT 10.0; WOW64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/53.0.2785.143 Safari/537.36"

func setUserAgent(fake: Bool) {
    if originalUserAgent == nil {
        originalUserAgent = UIWebView().stringByEvaluatingJavaScript(from: "navigator.userAgent")
    }

    guard let originalUserAgent = originalUserAgent else {
        return
    }

    if (fake) {
        UserDefaults.standard.register(defaults: ["UserAgent": fakeUserAgent])
    } else {
        UserDefaults.standard.register(defaults: ["UserAgent": originalUserAgent])
    }
}

// then use
setUserAgent(fake: false)
Bartosz Hernas
  • 1,130
  • 1
  • 9
  • 17