IP address
iOS development
macOS
Swift programming
networking

How to get my IP address programmatically on iOS/macOS?

System Design practice on Codemia

Work through 120+ system design problems with detailed solutions, from rate limiters to multi-region storage.

Practice system design

Introduction

On iOS and macOS, “my IP address” can mean two different things: the local address assigned to a network interface such as Wi‑Fi, or the public address seen by internet services. Those are retrieved in different ways. Local addresses come from system interfaces, while public addresses usually require asking an external service.

Decide Whether You Need Local or Public IP

The first question is what your app actually needs.

  • local IP is useful for devices on the same LAN
  • public IP is useful for diagnostics or internet-facing networking

These are not interchangeable. A phone on Wi‑Fi might have a local address like 192.168.x.x, while its public address is the one exposed by the router or carrier network.

Read Local Interface Addresses with getifaddrs

On Apple platforms, the standard low-level way to enumerate interface addresses is getifaddrs. You inspect each interface, filter for address families such as IPv4 and IPv6, and then choose the interface names you care about.

swift
1import Foundation
2
3func localIPAddresses() -> [String: String] {
4    var addresses: [String: String] = [:]
5    var ifaddr: UnsafeMutablePointer<ifaddrs>?
6
7    guard getifaddrs(&ifaddr) == 0, let firstAddr = ifaddr else {
8        return addresses
9    }
10
11    defer { freeifaddrs(ifaddr) }
12
13    for ptr in sequence(first: firstAddr, next: { $0.pointee.ifa_next }) {
14        let interface = ptr.pointee
15        let addrFamily = interface.ifa_addr.pointee.sa_family
16
17        guard addrFamily == UInt8(AF_INET) || addrFamily == UInt8(AF_INET6) else {
18            continue
19        }
20
21        let name = String(cString: interface.ifa_name)
22        var host = [CChar](repeating: 0, count: Int(NI_MAXHOST))
23
24        getnameinfo(
25            interface.ifa_addr,
26            socklen_t(interface.ifa_addr.pointee.sa_len),
27            &host,
28            socklen_t(host.count),
29            nil,
30            0,
31            NI_NUMERICHOST
32        )
33
34        addresses[name] = String(cString: host)
35    }
36
37    return addresses
38}
39
40print(localIPAddresses())

This returns a dictionary keyed by interface name such as en0 or pdp_ip0.

Pick the Interface You Actually Want

On Apple devices, several interfaces may exist at once. Typical examples include:

  • 'en0 for Wi‑Fi on many devices'
  • 'pdp_ip0 for cellular data on iPhone'
  • 'lo0 for loopback'

A helper that prefers Wi‑Fi and then cellular is often practical:

swift
1import Foundation
2
3func preferredLocalIPAddress() -> String? {
4    let addresses = localIPAddresses()
5    return addresses["en0"] ?? addresses["pdp_ip0"]
6}
7
8print(preferredLocalIPAddress() ?? "No address found")

This is usually better than returning the first interface blindly, because the first one may be loopback or an interface you do not actually want.

Public IP Requires an External Service

Your app cannot infer its public internet address purely from local interfaces in the general case. NAT and carrier networks mean the public address is often owned by a gateway, not by the device interface directly.

The normal solution is to query a service that returns the caller’s public IP.

swift
1import Foundation
2
3func fetchPublicIPAddress() async throws -> String {
4    let url = URL(string: "https://api.ipify.org")!
5    let (data, _) = try await URLSession.shared.data(from: url)
6    return String(decoding: data, as: UTF8.self)
7}

You can call it from an async context:

swift
1Task {
2    do {
3        let ip = try await fetchPublicIPAddress()
4        print(ip)
5    } catch {
6        print("Failed to fetch public IP: \(error)")
7    }
8}

This is the simplest and most reliable public-IP approach for most apps.

IPv4 vs IPv6

Apple platforms fully support IPv6, and many networks now prefer it. That means your local-IP logic should not assume IPv4 only unless the app explicitly requires it.

If you only want IPv4, filter for AF_INET. If you want to be network-agnostic, keep both AF_INET and AF_INET6 and decide later which one is appropriate for the use case.

Common Pitfalls

The most common mistake is asking for “the IP address” without deciding whether local or public IP is required. Another is returning the first interface found, which often produces loopback or an irrelevant address instead of Wi‑Fi or cellular. Developers also sometimes try to derive the public address from device interfaces, which does not work reliably behind NAT. A final issue is ignoring IPv6 and hardcoding IPv4-only assumptions into code that will run on modern Apple networks.

Summary

  • Local and public IP addresses are different and require different techniques.
  • Use getifaddrs to enumerate local interface addresses on iOS and macOS.
  • Prefer a specific interface such as en0 or pdp_ip0 rather than taking the first result blindly.
  • Public IP usually requires an external service queried through URLSession.
  • Keep IPv6 in mind unless the use case is explicitly IPv4-only.

Related reading
Course
Beginner
27 lessons
10 hours
System Design Fundamentals

Build a strong foundation in designing scalable, reliable distributed systems.

View the course
Track what you have practised

A free account saves your progress, solutions and study plan across every problem on Codemia.

System Design practice on Codemia

Work through 120+ system design problems with detailed solutions, from rate limiters to multi-region storage.

Practice system design

All Rights Reserved.