Resolve an IP to its provider.
One endpoint. Give it an IPv4 or IPv6 address; get back every operator whose published ranges contain it, with the matching CIDR and a trust level, or an empty array when nothing matches.
curl -s 'https://sourceip.io/v1/lookup?ip=8.8.8.8' \ -H 'x-api-key: YOUR_KEY'
No key yet? Request a free one, or try it without any setup from the search box on the home page.
Pass your key in the x-api-key header on every request. Keys are issued per organisation. Do not embed a key in client-side code or a public repository: anything shipped to a browser is public.
x-api-key: YOUR_KEY
| Parameter | Type | Required | Description |
|---|---|---|---|
| ip | string | yes | IPv4 or IPv6 address in standard notation. CIDR ranges are not accepted. |
{
"ip": "8.8.8.8",
"last_updated": "2026-08-05T04:12:07Z",
"providers": [
{
"id": "0ec4da84-96c0-3756-b79c-4d0034b75228",
"name": "Google Public DNS",
"description": "Google's global domain name system (DNS) resolution service.",
"category": "public_dns",
"explanation": "Public DNS services are used as alternatives to ISP's name servers...",
"logo": "https://upload.wikimedia.org/wikipedia/commons/2/2f/Google_2015_logo.svg",
"precedence": 0,
"trust_level": 1,
"ip_cidr": "8.8.8.8/32"
}
]
}| Field | Type | Description |
|---|---|---|
| ip | string | The address you queried, echoed back. |
| last_updated | string | ISO8601 build time of the snapshot that answered this query. |
| providers | array | Every provider whose published ranges contain this address. Empty when there is no match. |
| providers[].id | string | Stable UUID for the provider. |
| providers[].name | string | Provider name. |
| providers[].description | string | What the organisation is and what these ranges are for. |
| providers[].category | string | Service category, e.g. cloud, cdn, public_dns, security. |
| providers[].explanation | string | Why you would see this traffic on your network. |
| providers[].logo | string | Logo URL. May be empty. |
| providers[].precedence | number | Ordering hint for overlapping matches; higher sorts first. |
| providers[].trust_level | number | How much weight the attribution carries. See trust levels. |
| providers[].ip_cidr | string | The specific CIDR that matched. |
Multiple providers can match one address: a service running on a cloud provider matches both. Results are sorted by precedence, most specific first.
| Status | Meaning |
|---|---|
| 400 | Missing or unparseable ip query parameter. |
| 403 | Missing or invalid API key. |
| 429 | Rate limit exceeded. Check the Retry-After header. |
| 500 | Server error. Retry with backoff. |
Errors return JSON with an error field. A successful lookup with no match is 200 with an empty providers array, not a 404: an address we have no source for is an answer, not a failure.
| Tier | Limit | Counted by |
|---|---|---|
| Anonymous (website) | 100/day | client address |
| Free key | 1,000/day | API key |
| Paid | negotiated | API key |
Quotas reset at midnight UTC. A 429 carries Retry-After in seconds; anonymous responses also carryX-RateLimit-Remaining. Cache results. The dataset changes daily, so re-querying the same address within a day gains you nothing.
| Level | Label | Meaning |
|---|---|---|
| 1 | TRUSTED | The provider directly operates the service (e.g., API endpoints, DNS, software delivery, or control-plane infrastructure published by the operator itself). |
| 2 | SHARED INFRASTRUCTURE | Ownership is known, but the provider supplies infrastructure to customers or third parties, so activity is not attributable to the provider itself. |
| 0 | INFORMATIONAL | Descriptive context only — the match provides information without serving as a basis for trust or distrust decisions. |
| -1 | UNTRUSTED | Important to label, but a match must not imply benign behaviour, accountability, or allow-list suitability. |
trust_level describes what an attribution means;precedence only orders overlapping matches. They are not the same thing. Level 1 can support allow-list style decisions where your policy allows it; level 2 cannot, because the provider is supplying infrastructure to third parties.
curl
curl -s 'https://sourceip.io/v1/lookup?ip=1.1.1.1' \ -H 'x-api-key: YOUR_KEY' | jq '.providers[].name'
Python
import os, requests
resp = requests.get(
"https://sourceip.io/v1/lookup",
params={"ip": "1.1.1.1"},
headers={"x-api-key": os.environ["SOURCEIP_KEY"]},
timeout=5,
)
resp.raise_for_status()
for provider in resp.json()["providers"]:
print(provider["name"], provider["ip_cidr"], provider["trust_level"])Go
req, _ := http.NewRequest("GET", "https://sourceip.io/v1/lookup?ip=1.1.1.1", nil)
req.Header.Set("x-api-key", os.Getenv("SOURCEIP_KEY"))
resp, err := http.DefaultClient.Do(req)
if err != nil {
log.Fatal(err)
}
defer resp.Body.Close()
var out struct {
IP string `json:"ip"`
Providers []struct {
Name string `json:"name"`
IPCIDR string `json:"ip_cidr"`
TrustLevel int `json:"trust_level"`
} `json:"providers"`
}
json.NewDecoder(resp.Body).Decode(&out)A machine-readable spec is at /openapi.json.