IP to Country API
You need a reliable way to turn an IP address into a country (and related geolocation and security context) so you can personalize content, comply with regional rules, or filter risky traffic. By the end of this post, you will be able to call a single IP-to-country API endpoint, parse its JSON, check proxy/VPN flags, and ship a production-ready integration with caching and observability.
What the IP to Country endpoint returns and when to use it
The IP to Country lookup at /api/ip gives you country and region data for a given IP address, with additional context such as timezone, latitude/longitude, ISP/organization, and basic security flags for proxy/VPN/cloud-provider. This is useful when you need to:
- Gate features or content by country (e.g., show tax/VAT by countryCode).
- Apply regional compliance or privacy logic (e.g., if inEU is true, adjust consent flows).
- Detect potential anonymity networks (is_proxy or is_vpn) before allowing sensitive actions.
- Record location metadata for analytics while avoiding storing exact addresses.
All examples below use the documented fixture IP 148.105.12.120 and the same path /api/ip. Live flags can change in production, so always treat security booleans as dynamic signals and not constants.
Endpoint and authentication
Base endpoint for the IP-to-country lookup:
- Path: /api/ip
- Method: GET
- Query parameter: ip
Authentication is sent via an Authorization header with a Bearer token. Replace YOUR_KEY with your actual token after you register:
- Header: Authorization: Bearer YOUR_KEY
- Header: Accept: application/json
You can manage and observe your integrations via the MCP endpoint: MCP. For parameter details and field descriptions, see the official Documentation.
Quickstart with cURL
The following request hits the IP to Country endpoint with the documented fixture IP. Copy and run it as-is (replace the auth value when you’re ready):
curl "https://ipxapi.com/api/ip?ip=148.105.12.120" -H "Accept: application/json" -H "Authorization: Bearer YOUR_KEY"
Official JSON sample and field usage
This is the official JSON sample for the fixture IP 148.105.12.120. Use this as a reference for field names and types. Do not treat these as your user’s live values; production responses can vary.
{
"status": "success",
"country": "United States",
"countryCode": "US",
"region": "US-CA",
"regionName": "California",
"city": "Mountain View",
"zip": "94043",
"lat": 37.40599,
"lon": -122.0786,
"timezone": "America/Los_Angeles",
"isp": "MailChimp",
"org": "MailChimp",
"as": "AS14782 MailChimp",
"query": "148.105.12.120",
"inEU": false,
"continentCode": "NA",
"security": {
"is_proxy": false,
"is_vpn": false,
"is_cloud_provider": true
}
}
What you’ll typically read in application logic:
- country and countryCode: Primary data for country gating and localization.
- inEU: Toggle for EU-related flows (consent, data handling).
- timezone: Useful for date/time display or scheduling in user’s local zone.
- lat/lon: Optional for region-mapping and coarse analytics (units are degrees).
- security.is_proxy and security.is_vpn: Filter or flag risky traffic.
- query: Echo of the looked-up IP, helpful for logging and debugging.
JavaScript example: fetch country and enforce region rules
This code calls the same /api/ip endpoint, parses the JSON, and applies simple rules for country and proxy/VPN checks. Replace YOUR_KEY with your token for real use.
async function lookupIpCountry(ip) {
const url = `https://ipxapi.com/api/ip?ip=${encodeURIComponent(ip)}`;
const res = await fetch(url, {
method: "GET",
headers: {
"Accept": "application/json",
"Authorization": "Bearer YOUR_KEY"
},
// Optionally set a conservative client timeout with AbortController in production
});
if (!res.ok) {
// Avoid leaking details to users; log and handle gracefully
const text = await res.text().catch(() => "");
throw new Error(`ipxapi request failed (${res.status}): ${text}`);
}
const data = await res.json();
// Minimal required fields for country gating
const country = data.country; // e.g., "United States"
const code = data.countryCode; // e.g., "US"
const inEU = data.inEU === true; // booleans may vary
// Security flags (live signals): proxy/vpn/cloud
const security = data.security || {};
const isProxy = security.is_proxy === true;
const isVpn = security.is_vpn === true;
const isCloud = security.is_cloud_provider === true;
// Example decision logic:
// - allow only US and CA traffic
// - block proxy/vpn
const allowlist = new Set(["US", "CA"]);
const isAllowedCountry = allowlist.has(code);
return {
country,
countryCode: code,
inEU,
isProxy,
isVpn,
isCloud,
isAllowedCountry
};
}
// Example invocation using the documented fixture IP.
// Do not treat this fixture as the reader’s IP; it is a static example.
lookupIpCountry("148.105.12.120")
.then(result => {
console.log("IP geolocation result:", result);
if (!result.isAllowedCountry) {
console.log("Access restricted by country policy.");
}
if (result.isProxy || result.isVpn) {
console.log("Extra verification required due to proxy/VPN.");
}
})
.catch(err => {
console.error("Lookup error:", err);
});
Integration patterns with the IP to Country lookup
1) Country-based feature flags
Use countryCode to enable or disable features. Store countryCode in your session or user context. For server-rendered pages, fetch once at the edge or at the start of the request flow and pass the result downstream.
2) Consent and compliance gating
Read inEU to switch consent banners or data-handling paths. Because flags can change, do not hardcode by ASN or ISP; always trust the API field per request or per session.
3) Proxy/VPN friction
If security.is_proxy or security.is_vpn is true, add additional verification (e.g., MFA or proof-of-humanity) rather than outright blocking legitimate users. Keep this logic adjustable via a configuration flag.
4) Timezone-aware UX
Use timezone to format timestamps for receipts, schedules, and notifications. When writing logs or metrics, store UTC timestamps and display in the user’s timezone for UI rendering.
5) Geofencing API access
Protect sensitive API routes based on countryCode. Cache the lookup result for the request lifetime to reduce repeated calls, then refresh on subsequent sessions.
Field reference quick notes (with official sample)
Below is the same official sample, repeated for rapid reference while you write parsers and tests. Keep your parser tolerant for additional fields introduced in the future.
{
"status": "success",
"country": "United States",
"countryCode": "US",
"region": "US-CA",
"regionName": "California",
"city": "Mountain View",
"zip": "94043",
"lat": 37.40599,
"lon": -122.0786,
"timezone": "America/Los_Angeles",
"isp": "MailChimp",
"org": "MailChimp",
"as": "AS14782 MailChimp",
"query": "148.105.12.120",
"inEU": false,
"continentCode": "NA",
"security": {
"is_proxy": false,
"is_vpn": false,
"is_cloud_provider": true
}
}
- lat/lon are floats in degrees (WGS84). Do not assume meter-level precision; this is for country/region context.
- timezone is an IANA zone string (e.g., America/Los_Angeles), not a UTC offset. Offsets vary with DST.
- as, isp, and org are strings and can be helpful for fraud analytics, but avoid hardcoding behaviors based on them.
Performance, caching, and reliability
Where to call:
- At the edge or API gateway: Low-latency enforcement of country rules early in the request lifecycle.
- At session start: Cache the result for the duration of a user session to minimize repeated lookups.
Caching tips:
- Key by IP address and short TTL (e.g., minutes to hours). The country for an IP is relatively stable, but security flags can change—avoid long TTLs.
- Cache failures negatively: if the API is briefly unavailable, avoid hammering with retries from many instances.
Timeouts and retries:
- Use a conservative HTTP client timeout and bounded retries with jitter.
- On retry exhaustion, fall back to a neutral policy (e.g., restrict sensitive actions) rather than failing open.
Observability:
- Log the query, countryCode, inEU, and security flags, but do not log raw auth tokens.
- Emit metrics: success/error counts, p50/p95 latency, and hit/miss for your IP cache.
Testing and repeatable fixtures
Use the documented fixture IP 148.105.12.120 and the official sample below for deterministic tests. This ensures your parsing and decision logic remain stable across CI environments.
{
"status": "success",
"country": "United States",
"countryCode": "US",
"region": "US-CA",
"regionName": "California",
"city": "Mountain View",
"zip": "94043",
"lat": 37.40599,
"lon": -122.0786,
"timezone": "America/Los_Angeles",
"isp": "MailChimp",
"org": "MailChimp",
"as": "AS14782 MailChimp",
"query": "148.105.12.120",
"inEU": false,
"continentCode": "NA",
"security": {
"is_proxy": false,
"is_vpn": false,
"is_cloud_provider": true
}
}
When writing tests:
- Assert field presence and type (string, number, boolean, object).
- Avoid asserting on dynamic security booleans in live environments; pin your tests to the official sample for unit tests only.
- Build your code to ignore unknown future fields for forward compatibility.
Security model and privacy
Handling user IP responsibly:
- Process the IP in memory or short-lived logs; avoid storing IPs long-term unless required.
- If you must persist, hash with a rotation strategy or store only derived attributes like countryCode and inEU.
Security flags and decisions:
- Use security.is_proxy and security.is_vpn as signals to require additional proof, not a blanket ban.
- For cloud environments (security.is_cloud_provider), consider tightening rate limits or requiring authenticated sessions.
Pricing, trial, and rollout plan
Basic is $29.99/mo. The trial is 7 days or 50 requests. Start with a small rollout:
- Phase 1: Shadow mode. Call /api/ip for production traffic but do not enforce; log decisions.
- Phase 2: Partial enforcement. Apply rules to a percentage of traffic and measure impact.
- Phase 3: Full enforcement. Turn on all country and security checks with circuit breakers and fallbacks.
Create your account here: Register. For endpoint details, see: Documentation.
Operational runbook
Common runbook entries for on-call:
- High error rate: Switch to fallback policy and increase cache TTL for recent good lookups.
- Timeout spikes: Reduce concurrency and enable exponential backoff; confirm MCP status.
- Incorrect gating reports: Verify you’re using country or countryCode and not inferring from ISP/AS fields.
Change management:
- Gate new rules behind a feature flag and record the version in logs.
- Include an allowlist override to unblock impacted customers quickly.
FAQ
Q: Which endpoint should I call for IP-to-country?
A: Use GET /api/ip with the ip query parameter. Example: /api/ip?ip=148.105.12.120. Send Authorization: Bearer YOUR_KEY.
Q: Which fields are most important for country gating?
A: country and countryCode are primary. Use inEU for EU-related flows. timezone is useful for display, and security flags help with risk-based checks.
Q: How should I cache results?
A: Cache by IP with a short TTL. The country is relatively stable; however, proxy/vpn flags can change, so avoid multi-day TTLs.
Q: Do I need to parse latitude/longitude?
A: Not for country gating. lat/lon are provided (in degrees) if you need broader geolocation context or regional analytics.
Q: Can I use this sample JSON to test?
A: Yes. Use the documented fixture IP 148.105.12.120 and the official JSON samples above for unit tests. Do not assume these values match live traffic.
Ship your IP-to-country integration now. Start with the 7-day or 50-request trial, then move to Basic at $29.99/mo when you’re ready to scale. Create your account at Register and keep the Documentation and MCP handy for production.
