Developers
IP API and developer documentation
Get your public IP, inspect request details, or calculate a CIDR range. These endpoints require no account or API key.
Examples and response contract reviewed October 3, 2026.
Choose an endpoint
- GET /ip
- One IP address followed by a newline. Content type:
text/plain; charset=utf-8. - GET /json
- JSON address, request context and optional geolocation.
/api/ipis an alias. - GET /headers
- JSON containing
ip,headers,queryandpost./api/headersis an alias.
Use https://showip.net directly. The endpoints accept GET, HEAD and POST. HEAD returns response headers without a body. Prefer the explicit /ip path over the homepage, whose format depends on the request's Accept and User-Agent headers.
checkip accepts an IPv4 or IPv6 address in the query string, or a POST form field. A non-empty query value takes precedence over the form field. This selects an address to look up; it does not change the client's connection.
On /json and /api/ip, a non-empty network query parameter selects the CIDR response instead of the IP response. This parameter does not select a network on /ip or /headers.
POST form inspection supports application/x-www-form-urlencoded and multipart/form-data. Other body types, including JSON, are read and discarded rather than parsed into post. Do not upload files or secrets to debug a request.
Copyable code examples
curl: public IP
curl --fail --silent --show-error --max-time 10 https://showip.net/ip
Example output (documentation address)
192.0.2.10
Illustrative IPv4 output, followed by a newline. Without checkip, this is the address of the client running curl as seen by ShowIP. Use -4 or -6 to require one address family; the selected family must be available end to end.
curl: inspect JSON or calculate a network
curl --fail --silent --show-error --max-time 10 'https://showip.net/json?checkip=192.0.2.10'
curl --fail --silent --show-error --max-time 10 'https://showip.net/json?network=192.0.2.10%2F24'
checkip selects an address for lookup. network selects a different CIDR response shape and takes precedence over checkip on /json. The example address is reserved for documentation, so geolocation is normally absent.
JavaScript: Node.js 22+
const response = await fetch("https://showip.net/json", {
signal: AbortSignal.timeout(10_000),
});
if (!response.ok) {
throw new Error(`ShowIP HTTP ${response.status}: ${await response.text()}`);
}
const result = await response.json();
console.log(result.ip);
Save as showip.mjs and run node showip.mjs. This reports the Node process's network exit. A request from your backend does not discover the browser visitor's IP; cross-origin browser access is not part of this example.
Python 3: standard library
import json
from urllib.request import urlopen
with urlopen("https://showip.net/json", timeout=10) as response:
result = json.load(response)
print(result["ip"])
No extra package required. urllib raises HTTPError for HTTP failures and URLError for connection failures; handle these at your application's boundary. Geolocation fields are optional.
Go: standard library
package main
import (
"encoding/json"
"fmt"
"log"
"net/http"
"time"
)
func main() {
client := &http.Client{Timeout: 10 * time.Second}
response, err := client.Get("https://showip.net/json")
if err != nil { log.Fatal(err) }
defer response.Body.Close()
if response.StatusCode != http.StatusOK {
log.Fatalf("ShowIP HTTP %d", response.StatusCode)
}
var result struct { IP string `json:"ip"` }
if err := json.NewDecoder(response.Body).Decode(&result); err != nil {
log.Fatal(err)
}
fmt.Println(result.IP)
}
Save as main.go and run go run main.go. Unknown JSON fields are ignored. Use bounded retries in a long-running application; do not immediately repeat a rate-limited request.
IP JSON response
This illustrative response represents a direct request with no User-Agent and no matching geolocation record. Proxy details and optional fields differ on the live service. Treat absent fields as unavailable, and ignore unknown fields for forward compatibility.
{
"ip": "192.0.2.10",
"version": "IPv4",
"source": "checkip",
"remote_address": "198.51.100.20",
"host": "showip.net",
"user_agent": "",
"trusted_proxy_headers": false,
"geo_status": "not_found"
}
ip,version,source- Strings. The selected address,
IPv4orIPv6, and where it came from:checkip,x_forwarded_for,x_real_iporremote_addr. Development instances can also returndev_override. remote_address,host,user_agent- Strings describing the request. The socket peer can be ShowIP's reverse proxy, so
remote_addressis not necessarily the public client address. browser_name,browser_version,os- Optional strings parsed from User-Agent. They are hints supplied by the client, not verified device identity.
forwarded_for,forwarded_proto,trusted_proxy_headers- Optional string array and optional string, plus a boolean. These expose proxy context and whether proxy headers are trusted by this deployment. Forwarded values are not an authentication mechanism.
geo_status,geo- Status is normally
found,not_found,unavailableornot_configured. Missing geolocation is not an HTTP error. The optionalgeoobject can contain stringscontinent_code,continent_name,country_code,country_name,city,postal_code,time_zone,asn_organization; numericlatitude,longitude; and integerasn. Each field can be omitted. Location is approximate.
CIDR JSON response
/json?network=192.0.2.10%2F24 produces this shape. Large counts are decimal strings to avoid JavaScript integer precision loss. prefix_length is an integer; the other fields are strings. normalized_note is optional. IPv6 has no broadcast address; display-only fields may contain an explanatory value rather than an address.
{
"type": "cidr",
"input": "192.0.2.10/24",
"canonical_network": "192.0.2.0/24",
"version": "IPv4",
"prefix_length": 24,
"network_address": "192.0.2.0",
"first_address": "192.0.2.0",
"last_address": "192.0.2.255",
"netmask": "255.255.255.0",
"broadcast": "192.0.2.255",
"total_addresses": "256",
"usable_hosts": "254",
"normalized_note": "Normalized 192.0.2.10/24 to the canonical network 192.0.2.0/24."
}
Request-header JSON response
ip is the same object described above. headers, query and post are objects whose values are arrays of strings, including single values. Empty collections are {}. Header names use canonical capitalization. The following excerpt omits ip for readability:
{
"headers": {"Accept": ["application/json"], "Authorization": ["[redacted]"]},
"query": {"example": ["one", "two"]},
"post": {}
}
Errors, limits and retries
The current application limit is 200 requests per 60 seconds per client IP, shared across rate-limited public routes. People or servers sharing a NAT/VPN exit can share the limit. Configuration can change; this is not a guaranteed throughput allocation.
On HTTP 429, wait at least the number of seconds in Retry-After, then retry with backoff and jitter. Use timeouts, cache results where appropriate, and avoid continuous polling. Temporary network or server failures should not trigger an unbounded retry loop.
400:invalid ip,invalid cidrorcould not parse post form.405:method not allowed; theAllowheader lists supported methods.413:post body too large. POST bodies are limited to 2 MiB.429:too many requests, withRetry-After.500:could not resolve iporcould not calculate cidr. An upstream proxy can produce other error responses.
Application error bodies are plain text followed by a newline, including errors on JSON endpoints. Check the HTTP status before decoding JSON. POST form output keeps at most 100 values, ordered by field name, with each value truncated after 8,192 characters. Query values are also truncated after 8,192 characters in header inspection; non-sensitive header values are trimmed and truncated after 240 bytes. Truncated values end in ....
Privacy and redaction
Never send real credentials to a public request-inspection endpoint. The response redacts values whose field/header name is exactly Authorization, Cookie, Proxy-Authorization, Set-Cookie or X-CSRF-Token, ignoring case. This is a limited name-based list: password, token and custom API-key names are not automatically redacted.
Redaction in the response does not mean a secret was never transmitted. Query strings may also remain in browser history or infrastructure logs. Use made-up values when debugging.
Plain-text and JSON responses do not contain the site's advertising, map or browser analytics scripts. Requests still pass through the service and its operational metrics. Individual server request records are retained for 14 days, detailed statistics for 90 days, and daily summaries for two years; compact lifetime counters have no visitor identifiers. See the privacy policy for exact scope and backup exceptions.
Do the work in your own application
Use local libraries for IP arithmetic so your application does not need a network call for each calculation. DNS answers depend on the resolver and time of lookup.
- Python ipaddress: standard-library IPv4/IPv6 parsing, subnet membership, range summarization and network collapsing.
- Go net/netip: standard-library addresses and prefixes, containment and overlap checks.
- JavaScript ipaddr.js: third-party IPv4/IPv6 parsing and CIDR matching.
- Node.js node:dns: DNS record queries;
resolve*and OS-backedlookuphave different behavior. - Python dnspython: third-party record and reverse-DNS queries, including answer TTLs.
- Go net.Resolver: standard-library address, common record and reverse lookups; these methods do not expose DNS TTLs.
For browser and bot identification, see the language-specific user-agent parser libraries. These are external projects; check their license and supported versions before adopting them.