C# IPAddress and IPNetwork
last modified October 17, 2026
In this article we show how to work with IP addresses, networks, and endpoints in C#.
An IP address identifies a network interface on an IP network. IPv4
addresses have 32 bits and are written as four decimal numbers, such as
192.168.0.10. IPv6 addresses have 128 bits and are written as
eight groups of hexadecimal digits, such as 2001:db8::1; the
:: stands for a run of zero groups.
The System.Net namespace contains the IPAddress
class for addresses, the IPNetwork structure for address ranges
in CIDR notation, and the IPEndPoint class for an address
combined with a port.
C# IPAddress parse
The IPAddress.Parse method converts a string into an address and
throws a FormatException if the string is invalid. The
TryParse method returns false instead.
using System.Net;
string[] inputs = ["192.168.0.10", "2001:db8::1", "::1", "10.0.0.256", "localhost", "fe80::1%2"];
foreach (var input in inputs)
{
if (IPAddress.TryParse(input, out IPAddress? ip))
{
Console.WriteLine($"{input,-14} {ip.AddressFamily,-15} loopback: {IPAddress.IsLoopback(ip)}");
}
else
{
Console.WriteLine($"{input,-14} not an IP address");
}
}
We try to parse several strings.
Console.WriteLine($"{input,-14} {ip.AddressFamily,-15} loopback: {IPAddress.IsLoopback(ip)}");
The AddressFamily property tells IPv4 (InterNetwork)
and IPv6 (InterNetworkV6) addresses apart. The
IsLoopback method checks for the loopback addresses
127.0.0.0/8 and ::1.
$ dotnet run 192.168.0.10 InterNetwork loopback: False 2001:db8::1 InterNetworkV6 loopback: False ::1 InterNetworkV6 loopback: True 10.0.0.256 not an IP address localhost not an IP address fe80::1%2 InterNetworkV6 loopback: False
The number 256 is out of range for an IPv4 address. A host name such as
localhost is not an address; it must be resolved with the
Dns class. The %2 suffix is the scope id of a
link-local IPv6 address.
C# IPAddress properties
In the next example, we look at the bytes of an address, convert between IPv4 and IPv6, and use the predefined addresses.
using System.Net;
IPAddress ip = IPAddress.Parse("192.168.0.10");
byte[] bytes = ip.GetAddressBytes();
Console.WriteLine(string.Join(".", bytes));
Console.WriteLine(Convert.ToHexString(bytes));
var fromBytes = new IPAddress([10, 0, 0, 1]);
Console.WriteLine(fromBytes);
IPAddress mapped = ip.MapToIPv6();
Console.WriteLine(mapped);
Console.WriteLine(mapped.IsIPv4MappedToIPv6);
Console.WriteLine(mapped.MapToIPv4());
IPAddress v6 = IPAddress.Parse("2001:0db8:0000:0000:0000:0000:0000:0001");
Console.WriteLine(v6);
IPAddress link = IPAddress.Parse("fe80::1c3b:5e0c:5371:bddc%2");
Console.WriteLine($"{link.IsIPv6LinkLocal} scope {link.ScopeId}");
Console.WriteLine(IPAddress.Any);
Console.WriteLine(IPAddress.IPv6Any);
Console.WriteLine(IPAddress.Broadcast);
We work with IPv4 and IPv6 addresses.
byte[] bytes = ip.GetAddressBytes();
Console.WriteLine(string.Join(".", bytes));
Console.WriteLine(Convert.ToHexString(bytes));
var fromBytes = new IPAddress([10, 0, 0, 1]);
The GetAddressBytes method returns the address in network byte
order; four bytes for IPv4 and sixteen for IPv6. An address can be created
from bytes as well.
IPAddress mapped = ip.MapToIPv6(); Console.WriteLine(mapped); Console.WriteLine(mapped.IsIPv4MappedToIPv6); Console.WriteLine(mapped.MapToIPv4());
An IPv4 address can be represented as an IPv4-mapped IPv6 address.
Dual-mode sockets, which accept both IPv4 and IPv6 connections, report IPv4
clients in this form, for instance ::ffff:192.168.0.10. The
MapToIPv4 method converts it back.
IPAddress v6 = IPAddress.Parse("2001:0db8:0000:0000:0000:0000:0000:0001");
Console.WriteLine(v6);
IPv6 addresses are printed in the shortest form: leading zeros are dropped and
the longest run of zero groups is replaced with ::.
Console.WriteLine(IPAddress.Any); Console.WriteLine(IPAddress.IPv6Any); Console.WriteLine(IPAddress.Broadcast);
The Any addresses are used by servers to listen on all network
interfaces.
$ dotnet run 192.168.0.10 C0A8000A 10.0.0.1 ::ffff:192.168.0.10 True 192.168.0.10 2001:db8::1 True scope 2 0.0.0.0 :: 255.255.255.255
C# IPNetwork
The IPNetwork structure, added in .NET 8, represents a range of
addresses in CIDR notation, for instance 192.168.0.0/16. The
number after the slash is the prefix length: the number of leading bits that
are the same for all addresses of the network. In the following example, we
check whether addresses belong to the private address ranges.
using System.Net;
IPNetwork[] privateNetworks =
[
IPNetwork.Parse("10.0.0.0/8"),
IPNetwork.Parse("172.16.0.0/12"),
IPNetwork.Parse("192.168.0.0/16"),
IPNetwork.Parse("fc00::/7")
];
string[] addresses = ["192.168.1.20", "172.20.5.1", "172.32.0.1", "8.8.8.8", "fd12:3456::1"];
foreach (var a in addresses)
{
IPAddress ip = IPAddress.Parse(a);
int idx = Array.FindIndex(privateNetworks, n => n.Contains(ip));
string res = idx >= 0 ? $"private ({privateNetworks[idx]})" : "public";
Console.WriteLine($"{a,-14} {res}");
}
var net = IPNetwork.Parse("192.168.0.77/24");
Console.WriteLine($"{net} base: {net.BaseAddress}, prefix: {net.PrefixLength}");
Console.WriteLine(IPNetwork.TryParse("192.168.0.0/33", out _));
We define the private IPv4 networks from RFC 1918 and the IPv6 unique local network.
int idx = Array.FindIndex(privateNetworks, n => n.Contains(ip));
string res = idx >= 0 ? $"private ({privateNetworks[idx]})" : "public";
The Contains method checks if an address belongs to the network.
We look for the first network that contains the address.
Note that IPNetwork is a structure. If we used
FirstOrDefault to find the network, it would return the default
value of the structure, 0.0.0.0/0, instead of null
when there is no match; every address would look private. This is why we use
Array.FindIndex, which returns -1 when nothing is found.
var net = IPNetwork.Parse("192.168.0.77/24");
Console.WriteLine($"{net} base: {net.BaseAddress}, prefix: {net.PrefixLength}");
The BaseAddress and PrefixLength properties give the
parts of the network. If the given address has bits set beyond the prefix,
.NET 10 clears them, so 192.168.0.77/24 becomes
192.168.0.0/24.
Console.WriteLine(IPNetwork.TryParse("192.168.0.0/33", out _));
An IPv4 prefix cannot be longer than 32 bits, so parsing fails.
$ dotnet run 192.168.1.20 private (192.168.0.0/16) 172.20.5.1 private (172.16.0.0/12) 172.32.0.1 public 8.8.8.8 public fd12:3456::1 private (fc00::/7) 192.168.0.0/24 base: 192.168.0.0, prefix: 24 False
The 172.16.0.0/12 network spans the addresses from
172.16.0.0 to 172.31.255.255, so
172.32.0.1 is public.
C# IPEndPoint
An IPEndPoint is an IP address combined with a port number. It is
used by sockets to specify where to connect or listen.
using System.Net;
IPEndPoint ep1 = IPEndPoint.Parse("192.168.0.10:8080");
IPEndPoint ep2 = IPEndPoint.Parse("[2001:db8::1]:443");
Console.WriteLine($"{ep1.Address} port {ep1.Port}");
Console.WriteLine($"{ep2.Address} port {ep2.Port}");
var ep3 = new IPEndPoint(IPAddress.Loopback, 5000);
Console.WriteLine(ep3);
Console.WriteLine(IPEndPoint.TryParse("example.com:80", out _));
We parse endpoints from strings and create one from an address and a port.
IPEndPoint ep2 = IPEndPoint.Parse("[2001:db8::1]:443");
An IPv6 address must be enclosed in square brackets; otherwise its colons could not be told apart from the port separator.
Console.WriteLine(IPEndPoint.TryParse("example.com:80", out _));
An IPEndPoint requires an IP address. For a host name, use the
DnsEndPoint class.
$ dotnet run 192.168.0.10 port 8080 2001:db8::1 port 443 127.0.0.1:5000 False
Source
IPAddress class - language reference
IPNetwork struct - language reference
In this article we have worked with IP addresses, networks, and endpoints in C#.
Author
List all C# tutorials.