Skip to content
IP IPBot
Get Started

Response Schema

The v1 API returns IPBot-owned intelligence fields. Public responses do not expose internal data source names, data package versions, raw rule identifiers, or runtime metadata.

{
"ip": "2001:4860:4860::8888",
"stack": "ipv6",
"location": {
"country": "United States",
"country_code": "US",
"region": "California",
"city": "Mountain View",
"latitude": 37.3861,
"longitude": -122.0838,
"timezone": "-08:00"
},
"network": {
"asn": "AS15169",
"org": "GOOGLE",
"category": "internet_infrastructure",
"operator": "Google",
"operator_domain": "google.com",
"operator_type": "cloud",
"service_role": "public_dns_resolver",
"service_name": "Google Public DNS",
"routability": "global",
"owner": "Google LLC",
"allocation": {
"cidr": "2001:4860:4860::/48",
"range": "2001:4860:4860:: - 2001:4860:4860:ffff:ffff:ffff:ffff:ffff",
"registry": "arin",
"country": "US"
}
},
"routing": {
"origin_asn": "AS15169",
"prefix": "2001:4860:4860::/48",
"rpki_status": "valid",
"confidence": "high",
"origin_conflict": false
},
"score": {
"ip_score": 70,
"risk_score": 30,
"band": "good",
"verdict": "allow",
"recommended_action": "allow"
},
"classification": {
"usage_type": "public_dns_resolver",
"is_datacenter": false,
"is_proxy": false,
"service_role": "public_dns_resolver",
"service_name": "Google Public DNS",
"is_public_resolver": true,
"is_anycast": true,
"is_special_use": false,
"is_bogon": false,
"is_privacy_relay": false,
"is_known_crawler": false,
"is_verified_crawler": false,
"is_mobile": false,
"confidence": "high",
"traits": ["public_dns_resolver", "anycast_network", "internet_infrastructure"],
"threat_level": "Low",
"country_alignment": {
"status": "multi_region",
"geo_country": "US",
"allocation_country": "US",
"confidence": "low",
"basis": ["geoip", "allocation"],
"reason_codes": ["anycast_service"],
"score_effect": 0
}
},
"evidence": {
"summary": {
"direct_threat_match": false,
"prefix_context_only": false
},
"signals": [
{
"category": "network",
"label": "Public DNS Resolver",
"severity": "info",
"confidence": "high",
"description": "This IP is a well-known public DNS resolver endpoint."
}
]
}
}
FieldTypeDescription
ipstringQueried IP address
stackstringipv4, ipv6, or unknown
locationobjectApproximate geolocation
networkobjectASN, organization, network category, and public operator
routingobject or nullOptional route-origin confidence for the matched prefix
rdapobjectPro-only normalized RDAP registration contacts, omitted unless include=rdap_contacts is accepted
scoreobjectScore, band, verdict, and recommended action
classificationobjectProxy, crawler, privacy, datacenter, and threat flags
evidenceobjectStructured public signals
decisionobject (optional)Decision Engine v1 recommendation (additive; does not change score)
scoresobject (optional)Decision Engine v1 component sub-scores (0-100 each)
scenariosobject (optional)Decision Engine v1 per-scenario recommendations
explanationobject (optional)Decision Engine v1 human-readable explanation and drivers

GET /v1/ip/current and GET /v1/ip/{ip} support fields for top-level response projection:

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

fields accepts ip, stack, location, network, routing, score, classification, evidence, decision, scores, scenarios, and explanation. The returned object contains only the requested top-level fields and preserves each field’s canonical nested structure. Empty fields= or unknown names return 400 INVALID_FIELDS with allowed_fields and invalid_fields in details.

When a Pro API key requests include=rdap_contacts, rdap becomes an additional top-level field and can be projected with fields=rdap. Without the include, fields=rdap is invalid because the public canonical response does not contain RDAP contacts.

FieldTypeDescription
asnstringAutonomous System Number
orgstringOrganization name associated with the ASN
categorystringNormalized category such as residential, datacenter, cloud, edge, internet_infrastructure, content, network, or unknown
operatorstringPublic network operator name when available
operator_domainstringOptional normalized official operator hostname from reviewed mappings or the loaded operator profile; display-only metadata that never changes scores or decisions
operator_typestringOperator class such as isp, cloud, cdn, content, network_service_provider, mobile_carrier, or enterprise
service_rolestringStable role for known public infrastructure endpoints, such as public_dns_resolver
service_namestringUser-facing service name, such as Google Public DNS, Cloudflare 1.1.1.1, Telegram, or Stripe Webhooks
routabilitystringPublic routability class: global, private, non_global, reserved, or bogon
ownerstringRegistry owner name when available
allocationobject or nullAllocation CIDR/range/country context when available

The country fields answer different questions and must not be conflated: location.country_code is the estimated GeoIP country (where the IP appears to be used), network.allocation.country is the registration/allocation country (who holds the block and where it is registered), classification.registry_country is RIR delegated country context, and routing.origin_asn describes route origin — none of them proves physical server location. classification.country_alignment compares these inputs and reports the result explicitly.

rdap is omitted from Free and anonymous responses. It is only returned by GET /v1/ip/current and GET /v1/ip/{ip} when a Pro API key explicitly sends include=rdap_contacts.

FieldTypeDescription
availablebooleanWhether normalized RDAP registration data was available for the lookup
cache_statusstringOptional ownership cache state such as fresh or stale
conformancearrayRDAP conformance labels from the RDAP response
networkobject or nullRegistered network metadata, allocation, events, and RDAP links
contactsarrayRDAP entity contacts with roles, names, organizations, emails, phones, addresses, events, and links
noticesarrayRDAP notices from the registry response
remarksarrayRDAP remarks from the registry response
redactedarrayRDAP redaction metadata when the registry reports redacted fields

IPBot still does not expose raw RDAP JSON or raw WHOIS text. The Pro object is normalized, cacheable ownership data extracted from RDAP fields.

FieldTypeDescription
origin_asnstringOrigin ASN used for route-origin validation
prefixstringMatched prefix used for validation
rpki_statusstringvalid, invalid_asn, invalid_length, or unknown
confidencestringlow, medium, or high
origin_conflictbooleanTrue when optional BGP origin evidence disagrees with lookup or range ASN evidence
FieldTypeDescription
ip_scoreinteger0-100, higher is better
risk_scoreinteger0-100, higher is riskier
bandstringperfect, excellent, good, fair, poor, or danger
verdictstringallow, monitor, challenge, or block
recommended_actionstringallow, rate_limit, captcha_challenge, manual_review, or block
FieldTypeDescription
usage_typestringProduct-level usage type such as datacenter, vpn, residential_proxy, or unknown
is_datacenterbooleanTrue when hosting/cloud/infrastructure evidence is present
is_proxybooleanTrue when proxy, VPN, Tor, or related proxy evidence is present
is_cloudbooleanTrue when the IP matched a public cloud provider range
cloud_providerstringPublic cloud or network operator name when available
cloud_servicestringProvider service label when available
cloud_regionstringProvider region when available
is_vpnbooleanTrue when VPN evidence is present
is_torbooleanTrue when Tor evidence is present
is_known_abuserbooleanTrue when abuse evidence is present
is_residential_proxybooleanPresent only when residential proxy evidence is known
service_rolestringStable role for known public infrastructure endpoints
service_namestringUser-facing service name for known public infrastructure endpoints and official service ranges
is_public_resolverbooleanTrue for well-known public DNS resolver endpoints
is_anycastbooleanTrue when the endpoint is known to be anycasted
is_edge_networkbooleanTrue when the IP matched a CDN or edge provider range
is_privacy_relaybooleanTrue for privacy relay networks
privacy_relay_providerstringPublic relay operator name when available
is_known_crawlerbooleanTrue when official crawler range evidence is present; known crawlers are not penalized only for a bot-like user agent
is_verified_crawlerbooleanPresent and true when caller-independent crawler DNS verification passes, or on the no-store verification endpoint when a supported range and explicitly supplied user-agent agree
crawler_providerstringPublic crawler operator name when available
crawler_typestringStable crawler family label such as googlebot, bingbot, or gptbot
crawler_verified_bystringPresent only for verified crawler evidence; user_agent_ip_range is limited to a surface that explicitly accepts caller context, not cacheable third-party IP GETs
crawler_hostnamestringPresent only when DNS verification yields a stable crawler hostname
is_special_usebooleanTrue when the IP is in a special-use or non-global address range
special_use_typestringStable label such as private, shared_address_space, loopback, documentation, reserved, or unallocated
is_bogonbooleanTrue when the IP is not expected as a normal public Internet source address, including dynamic full-bogon evidence when available
is_mobilebooleanTrue when the network is classified as a mobile carrier network
registrystringPublic registry context when available
registry_countrystringRIR delegated country code when available
proxy_typestringNormalized proxy type such as vpn, tor, web_proxy, or residential_proxy
confidencestringlow, medium, or high
traitsstring[]Stable traits such as datacenter, cloud_network, known_crawler, public_dns_resolver, anycast_network, proxy, or verified_crawler
threat_levelstringHuman-readable threat level
country_alignmentobjectExplainable “native IP” tendency: estimated GeoIP country versus registration countries. Always present on v1 IP responses — see below

The explainable replacement for a bare is_native boolean. It compares the estimated GeoIP country with the registration countries (allocation first, RIR delegation as fallback) and reports a tendency, never proof of physical server location. An RFC 8805 operator geofeed from a reviewed publisher can corroborate the estimated GeoIP country, but it never replaces missing registration context. The current authority review is publisher-level, not an independent per-prefix authorization proof. Descriptive only: the result never feeds risk_score, verdict, or recommended_action.

FieldTypeDescription
statusstringaligned, mismatch, multi_region, unknown, or not_applicable
geo_countrystringEstimated GeoIP two-letter country code input; invalid/unknown sentinels are omitted
allocation_countrystringRegistration/allocation two-letter country input; invalid/unknown sentinels are omitted
delegation_countrystringRIR delegated two-letter country context input; invalid/unknown sentinels are omitted
confidencestringlow, medium, or high; high requires a publisher-reviewed RFC 8805 geofeed to corroborate the GeoIP country
basisstring[]Inputs actually available: geoip, allocation, rir_delegation, and publisher-reviewed geofeed
reason_codesstring[]Machine-readable reasons such as geo_matches_allocation, geo_mismatch_allocation, geo_corroborated_by_geofeed, geofeed_geo_conflict, anycast_service, special_use_address, bogon_address, rdap_rir_country_conflict, origin_conflict_present
score_effectintegerAlways 0 — country alignment never changes scores or verdicts

Anycast and public-resolver services report multi_region instead of a single-country verdict; special-use and bogon addresses report not_applicable; conflicting or missing inputs (including an operator-geofeed conflict or contested BGP origin) report unknown. Geofeed rows from an unreviewed publisher—or a source claiming verification without a documented publisher-authority basis—are ignored. RFC 9092 plus RPKI/RDAP per-prefix scope validation remains Phase 2. mismatch describes a cross-region deployment tendency (often called “non-native”), not malice, and the assessment always describes the current egress IP—it cannot recover the real IP behind a VPN or proxy.

evidence.signals is the public explanation layer. It is designed for product UI and customer automation.

{
"signals": [
{
"category": "privacy",
"label": "VPN",
"severity": "medium",
"confidence": "medium",
"description": "This IP is associated with VPN traffic."
}
]
}
FieldTypeDescription
categorystringnetwork, privacy, threat, automation, routing, or context
labelstringUser-facing signal label
severitystringinfo, low, medium, or high
confidencestringlow, medium, or high
descriptionstringShort explanation suitable for UI

summary separates “this exact IP has a direct threat record” from “only the surrounding prefix has threat context”. A risk_score of 0 means trust offsets, suppression, and rounding left no effective risk score; it does not prove that no direct record exists. Use direct_threat_match for that question.

FieldTypeDescription
direct_threat_matchbooleanTrue when this exact IP appears on a loaded threat list
prefix_context_onlybooleanTrue when the IP itself has no direct record but its surrounding /24 shows threat-list coverage

For IPv4 lookups, reports sampled threat-list coverage of the surrounding /24 (method sampled_hosts_v1: 8 host addresses probed against the loaded threat lists). Omitted for IPv6. matched_hosts / sampled_hosts is a sampling estimate of list coverage in the prefix — not a measured share of malicious hosts. Evidence-only: score_effect is always 0; this context never enters scoring and never flips a verdict on its own.

FieldTypeDescription
scopestringSampled prefix, for example 137.175.101.0/24
methodstringsampled_hosts_v1
sampled_hostsintegerProbed neighbor addresses
matched_hostsintegerProbed neighbors present on loaded threat lists
confidencestringlow or medium — sampling confidence, capped because 8 probes cover a /24 sparsely
sourcestringloaded_threat_lists
score_effectintegerAlways 0

When the optional ThreatFox sidecar is present and the IP also matched the existing ThreatFox feed, evidence can include a structured threatfox object. This is metadata only: it does not add any extra score beyond the normal THREAT_LIST:threatfox risk path.

FieldTypeDescription
malwarestringMalware family or printable label from the sidecar
first_seenstringFirst-seen timestamp from the sidecar
last_seenstringLast-seen timestamp from the sidecar
confidence_levelintegerThreatFox confidence level for the IOC

GET /v1/data/status returns public service capability readiness. Detailed source versions and coverage counters are reserved for internal operations.

{
"service_status": "ok",
"capabilities": [
"geolocation",
"asn_intelligence",
"threat_intelligence",
"proxy_detection",
"provider_intelligence",
"range_intelligence",
"routability_intelligence",
"ownership_intelligence",
"routing_intelligence",
"service_intelligence",
"bgp_origin_intelligence",
"crawler_verification"
],
"coverage_summary": {
"lookup_ready": true,
"threat_intelligence_ready": true,
"proxy_detection_ready": true,
"provider_intelligence_ready": true,
"range_intelligence_ready": true,
"routability_ready": true,
"ownership_ready": true,
"routing_ready": true,
"service_intelligence_ready": true,
"bgp_origin_ready": false,
"crawler_verification_ready": true
}
}
interface IPBotResponse {
ip: string;
stack: "ipv4" | "ipv6" | "unknown";
location: {
country: string;
country_code: string;
region?: string;
city: string;
postal?: string;
latitude: number;
longitude: number;
timezone: string;
};
network: {
asn: string;
org: string;
category: string;
operator?: string;
operator_domain?: string;
operator_type?: string;
service_role?: string;
service_name?: string;
routability?: "global" | "private" | "non_global" | "reserved" | "bogon";
owner?: string;
allocation?: {
cidr?: string;
range?: string;
registry?: string;
country?: string;
};
};
routing?: {
origin_asn?: string;
prefix?: string;
rpki_status?: "valid" | "invalid_asn" | "invalid_length" | "unknown";
confidence?: "low" | "medium" | "high";
origin_conflict?: boolean;
};
score: {
ip_score: number;
risk_score: number;
band: "perfect" | "excellent" | "good" | "fair" | "poor" | "danger";
verdict: "allow" | "monitor" | "challenge" | "block";
recommended_action: "allow" | "rate_limit" | "captcha_challenge" | "manual_review" | "block";
};
classification: {
usage_type: string;
is_datacenter: boolean;
is_proxy: boolean;
is_cloud?: boolean;
cloud_provider?: string;
cloud_service?: string;
cloud_region?: string;
service_role?: string;
service_name?: string;
is_public_resolver?: boolean;
is_anycast?: boolean;
is_edge_network?: boolean;
is_privacy_relay?: boolean;
privacy_relay_provider?: string;
is_known_crawler?: boolean;
is_verified_crawler?: boolean;
crawler_provider?: string;
crawler_type?: string;
crawler_verified_by?: string;
crawler_hostname?: string;
is_special_use?: boolean;
special_use_type?: string;
is_bogon?: boolean;
registry?: string;
registry_country?: string;
is_mobile?: boolean;
proxy_type?: string;
confidence: "low" | "medium" | "high";
traits?: string[];
is_vpn?: boolean;
is_tor?: boolean;
is_known_abuser?: boolean;
is_residential_proxy?: boolean;
threat_level: string;
country_alignment: {
status: "aligned" | "mismatch" | "multi_region" | "unknown" | "not_applicable";
geo_country?: string;
allocation_country?: string;
delegation_country?: string;
confidence: "low" | "medium" | "high";
basis?: string[];
reason_codes?: string[];
score_effect: 0;
};
};
evidence: {
summary: {
direct_threat_match: boolean;
prefix_context_only: boolean;
};
signals: Array<{
category: string;
label: string;
severity: "info" | "low" | "medium" | "high";
confidence: "low" | "medium" | "high";
description: string;
}>;
prefix_threat_context?: {
scope: string;
method: "sampled_hosts_v1";
sampled_hosts: number;
matched_hosts: number;
confidence: "low" | "medium";
source: "loaded_threat_lists";
score_effect: 0;
};
threatfox?: {
malware?: string;
first_seen?: string;
last_seen?: string;
confidence_level?: number;
};
};
// Decision Engine v1 — additive, optional. Does not change score/verdict/recommended_action.
decision?: {
profile: string;
role: string;
action: "allow" | "monitor" | "challenge" | "rate_limit" | "manual_review" | "block";
risk_level: "low" | "medium" | "high";
confidence: "low" | "medium" | "high";
policy_version: string;
allowed_actions: string[];
blocked_actions: string[] | null;
guardrails_applied: string[] | null;
};
scores?: {
risk_score: number;
base_risk_score: number;
abuse_score: number;
anonymity_score: number;
trust_score: number;
infrastructure_score: number;
routing_risk_score: number;
evidence_quality_score: number;
};
scenarios?: Record<
"content" | "seo_crawler" | "login" | "signup" | "payment" | "api",
{
action: string;
risk_level: string;
confidence: string;
reason: string;
}
>;
explanation?: {
summary: string;
key_reason: string;
drivers: Array<{
type: string;
label: string;
impact: string;
impact_score: number;
direction: "raises_risk" | "lowers_risk";
reason: string;
}>;
guardrails_applied: string[];
reason_chain: string[];
};
}

The Decision Engine adds four optional, additive top-level objects to the v1 lookup response: decision, scores, scenarios, and explanation. They are purely advisory and do not change score.risk_score, score.verdict, or score.recommended_action. Clients that do not consume these fields keep working unchanged. Any of these objects may be absent.

{
"decision": {
"profile": "balanced",
"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": 30,
"base_risk_score": 28,
"abuse_score": 0,
"anonymity_score": 10,
"trust_score": 90,
"infrastructure_score": 80,
"routing_risk_score": 0,
"evidence_quality_score": 85
},
"scenarios": {
"content": { "action": "allow", "risk_level": "low", "confidence": "high", "reason": "Trusted infrastructure" },
"seo_crawler": { "action": "allow", "risk_level": "low", "confidence": "high", "reason": "Known good network" },
"login": { "action": "monitor", "risk_level": "medium", "confidence": "medium", "reason": "Datacenter origin" },
"signup": { "action": "challenge", "risk_level": "medium", "confidence": "medium", "reason": "Datacenter origin" },
"payment": { "action": "challenge", "risk_level": "high", "confidence": "medium", "reason": "Elevated payment risk" },
"api": { "action": "monitor", "risk_level": "low", "confidence": "high", "reason": "Automation expected" }
},
"explanation": {
"summary": "Datacenter network with strong infrastructure trust and no 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=28", "datacenter_origin", "policy=balanced"]
}
}
FieldTypeDescription
profilestringPolicy profile that produced this decision
rolestringInferred role of the IP (for example datacenter, residential, proxy, verified_crawler)
actionstringRecommended action: allow, monitor, challenge, rate_limit, manual_review, or block
risk_levelstringlow, medium, or high
confidencestringlow, medium, or high
policy_versionstringVersion of the decision policy applied
allowed_actionsstring[]Actions permitted under the active policy
blocked_actionsstring[] or nullActions explicitly blocked, or null when none
guardrails_appliedstring[] or nullGuardrails that constrained the decision, or null when none

Eight component sub-scores, each 0-100. These break down how the assessment is composed and are advisory only.

FieldTypeDescription
risk_scoreintegerComposite risk (0-100)
base_risk_scoreintegerBase risk before policy adjustments
abuse_scoreintegerKnown-abuse contribution
anonymity_scoreintegerProxy/VPN/Tor anonymity contribution
trust_scoreintegerPositive trust contribution (higher = more trusted)
infrastructure_scoreintegerInfrastructure/datacenter contribution
routing_risk_scoreintegerRoute-origin/RPKI risk contribution
evidence_quality_scoreintegerConfidence in the supporting evidence

Per-scenario recommendation keyed by scenario name (content, seo_crawler, login, signup, payment, api). Each value has the same shape, and scenarios.*.confidence is computed for that scenario from its own expected-loss margin and supporting evidence rather than copied from decision.confidence.

FieldTypeDescription
actionstringRecommended action for this scenario
risk_levelstringlow, medium, or high for this scenario
confidencestringlow, medium, or high
reasonstringShort explanation for the scenario recommendation
FieldTypeDescription
summarystringHuman-readable summary of the decision
key_reasonstringPrimary driver identifier
driversarrayIndividual factors influencing risk
drivers[].typestringDriver category
drivers[].labelstringUser-facing driver label
drivers[].impactstringSigned impact magnitude (for example +10)
drivers[].impact_scoreintegerNumeric impact contribution
drivers[].directionstringraises_risk or lowers_risk
drivers[].reasonstringShort explanation for the driver
guardrails_appliedstring[]Guardrails that constrained the decision
reason_chainstring[]Ordered reasoning steps