# What is a private IP address? Private, reserved, and bogon addresses, explained

_2026-09-11 · Boundstone (https://boundstone.io/blog/what-is-a-private-ip)_


You typed "what is a private IP address" into a search box, and there's a decent chance you did it because one turned up somewhere it had no business being — a request log, a signup record, an `X-Forwarded-For` header on traffic that came in off the open internet. A private IP address is one drawn from a range the internet's governing bodies set aside for use *inside* a network rather than *across* it. Your laptop has one. Your home router has one. Neither should ever be the origin of a request that reached your public API. When one is, something is broken or someone is lying — telling those apart is the point here.

## The private ranges, and how they got that way

In 1996, RFC 1918 carved three blocks out of IPv4 space and declared them off-limits for the public internet. Any organization can use them internally without asking anyone:

- `10.0.0.0/8` — one huge block, 16.7 million addresses
- `172.16.0.0/12` — the middle one everybody forgets (it's `172.16.x.x` through `172.31.x.x`, not all of `172.*`)
- `192.168.0.0/16` — the one on the sticker under your router

Two more ranges behave privately without being RFC 1918. `127.0.0.0/8` is loopback — `127.0.0.1` is your own machine talking to itself. `169.254.0.0/16` is link-local: the range a device assigns itself when it asks for a DHCP lease and nobody answers. If you've seen a `169.254.*` address, a network handshake failed somewhere.

The common thread is that routers on the public internet are expected to drop these. They are addresses for a private conversation, and they don't survive the trip across a public network.

## Reserved and bogon addresses

Private is one flavor of "not a normal public address." There are others. IANA marks whole ranges as *reserved* for specific jobs — `192.0.2.0/24` and its siblings are documentation ranges (the IPs you put in a blog post so you don't accidentally name a real host), `255.255.255.255` is broadcast, `0.0.0.0` is "this network."

A *bogon* is the umbrella term: any address that should never appear as the source of traffic on the public internet — private ranges, reserved ranges, and blocks not yet allocated to anyone. The name is short for "bogus." A packet claiming to come from a bogon reached you carrying a return address that cannot be real.

## Why a private or bogon source IP is a red flag

Here is the part that matters if you run anything public-facing. When a request arrives at your API and the source IP — or the client IP your proxy hands you in a header — falls in a private or bogon range, there are only two explanations, and neither is good:

1. **Misconfiguration.** A load balancer or reverse proxy is forwarding its own internal address instead of the real client's, or an `X-Forwarded-For` header is being read without being set. Your geo rules, rate limits, and audit logs are now keyed on garbage.
2. **Spoofing.** Someone is setting a client-IP header by hand to `127.0.0.1` or `10.0.0.1`, betting that a downstream service treats "internal-looking" addresses as trusted. This is a standard trick for slipping past IP allowlists.

Either way, a private or bogon address in a field that is supposed to hold a public client IP is a signal to distrust that record — not to geolocate it, because there is nothing real to locate.

## Classify them yourself first

You do not need a service to answer "is this address private." The standard library does it. In Python, `ipaddress` has shipped since 3.3:

```python
import ipaddress

ip = ipaddress.ip_address("192.168.1.10")
print(ip.is_private)     # True
print(ip.is_loopback)    # False
print(ip.is_link_local)  # False
print(ip.is_global)      # False  <- the one to check for public traffic
```

For a lot of cases that is the whole job — `is_global` is False and you are done. Node's `net` module is thinner: it validates the address and tells you the version, but it will not classify the range for you.

```javascript
const net = require("node:net");

net.isIP("192.168.1.10"); // 4  (valid IPv4)
net.isIP("::1");          // 6  (valid IPv6)
net.isIP("not-an-ip");    // 0  (invalid)
```

That gap — valid IP versus *what kind* of IP — is where you either write the range checks by hand or reach for something that already has them. There is a longer walk-through for [Node.js](/blog/validate-ip-nodejs) and the [Python version](/blog/validate-ip-python).

## Where Boundstone fits

If you are checking IPs in one script, use the stdlib. If you are checking them across a fleet of services in three languages and you would rather have one answer that every service agrees on, that is the API layer:

```bash
curl -s https://api.boundstone.io/v1/verify/ip \
  -H "Authorization: Bearer bs_live_YOUR_KEY" \
  -H "Content-Type: application/json" \
  -d '{"ip":"192.168.1.10"}'
```

```json
{
  "valid": true,
  "version": 4,
  "normalized": "192.168.1.10",
  "classification": "private",
  "is_public": false,
  "is_bogon": true,
  "checks": {
    "performed": ["format", "version", "range_classification"],
    "not_performed": ["geolocation", "asn", "hosting_datacenter", "proxy_vpn_tor", "reputation"]
  }
}
```

Read the `not_performed` array, because it is the honest part. Boundstone classifies the range — that is arithmetic on the address, it costs nothing, and it is in the free tier. It does **not** geolocate the address, look up the ASN, tell you whether it is a datacenter, or flag it as a proxy, VPN, or Tor exit. That is IP *intelligence*, it needs licensed data, and it is not shipped. We would rather hand you an honest answer with an empty middle than a confident guess. When Boundstone says an address is public and valid, you can trust it because you can see exactly what "valid" did and did not cover.

You can run the classifier with no key and no signup at the [free IP validator](/tools/ip-validator).

## The short version

- A **private** address (`10/8`, `172.16/12`, `192.168/16`), a loopback (`127/8`), or a link-local (`169.254/16`) address belongs inside a network. A **bogon** is any address that cannot legitimately be a public source.
- A private or bogon address arriving as a *public* client IP means misconfiguration or spoofing. Distrust the record; do not try to locate it.
- Classify with the stdlib first — Python's `ipaddress.is_global` is often all you need.
- Reach for the API's `/v1/verify/ip` when you want one classification contract across every service — [try it keyless first](/tools/ip-validator) — and read `checks.not_performed` so you know precisely what the "valid" is worth.
