IPBot
Free API Key
API Reference

Build with the IPBot API

Everything you need to call the API: endpoints, evidence fields, data status, and error codes. Anonymous access works out of the box, and free API keys unlock higher limits.

CORS enabled JSON responses API key optional
Example response GET /v1/ip/8.8.8.8
{
  "ip": "203.0.113.1",
  "stack": "ipv4",
  "location": {
    "country": "United States",
    "country_code": "US",
    "region": "California",
    "city": "San Francisco",
    "timezone": "-08:00"
  },
  "network": {
    "asn": "AS15169",
    "org": "Example ISP Inc.",
    "category": "residential",
    "operator": "Example ISP",
    "operator_type": "isp",
    "owner": "Example ISP Inc.",
    "allocation": {
      "cidr": "203.0.113.0/24",
      "range": "203.0.113.0 - 203.0.113.255",
      "registry": "arin",
      "country": "US"
    }
  },
  "routing": {
    "origin_asn": "AS15169",
    "prefix": "203.0.113.0/24",
    "rpki_status": "unknown",
    "confidence": "low",
    "origin_conflict": false
  },
  "score": {
    "ip_score": 60,
    "risk_score": 40,
    "band": "fair",
    "verdict": "monitor",
    "recommended_action": "rate_limit"
  },
  "classification": {
    "usage_type": "vpn",
    "is_datacenter": false,
    "is_proxy": true,
    "is_privacy_relay": false,
    "is_known_crawler": false,
    "is_verified_crawler": false,
    "is_mobile": false,
    "proxy_type": "vpn",
    "confidence": "medium",
    "traits": ["proxy", "vpn"],
    "threat_level": "Low"
  },
  "evidence": {
    "signals": [
      {
        "category": "privacy",
        "label": "VPN",
        "severity": "medium",
        "confidence": "medium",
        "description": "This IP is associated with VPN traffic."
      }
    ]
  }
}
GET /v1/ip/current

Auto-detect the caller IP with v1 schema. Supports fields projection and Pro RDAP include.

curl -s "https://api.ipbot.com/v1/ip/current?fields=ip,location,score" | jq
GET /v1/ip/{ip}

Lookup a specific IPv4 or IPv6 address with v1 schema. Supports fields projection and Pro RDAP include.

curl -s "https://api.ipbot.com/v1/ip/8.8.8.8?fields=ip,network,score" | jq
GET /v1/assessment

Dual-stack assessment; supports ?ipv4= and ?ipv6=.

curl -s "https://api.ipbot.com/v1/assessment?ipv4=8.8.8.8&ipv6=2001:4860:4860::8888" | jq

Base URL

Canonical /v1 endpoints return JSON and include CORS headers. The two legacy lookup routes also support an explicit plain-text representation for command-line use.

https://api.ipbot.com

Plain text (legacy)

GET / and GET /{ip} return JSON by default. Request text with ?format=text or an Accept: text/plain header. The query parameter takes precedence; otherwise text is selected only when its accepted quality is higher than JSON (or an exact text match is more specific). Canonical /v1 routes remain JSON-only.

One-line current IP

curl -s -H "Accept: text/plain" https://api.ipbot.com/

Four-line detail

curl -s "https://api.ipbot.com/8.8.8.8?format=text&detail=1"

Lines are IP, location, ASN, and organization (plus the official operator domain when known). Missing values render as -. Errors keep the JSON route's HTTP status and use one error: message line.

Authentication

Anonymous access is supported with a baseline rate limit. Use an API key to raise your throughput. Pro-only fields require an authenticated Pro API key.

X-API-Key: ipb_free_REPLACE_ME

V1 Lookup Parameters

GET /v1/ip/current and GET /v1/ip/{ip} support response projection. Legacy routes and /v1/assessment keep their existing response shape.

Parameter Required Description
fields No Comma-separated top-level response fields: ip, stack, location, network, routing, score, classification, evidence, decision, scores, scenarios, and explanation. With Pro RDAP enabled, rdap becomes an additional conditional field.
include No Optional include list. include=rdap_contacts is Pro-only and adds normalized RDAP registration/contact data.

Field Projection

fields trims the canonical v1 response. It does not create a new schema or rename nested fields. Supported public values are ip, stack, location, network, routing, score, classification, evidence, decision, scores, scenarios, and explanation.

curl -s "https://api.ipbot.com/v1/ip/8.8.8.8?fields=ip,location,score" | jq
{
  "ip": "8.8.8.8",
  "location": {
    "country": "United States",
    "country_code": "US",
    "region": "California",
    "city": "Mountain View",
    "timezone": "-07:00"
  },
  "score": {
    "ip_score": 85,
    "risk_score": 15,
    "band": "good",
    "verdict": "allow",
    "recommended_action": "allow"
  }
}

Pro RDAP Contacts

Free and anonymous responses never expose RDAP contact emails, phones, addresses, person records, raw RDAP JSON, or raw WHOIS text. Pro keys can request the normalized object explicitly. After the include is accepted, use fields=rdap to return only the RDAP object.

curl -s "https://api.ipbot.com/v1/ip/8.8.8.8?include=rdap_contacts&fields=ip,rdap" \
  -H "X-API-Key: $IPBOT_PRO_API_KEY" | jq
{
  "ip": "8.8.8.8",
  "rdap": {
    "available": true,
    "network": {
      "handle": "NET-8-8-8-0-1",
      "name": "GOGL",
      "registry": "arin",
      "registered_owner": "Google LLC",
      "allocation": {
        "cidr": "8.8.8.0/24",
        "range": "8.8.8.0 - 8.8.8.255",
        "registry": "arin",
        "country": "US"
      }
    },
    "contacts": [
      {
        "handle": "GOGL",
        "roles": ["registrant"],
        "name": "Google LLC",
        "organization": "Google LLC",
        "phones": ["+1-555-0100"]
      },
      {
        "roles": ["abuse"],
        "name": "Google Abuse",
        "emails": ["abuse@example.com"]
      }
    ]
  }
}

Without a Pro key, include=rdap_contacts returns 403 PRO_REQUIRED. Unknown include names return 400 INVALID_INCLUDE. Empty or unknown fields return 400 INVALID_FIELDS.

{
  "error": "RDAP contacts require a Pro API key",
  "code": "PRO_REQUIRED",
  "details": {
    "include": "rdap_contacts",
    "allowed_includes": ["rdap_contacts"]
  }
}

Invalid Field Names

The server returns the current public projection set in details.allowed_fields. When a Pro RDAP include is already accepted, rdap is appended to that list.

{
  "error": "Invalid fields parameter",
  "code": "INVALID_FIELDS",
  "details": {
    "allowed_fields": [
      "ip",
      "stack",
      "location",
      "network",
      "routing",
      "score",
      "classification",
      "evidence",
      "decision",
      "scores",
      "scenarios",
      "explanation"
    ],
    "invalid_fields": ["bogus"]
  }
}

Cache Behavior

Explicit lookups such as GET /v1/ip/{ip}, legacy GET /{ip}, and GET /v1/assessment?ipv4=...&ipv6=... default to Cache-Control: public, max-age=86400.

Auto-detected current-IP responses (GET /v1/ip/current, legacy GET /, and auto mode on /v1/assessment), accepted include=rdap_contacts lookups, and POST /v1/crawler/verify return Cache-Control: no-store.

Evidence Fields

IPBot returns product-level IP intelligence: network category, classification confidence, verdict, recommended action, and structured signals. Internal source and version details are not part of the public response contract.

Proxy and privacy signals

proxy_type, is_proxy, is_vpn, is_tor, and is_privacy_relay describe public classifications without exposing the underlying data vendor.

Structured evidence

evidence.signals contains stable labels, categories, severities, confidence, and short explanations suitable for product UI. When the optional ThreatFox sidecar is present, evidence.threatfox adds structured malware / first-seen / last-seen metadata without adding extra score beyond the existing ThreatFox threat-list hit.

Crawler protection

is_known_crawler comes from official ranges, including supported search crawler feeds, and avoids generic bot-UA over-scoring. Cacheable third-party IP GETs ignore the caller User-Agent; they can verify only from caller-independent evidence such as DNS. Use the no-store POST /v1/crawler/verify surface for supported range + explicitly supplied user-agent verification.

Routability checks

network.routability, is_special_use, and is_bogon explain private, reserved, documentation, dynamic full-bogon, and other non-global address states without exposing raw source names.

Operator and service context

network.category, operator_type, and service_name may include provider-declared content, network service provider, webhook, messaging, or crawler infrastructure context.

Data status

/v1/data/status reports public service and capability readiness. Detailed source readiness is reserved for internal operations.

RDAP boundary

network.owner and network.allocation come from normalized RDAP ownership data when available. Full RDAP contacts only appear in Pro responses after include=rdap_contacts.

Decision Engine

Decision Engine v1 adds four optional, additive top-level objects to v1 IP lookup responses: decision, scores, scenarios, and explanation. These fields are advisory only and do not change score.risk_score, score.verdict, or score.recommended_action.

Field What it adds
decision Top-level role/profile/action recommendation with policy version and applied guardrails.
scores Eight advisory component sub-scores, including base risk, abuse, anonymity, trust, infrastructure, routing risk, and evidence quality.
scenarios Per-surface recommendations for content, seo_crawler, login, signup, payment, and api.
explanation Human-readable summary, primary reason, risk drivers, guardrails, and reasoning chain.

scenarios.*.confidence is computed per scenario from that scenario's own expected-loss margin and supporting evidence; it is not a copy of decision.confidence.

curl -s "https://api.ipbot.com/v1/ip/8.8.8.8?fields=decision,scores,scenarios,explanation" | jq
{
  "decision": {
    "profile": "ordinary_datacenter",
    "role": "datacenter",
    "action": "monitor",
    "risk_level": "medium",
    "confidence": "high",
    "policy_version": "decision-v1-2026-07.1",
    "allowed_actions": ["allow", "monitor", "challenge"],
    "blocked_actions": null,
    "guardrails_applied": ["verified_crawler_protection"]
  },
  "scores": {
    "risk_score": 42,
    "base_risk_score": 40,
    "abuse_score": 8,
    "anonymity_score": 12,
    "trust_score": 62,
    "infrastructure_score": 74,
    "routing_risk_score": 4,
    "evidence_quality_score": 86
  },
  "scenarios": {
    "content": { "action": "allow", "risk_level": "low", "confidence": "high", "reason": "Low abuse pressure" },
    "seo_crawler": { "action": "allow", "risk_level": "low", "confidence": "high", "reason": "Known automation expected" },
    "login": { "action": "monitor", "risk_level": "medium", "confidence": "medium", "reason": "Datacenter origin" },
    "signup": { "action": "challenge", "risk_level": "medium", "confidence": "medium", "reason": "Higher fraud surface" },
    "payment": { "action": "manual_review", "risk_level": "high", "confidence": "medium", "reason": "Elevated payment risk" },
    "api": { "action": "monitor", "risk_level": "low", "confidence": "high", "reason": "Automation expected" }
  },
  "explanation": {
    "summary": "Datacenter-origin traffic with moderate anonymity pressure and no strong abuse history.",
    "key_reason": "datacenter_origin",
    "drivers": [
      {
        "type": "infrastructure",
        "label": "Datacenter Origin",
        "impact": "+10",
        "impact_score": 10,
        "direction": "raises_risk",
        "reason": "Traffic originates from a hosting/datacenter network."
      }
    ],
    "guardrails_applied": ["verified_crawler_protection"],
    "reason_chain": ["base_risk=40", "datacenter_origin", "policy=balanced"]
  }
}

Crawler Verification

POST /v1/crawler/verify is a narrow verification endpoint for site-owner workflows. It accepts an ip and optional user_agent, returns verification_status as verified, known_unverified, or not_known, and always responds with Cache-Control: no-store.

Request

curl -s -X POST https://api.ipbot.com/v1/crawler/verify \
  -H "Content-Type: application/json" \
  -d '{"ip":"66.249.66.1","user_agent":"Googlebot/2.1 (+http://www.google.com/bot.html)"}' | jq

DNS-verifiable families such as Googlebot and Bingbot can reach verified from the IP alone. OpenAI-family crawlers require both official range membership and a matching crawler user-agent token.

Response

{
  "ip": "66.249.66.1",
  "user_agent": "Googlebot/2.1 (+http://www.google.com/bot.html)",
  "verification_status": "verified",
  "classification": {
    "is_known_crawler": true,
    "is_verified_crawler": true,
    "crawler_provider": "Google",
    "crawler_type": "googlebot",
    "crawler_verified_by": "reverse_forward_dns",
    "crawler_hostname": "crawl-66-249-66-1.googlebot.com."
  },
  "network": {
    "owner": "Google LLC",
    "allocation": {
      "cidr": "66.249.64.0/19",
      "registry": "arin",
      "country": "US"
    }
  },
  "explanation": {
    "text": "Google googlebot is verified by reverse and forward DNS, and the hostname resolves back to this IP.",
    "reason_code": "verified_crawler"
  }
}

Endpoints

Method Path Description
GET /v1/ip/current Auto-detect the caller IP with v1 schema. Supports fields projection and Pro RDAP include.
GET /v1/ip/{ip} Lookup a specific IPv4 or IPv6 address with v1 schema. Supports fields projection and Pro RDAP include.
GET /v1/assessment Dual-stack assessment; supports ?ipv4= and ?ipv6=.
POST /v1/crawler/verify Crawler verification for site-owner workflows using IP and optional user-agent context.
GET /v1/data/status Public service status and high-level intelligence capabilities.
GET / Legacy auto-detect endpoint. JSON by default; supports an explicit plain-text representation.
GET /{ip} Legacy lookup endpoint. JSON by default; add ?format=text for shell-friendly output.
GET /v1/asn/{asn} Lookup ASN details with graceful local fallback, optional Radar enrichment, evidence-only threat_density, and optional ASN-DROP context.
GET /health Health check endpoint for liveness and readiness.
GET /metrics Operator-only Prometheus metrics for HTTP traffic and operational coverage counters.
POST /reload Admin-only: reloads runtime rules and intelligence data.
GET /auth/github Initiates GitHub OAuth flow for authentication.
GET /auth/me Returns current authenticated user profile.
GET /auth/tiers Returns tier limits and current tier context.
POST /auth/logout Clears the session and logs out the user.
GET /auth/keys Lists all API keys for the authenticated user.
POST /auth/keys Creates a new API key.
DELETE /auth/keys/{id} Revokes an API key immediately.
GET /auth/usage Returns request usage summary by API key.

ASN Response

/v1/asn/{asn} is the canonical ASN route. It always returns 200 for a valid ASN, even when Cloudflare Radar is unavailable, by falling back to IPBot's local ASN name and any evidence-only context it can still derive. The legacy /asn/{asn} route remains as a compatibility alias.

radar is optional enrichment. threat_density and asndrop are evidence-only ASN context and do not change per-IP risk_score.

{
  "asn": "AS64500",
  "name": "Example Network",
  "radar": null,
  "threat_density": {
    "threat_network_count": 2,
    "threat_ipv4_addresses": 512,
    "total_ipv4_addresses": 1048576,
    "ratio": 0.00048828125,
    "percent": 0.048828125,
    "significant": false,
    "source": "threat_lists+iptoasn"
  },
  "asndrop": {
    "asn": "AS64500",
    "as_name": "EXAMPLE-NETWORK",
    "rir": "arin",
    "domain": "example.net",
    "country_code": "US"
  }
}

Error Responses

All errors follow a consistent JSON format.

{
  "error": "Invalid IP address format",
  "code": "INVALID_IP",
  "details": {
    "provided": "invalid-ip"
  }
}
Code HTTP Description
INVALID_IP 400 Malformed or invalid IP address.
INVALID_FIELDS 400 The fields projection is empty or contains unknown fields.
INVALID_INCLUDE 400 The include parameter contains an unsupported include name.
INVALID_ASN 400 Malformed or invalid ASN format.
NO_CLIENT_IP 400 Unable to determine client IP.
UNAUTHORIZED 401 Authentication required.
INVALID_API_KEY 401 The API key is invalid or revoked.
FORBIDDEN 403 Access denied for admin routes.
PRO_REQUIRED 403 The requested include, such as rdap_contacts, requires a Pro API key.
NOT_FOUND 404 Endpoint or resource does not exist.
RATE_LIMITED 429 Rate limit exceeded.
INTERNAL_ERROR 500 Unexpected server error.
AUTH_DISABLED 503 Authentication not configured.