IP address converter

An IPv4 address is a 32-bit number, and dotted decimal is only one way to write it. 192.0.2.1 is also the integer 3221225985, the hex value 0xC0000201, and the binary 11000000.00000000.00000010.00000001. Paste any of those forms below and this converter returns all the others, in your browser, with nothing uploaded.

Enter any form and SubnetKit shows all the others.

Dotted decimal192.0.2.1
32-bit integer3221225985
Hexadecimal0xC0000201
Octal (per octet)300.0.2.1
Binary (dotted)11000000.00000000.00000010.00000001
Binary (32 bits)11000000000000000000001000000001
Try:

How does the conversion actually work?

The four numbers in a dotted-decimal address are not four separate values. They are four base-256 digits of one number, which is why the place values are 256 cubed, 256 squared, 256 and 1: that is 16777216, 65536, 256 and 1.

So 192.0.2.1 becomes 192 x 16777216, plus 0 x 65536, plus 2 x 256, plus 1. That is 3221225472 + 0 + 512 + 1, or 3221225985. Going the other way you divide by each place value in turn and keep the remainder: 3221225985 divided by 16777216 is 192 remainder 512, then 512 divided by 65536 is 0, 512 divided by 256 is 2, and 0 remains, which reassembles 192.0.2.1.

Binary and hex need no arithmetic at all, only regrouping the same bits. Each octet is exactly 8 bits, so it is always exactly two hex digits. 192 is 11000000 in binary and C0 in hex, which is why the integer, the hex value and the binary string are three views of one number rather than three conversions.

Why do IP addresses show up as integers in databases and code?

Three practical reasons, and they all come down to the fact that an integer is four bytes while a dotted string is up to fifteen.

Sorting is the first. Sorted as text, 10.0.0.10 comes before 10.0.0.9, because character comparison stops at the 1 versus the 9. Sorted as integers they land in the correct order automatically. Second, range tests become trivial: asking whether an address falls inside a CIDR block is a single BETWEEN against the block’s first and last integer, which an index can serve. That is exactly how GeoIP databases and firewall rule engines are built. Third, storage and comparison are cheaper at scale, which matters when a table holds hundreds of millions of rows of log data.

Binary is the form to reach for when you are reasoning about masks instead. A prefix length is literally a count of leading 1 bits, so seeing an address and its mask side by side in binary makes the network and host split visible rather than arithmetic. The subnet calculator does that split for you, and the subnet mask guide walks through reading one.

Why is 010.0.0.1 not the same as 10.0.0.1?

Because of a rule most people never learn: in the classic C library parser inet_aton, a part with a leading zero is octal and a part beginning 0x is hexadecimal. So 010 is decimal 8, and 010.0.0.1 resolves to 8.0.0.1. The same parser also accepts fewer than four parts, treating the last one as covering the remaining bytes, so 127.1 is a valid way to write 127.0.0.1.

This matters beyond trivia. Libraries disagree about whether to accept those forms, so a validator and the network stack underneath it can read the same string as two different addresses. That mismatch is a well-known source of filter-bypass bugs: a check that rejects 127.0.0.1 may happily pass 0177.0.0.1 or 2130706433, both of which the connection then makes to localhost anyway.

The defensive habit is to normalise before you compare. Convert whatever you were given to a single canonical form, the 32-bit integer is the easiest, and validate that. Never compare address strings.

IPv4 address conversion reference table

Common addresses in all four representations. Every value here was computed from the address using the arithmetic above.

Dotted decimal32-bit integerHexadecimalBinary
192.0.2.132212259850xC000020111000000.00000000.00000010.00000001
198.51.100.1033252567140xC633640A11000110.00110011.01100100.00001010
203.0.113.534058037810xCB00710511001011.00000000.01110001.00000101
10.0.0.11677721610x0A00000100001010.00000000.00000000.00000001
127.0.0.121307064330x7F00000101111111.00000000.00000000.00000001
255.255.255.25542949672950xFFFFFFFF11111111.11111111.11111111.11111111

The 192.0.2.0/24, 198.51.100.0/24 and 203.0.113.0/24 blocks above are reserved by RFC 5737 for documentation, which is why examples on this site use them rather than addresses that belong to somebody.

Do this from the terminal

The same reference data is a keyless JSON endpoint, and there are good local tools that need no network at all.

# decimal to 32-bit integer and back, in plain shell:
python3 -c 'import ipaddress; print(int(ipaddress.IPv4Address("192.0.2.1")))'
python3 -c 'import ipaddress; print(ipaddress.IPv4Address(3221225985))'

# check which reserved block an address falls in:
curl -s https://subnetkit.dev/api/reserved.json | jq -r '.ipv4.blocks[].cidr'

Python's ipaddress module is on almost every machine already and is the shortest route to the integer form.

The SubnetKit API is the one to reach for in a build step or a script. It has no key and no rate limit, and the full schema is in the OpenAPI document.

Frequently asked questions

How do I convert an IP address to a 32-bit integer?

Multiply each octet by its place value and add them: octet1 x 16777216 + octet2 x 65536 + octet3 x 256 + octet4. For 192.0.2.1 that is 3221225472 + 0 + 512 + 1, which is 3221225985. The place values are 256 cubed, 256 squared, 256 and 1, because each octet is one base-256 digit.

How do I convert an IP to binary?

Write each octet as 8 bits and keep the dots for readability. 192 is 11000000, 0 is 00000000, 2 is 00000010 and 1 is 00000001, so 192.0.2.1 is 11000000.00000000.00000010.00000001. There are always exactly 32 bits, because each of the four octets is always padded to 8.

What is an IP address in hexadecimal?

It is the same 32-bit value written in base 16, two hex digits per octet. 192.0.2.1 is 0xC0000201, because 192 is C0, 0 is 00, 2 is 02 and 1 is 01. Hex is the form you meet in packet captures, memory dumps and code that stores addresses as integers.

Can I convert an integer back to an IP?

Yes. Paste the integer, hex value or binary and the converter returns the dotted-decimal address plus every other representation. Going that way by hand means dividing by 16777216, 65536 and 256 in turn and taking the remainder each time.

Why do IP addresses appear as integers in databases and logs?

Because an integer is four bytes, sorts and compares correctly, and lets a range test be a simple BETWEEN. A dotted string is up to fifteen bytes, sorts lexicographically so 10.0.0.9 lands after 10.0.0.10, and cannot be range-checked without parsing. GeoIP databases and firewall rule engines store integers for exactly this reason.

Why is 010.0.0.1 not the same as 10.0.0.1?

Because a leading zero means octal in the classic inet_aton parser, so 010 is decimal 8 and the address resolves to 8.0.0.1. The same function accepts hex with a 0x prefix and shortened forms with fewer than four parts. Different libraries disagree about whether to allow this, which has produced real security bugs where a validator and the network stack read the same string as different addresses.

How many IPv4 addresses are there in total?

Exactly 2 to the power of 32, which is 4,294,967,296. The highest is 255.255.255.255, or 4294967295 as an integer, since counting starts at 0.0.0.0. Large blocks of that space are reserved and never appear as ordinary host addresses.

Sources