Skip to content

API reference

Endpoint

GET https://api.instantgeo.info/v1/geo

GET / is an alias. There is no POST.

Authentication

The key may be supplied three ways, checked in this order:

WhereExampleNotes
Query string?key=ig_pk_…Recommended for browsers — no preflight
Bearer tokenAuthorization: Bearer ig_sk_…Triggers a CORS preflight
HeaderX-API-Key: ig_sk_…Triggers a CORS preflight

Requests with no key are served at the free tier with a hard limit of 60 per hour per IP.

Parameters

ParameterDescription
keyYour publishable or secret key
fieldsComma-separated list to trim the response. Narrows what your plan allows; never widens it. Unknown names are ignored.

Response

{
"ip": "203.0.113.7",
"country": "ID",
"countryName": "Indonesia",
"continent": "AS",
"isEUCountry": false,
"region": "Jakarta",
"regionCode": "JK",
"city": "Jakarta",
"postalCode": "10110",
"latitude": "-6.2088",
"longitude": "106.8456",
"timezone": "Asia/Jakarta",
"asn": 64496,
"asOrganization": "EXAMPLE ISP",
"currency": "IDR",
"languages": ["id"],
"metroCode": null
}
FieldTypePlanNotes
ipstringPaidThe caller’s IP. Never stored by us.
countrystringFreeISO 3166-1 alpha-2
countryNamestringFreeEnglish name
continentstringFreeAF AN AS EU NA OC SA
isEUCountrybooleanPaidEU membership, post-Brexit
regionstringPaidFirst-level subdivision
regionCodestringPaidSubdivision code
citystringPaid
timezonestringPaidIANA identifier
postalCodestringPaidFrequently null outside NA and Europe
latitudestringPaidCity-level, not device-level
longitudestringPaid
asnnumberPaidAutonomous system number
asOrganizationstringPaidNetwork operator name
currencystringPaidISO 4217, derived from country
languagesstring[]PaidPrimary languages, derived from country
metroCodestringPaidUS only
partialbooleanPresent and true when geo data was incomplete

Every field can be null. A field your plan does not include is absent rather than null, so you can tell “not on your plan” apart from “we could not determine it”.

Accuracy

Coordinates are city-level, derived from the IP address. They are not GPS and should not be treated as a device location. A VPN, a corporate proxy, or a mobile carrier’s routing will place a caller somewhere they are not.

partial

When we cannot fully place an IP, you get a 200 with null fields and "partial": true. We do not return a 500 for missing geolocation — a page that breaks because a visitor is on an unusual network is worse than a page that falls back to a default.

Response headers

HeaderMeaning
Cache-Controlprivate, max-age=300 — cache it, please
X-RateLimit-LimitRequests included this period
X-RateLimit-RemainingRequests left
X-RateLimit-ResetUnix seconds until the period resets

Errors

Every non-2xx response has this shape:

{
"error": {
"code": "origin_not_allowed",
"message": "Origin \"https://evil.com\" is not allowed for key ig_pk_3lSd…. Add it at …",
"docs": "https://docs.instantgeo.info/errors/origin_not_allowed"
}
}

The message is written to be shown to a developer and acted on directly. The docs link goes to a page explaining that specific code.

StatusCode
401missing_keyNo key supplied
401malformed_keyWrong shape
401bad_signatureNot issued by us
401unknown_keyNo active record
401revoked_keyExplicitly revoked
403origin_not_allowedOrigin not on the allowlist
429rate_limitedPer-IP hourly limit
429quota_exceededMonthly included requests used
404not_foundNo such endpoint
500internal_errorOur fault

CORS

OPTIONS is answered immediately with Access-Control-Max-Age: 86400.

CORS headers are present on error responses too, so a 403 is readable by the calling page rather than showing up as an opaque network failure.

Putting the key in the query string avoids the preflight entirely — see caching for why that matters more than it usually would.

Privacy

We do not store the caller’s IP address. It appears in the response body and nowhere else — not in a log line, not in a table. That is enforced by a check in our CI, not just a policy.