Skip to main content

How to check the quality of a network connection

Using an NWPathMonitor and inspecting the value of NWPath.status, NWPath.isExpensive and NWPath.isConstrained can tell you what sort of connection you’re running on.

A couple of times I’ve been listening to ATP and Marco has mentioned there are APIs an app can use to check the quality of your network connection – for example, an app might choose to download podcasts over Wi-Fi but not cellular. These APIs have been present on iOS for a long time, but they’re also available on macOS.

I became curious about this when I was installing a Homebrew package while on a train, and Homebrew started its auto-updater. This is precisely the wrong time to do it, because I have a very unreliable connection – I want to spend what limited bandwidth I have installing the package I’m installing, not on updating Homebrew.

I wasn’t sure what API it was, so I decided to find out.


I struggled to find anything on Google, so I described this API to ChatGPT. It quickly pointed me at two items in Apple’s documentation:

The NWPath object has three attributes that are interesting:

I don’t have an immediate use for this API so this is mostly for idle curiosity, but I did write a small script to exercise this API – it monitors the network connection for a minute, and logs whether the network is up, and whether it’s expensive/constrained.

import Foundation
import Network

class NetworkStatusChecker {
    init() {
        let monitor = NWPathMonitor()
        monitor.pathUpdateHandler = { path in
            self.logCurrentStatus(path: path)
        }
        monitor.start(queue: DispatchQueue.global(qos: .background))
    }

    private func logCurrentStatus(path: NWPath) {
        if path.status == .satisfied {
            print("✅ We’re connected; isExpensive = \(path.isExpensive), isConstrained = \(path.isConstrained).")
        } else {
            print("❌ We’re not connected.")
        }
    }
}

let networkChecker = NetworkStatusChecker()

// Watch network changes for a minute
Thread.sleep(forTimeInterval: 60)

Now I know that “expensive” and “constrained” are the terminology that Apple uses, I can find other APIs that use it – for example, allowsExpensiveNetworkAccess which allows you to decide whether a URL session will fetch data over an expensive connection.