WorldIP API — Developer Documentation
A fast, JSON REST API over the same global IP intelligence that powers worldip.io — IP profiles, ASN & organization ownership, reverse/forward DNS, VPN/proxy classification, trust scoring and live BGP routing events. Built on a worldwide adaptive-scanning fleet processing over a billion record updates a day, with sub-second, edge-cached responses.
Getting started
Every endpoint lives under a single HTTPS base URL and returns application/json.
A successful response is 200 OK with the record at the top level; errors use
standard HTTP status codes with a JSON error body (see Errors).
| Base URL | https://worldip.io |
|---|---|
| Version | v1 (path-versioned) |
| Format | JSON, UTF-8. Slashes are unescaped. |
| Methods | GET (all data endpoints). OPTIONS is accepted for CORS preflight. |
| Auth | Authorization: Bearer YOUR_KEY or ?key=YOUR_KEY |
Quickstart — one full IP profile
curl -s https://worldip.io/api/v1/ext/lookup/8.8.8.8 \
-H "Authorization: Bearer YOUR_KEY"
Authentication
Present your key on every keyed request, either as a Bearer token (preferred for
server-to-server) or the key query parameter (handy for quick tests).
Authorization: Bearer YOUR_KEY
https://worldip.io/api/v1/ext/lookup/8.8.8.8?key=YOUR_KEY
Scopes
Each key carries one or more scopes. A request is rejected with 403 forbidden_scope
if its key lacks the scope the endpoint requires.
| Scope | Grants |
|---|---|
ext:read | IP profile lookup + forward DNS (the IP Intelligence endpoints). |
pulse:read | The keyed Pulse event stream + summary. |
* | All scopes (issued only to trusted / enterprise integrations). |
Key locking (optional)
A key can be pinned so a leaked value is useless elsewhere:
- Origin lock — restricts browser calls to one site
(enforced whenever the request carries an
Origin/Referer). Mismatch →403 origin_not_allowed. - IP allow-list — restricts calls to specific caller IPs,
the strongest server-to-server lock. Off-list →
403 ip_not_allowed.
IP profile lookup
One consolidated intelligence profile for an IPv4 address: PTR, ASN, organization, country,
CIDR, trust score, VPN/proxy/Tor/datacenter classification (with a decay-scored
residential & mobile proxy verdict), BGP route + recent routing anomalies, hosted
domains, and Web3 roles. The heavy assembly is cached per IP for one hour and served from
the edge, so repeat lookups return in milliseconds
(X-Ext-Cache: HIT / MISS).
| Path parameter | Description |
|---|---|
ipv4 | Dotted-quad IPv4 address, e.g. 8.8.8.8. Invalid input → 400 bad_ip. |
curl -s https://worldip.io/api/v1/ext/lookup/8.8.8.8 \
-H "Authorization: Bearer YOUR_KEY"
{
"ip": "8.8.8.8",
"reserved": false,
"reserved_note": null,
"ptr": "dns.google",
"asn": { "number": 15169, "name": "Google LLC" },
"org": { "name": "Google LLC", "slug": "google-llc", "category": "hosting" },
"country": { "code": "US", "name": "United States" },
"cidr": "8.8.8.0/24",
"trust": { "score": 92, "band": "Trusted", "color": "#3fb950" },
"web3": [],
"bgp": {
"prefix": "8.8.8.0/24",
"origin_asn": 15169,
"moas": false,
"anomalies": []
},
"forward_dns": null,
"flags": [
{ "key": "hosting", "label": "Hosting/DC", "level": "warn", "emoji": "🖥️",
"title": "Datacenter / hosting network - server addresses, not home connections." }
],
"classification": {
"is_vpn": false,
"is_proxy": false,
"is_relay": false,
"is_anonymous": false,
"access_type": "hosting",
"proxy_density_30d": null,
"vpn_density_30d": null,
"is_tor": false,
"is_datacenter": true,
"is_vpn_likely": false,
"verdict": "hosting",
"confidence": "high",
"score": 0,
"source": "worldip-classification"
},
"grip": null,
"grip_attribution": null,
"links": {
"ip": "https://worldip.io/8.8.8.8",
"asn": "https://worldip.io/asn/AS15169",
"org": "https://worldip.io/org/google-llc"
},
"generated_at": "2026-07-17T00:45:12+00:00"
}
Response fields
| Field | Type | Notes | Tier |
|---|---|---|---|
ip | string | Canonical IPv4 echoed back. | Free |
ptr | string | null | Reverse-DNS hostname. | Free |
asn | object | null | number, name. | Free |
org | object | null | name, slug, category. | Free |
country | object | null | ISO-2 code + name. | Free |
cidr | string | null | Allocated block this IP sits in. | Free |
links | object | Canonical worldip.io URLs for the IP/ASN/org. | Free |
forward_dns | object | null | Domains hosted on the IP (sample + count). Warms via the Forward DNS endpoint. | Basic |
classification | object | VPN / proxy / Tor / datacenter, access_type, residential/mobile-proxy verdict, confidence, score. | Pro |
trust | object | null | score 0-100, band, color. | Pro |
flags | array | Human-readable risk chips (Tor exit, Proxy/VPN, Hosting/DC, Malware). | Pro |
bgp | object | null | prefix, origin_asn, moas, recent anomalies[]. | Business |
web3 | array | Blockchain node roles hosted on the IP (chain + role). | Business |
generated_at | string | ISO-8601 UTC timestamp of assembly. | Free |
classification.verdict becomes
residential_proxy with is_proxy: true and a decay-scored
confidence that fades as the observation ages — the signal ipinfo/IPQS-class
vendors charge premium rates for. Unlocked on the Pro tier.
Forward DNS
The forward-DNS view of an IP: the domains currently hosted on it, plus the registerable domain and a hosted-domain count. The complement to the reverse (PTR/FCrDNS) data in the profile lookup.
curl -s https://worldip.io/api/v1/ext/forward/8.8.8.8 \
-H "Authorization: Bearer YOUR_KEY"
{
"ip": "8.8.8.8",
"forward_dns": {
"hostname": "dns.google",
"registerable_domain": "dns.google",
"hosted_domain_count": 2,
"hosted_domains": ["dns.google", "google-public-dns-a.google.com"],
"hosted_domains_truncated": false
},
"source": "GRIP",
"attribution": "Data via GRIP (General Research IP)",
"generated_at": "2026-07-17T00:45:20+00:00"
}
forward_dns is null for
reserved/bogon addresses or when the upstream source has no data.
Pulse events
A geo-tagged stream of live "internet events" — BGP routing anomalies (MOAS, RPKI-invalids,
route leaks, withdrawals, bogons) and RIR allocation changes — each tagged with a country
and country-centroid lat/lon so it can be plotted directly on a map. Designed to be polled:
pass the returned next_since back as ?since= on the next call.
| Query param | Default | Description |
|---|---|---|
since | now − 300s | Unix seconds or ISO-8601; lower time bound. |
until | now | Upper time bound. |
limit | 500 | Max events, 1–2000. |
min_severity | 0 | Drop BGP events below this severity. |
country | all | ISO-2 country filter, e.g. US. |
types | all | CSV of moas,rpki,first_seen,withdrawal,aspath,bogon. |
category | all | all · bgp · rir. |
moas_sample | 50 | Return 1 of every N MOAS events (MOAS is a legitimate-anycast firehose). 1 = full stream. |
curl -s "https://worldip.io/api/v1/pulse/events?types=rpki,aspath&min_severity=5&limit=100" \
-H "Authorization: Bearer YOUR_KEY"
{
"events": [
{
"id": "bgp:14238894120583017472",
"category": "bgp",
"type": "aspath",
"label": "AS-path anomaly (possible leak/hijack)",
"severity": 7,
"detected_at": "2026-07-17T00:44:57+00:00",
"ts": 1768610697,
"prefix": "103.163.158.0/24",
"asn": 141804,
"counter_asn": 140171,
"country": "IN",
"lat": 22.35,
"lon": 78.67,
"detail": { "collector": "rrc05", "as_path": "13237 3320 6453 4755 141804" }
}
],
"count": 1,
"next_since": 1768610697,
"server_time": 1768610760
}
Pulse summary
Current event-type counts for the last hour and last 24 hours — a cheap poll for dashboards and alerting that don't need the full event bodies.
curl -s https://worldip.io/api/v1/pulse/summary \
-H "Authorization: Bearer YOUR_KEY"
{
"bgp_anomalies": [
{ "type": "moas", "category": "bgp", "label": "Multiple-origin route (MOAS)", "last_1h": 24187, "last_24h": 571043 },
{ "type": "rpki", "category": "bgp", "label": "RPKI-invalid announcement", "last_1h": 312, "last_24h": 7885 }
],
"rir_changes": [
{ "type": "allocation", "category": "rir", "label": "RIR allocation", "last_1h": 6, "last_24h": 214 }
],
"server_time": 1768610760
}
Public feeds (no key)
The same Pulse data also powers the auto-refresh on our Pulse pages, exposed as lightweight no-key poll endpoints. They share the site-wide per-IP request floor (see Rate limits); for higher volume or geo-tagged output, use the keyed Pulse events endpoint.
The most recent BGP routing anomalies (last hour, across RIS collectors).
{
"anomalies": [
{
"prefix": "200.7.251.0/24",
"unexpected_asn": 273140,
"expected_asn": 19114,
"pings": 314,
"last_seen": "2026-07-17 00:44:57",
"collector": "rrc25",
"as_path": "198150 174 12956 19114 273140"
}
]
}
Recent RIR ownership changes — allocations, transfers, and country/RIR re-assignments.
Accepts ?since_id= to fetch only newer rows.
{
"events": [
{
"id": 293167,
"changed_at": "2026-07-11 12:03:24",
"ip_start": 3627346432,
"ip_end": 3627346943,
"ip_start_str": "216.52.234.0",
"change_type": "allocation",
"old_value": null,
"new_value": "US",
"rir": "arin",
"cidr_guess": "216.52.234.0/23",
"org_name": "Unitas Global",
"org_slug": "unitas-global",
"asn": 10912,
"country_code": "US"
}
]
}
Anomalies of a single type with 24h totals. type ∈
moas, first_seen, withdrawal, bogon,
aspath, rpki.
{
"type": "rpki",
"totals": { "anomalies_24h": 7885 },
"anomalies": [ /* ... */ ]
}
Rate limits
Limits are enforced with a sliding 60-second window. Exceeding one returns
429 with a Retry-After header and a JSON body.
| Endpoint | Limit |
|---|---|
/api/v1/ext/lookup, /api/v1/ext/forward |
Per-key sliding window (your plan's rate) and a 60/min per-source-IP ceiling. Profiles are additionally cached 1h per IP. |
/api/v1/pulse/events, /api/v1/pulse/summary |
Per-key sliding window (your plan's rate) on top of a 120/min per-IP floor. |
/api/pulse/* (no key) |
120/min per source IP. |
{ "error": "rate_limited", "retry_after_sec": 42 }
Errors
Errors use standard HTTP status codes with a JSON body of
{ "error": "...", "message": "..." } (the 429 body is shown above).
| Status | error | Meaning |
|---|---|---|
| 400 | bad_ip | Malformed IPv4 in the path. |
| 401 | missing_key | No key supplied. Response also sends WWW-Authenticate: Bearer. |
| 401 | invalid_key | Key not recognized or disabled. |
| 403 | forbidden_scope | Key lacks the required scope. |
| 403 | origin_not_allowed | Key is origin-locked; the request Origin/Referer did not match. |
| 403 | ip_not_allowed | Key is IP-locked; caller IP is off the allow-list. |
| 429 | rate_limited | Rate limit exceeded; retry after retry_after_sec. |
| 503 | db_unavailable | Backend temporarily unavailable; retry shortly. |
Plans & data tiers
Web lookups on worldip.io are always free and need no signup. The API adds monthly request quotas and unlocks progressively richer data. WorldIP deliberately undercuts the market on the premium signals — proxy/threat classification, live BGP, RPKI and Web3 — that other providers gate behind $100–500+ plans, while keeping a generous free, no-signup tier.
| Plan | Price | Requests / mo | Adds |
|---|---|---|---|
| Free | $0 | ~10,000 | Core: owner/org, ASN, country, PTR, CIDR. Unlimited web lookups, no signup. |
| Basic | $9 | 20,000 | + /24 neighbors, city geolocation, ASN type, RIR ownership, forward + reverse DNS, org/ASN enrichment. |
| Pro | $39 | 200,000 | + VPN/proxy/Tor/datacenter classification, residential & mobile proxy detection, access-type, trust score, blocklists, basic BGP context. |
| Business | $129 | 1,500,000 | + live BGP (prefixes/MOAS), BGP anomalies (Pulse API), RPKI validation, org footprint, bulk lookups (≤1000/call), Web3 validation. |
| Scale | $499 | 5,000,000 | Everything + dataset snapshots, WHOIS/RDAP, priority support. |
| Enterprise | Contact us | Custom | Custom / unlimited volume, custom data, SLA, dedicated support, DB / on-prem delivery. |
Annual billing is two months free (~17% off). See full pricing for details. Self-serve key issuance and plan checkout are rolling out with our subscription launch.
Get launch updates
Self-serve key issuance and plan checkout land with our subscription launch. Drop your email and we'll message you the day API keys open for signup — and again for major new endpoints. No spam, unsubscribe anytime.
Frequently Asked Questions
How do I get an API key?
Self-serve API keys and plan checkout roll out with our subscription launch. Until then, the keyless endpoint (curl https://worldip.io/8.8.8.8 — 1,000 lookups/day, no signup) and the public Pulse feeds need no key.
Do the web pages and the API share the same data?
Yes. Every field the API returns is the same intelligence rendered on worldip.io — the API just gives you one cached JSON call instead of scraping a page.
What does the /ext/ path mean?
It is the shared endpoint that also powers the WorldIP browser extension. The path is stable and safe to call server-side with a normal API key.
Is IPv6 supported?
The v1 keyed lookup endpoints are IPv4 today. IPv6 coverage is expanding across the fleet; follow the News page for availability.
What format are responses?
JSON, UTF-8. A success is 200 OK with the record at the top level; errors use standard HTTP status codes (400, 401, 403, 429, 503) with a JSON error body.