Call the free IP Reverse Lookup API endpoint
curl https://aisenseapi.com/services/v1/ip_reverse_lookup/8.8.8.8{
"ip": "8.8.8.8",
"country": "United States",
"city": null,
"location": {
"lat": "37.751000",
"lng": "-97.822000"
},
"place": null,
"timezone": "America/Chicago"
}Put the address in the path and read the JSON that comes back. Nothing else is required. There is no request body, no query string and no header to set, so the URL is the entire interface.
That keeps the call portable. A browser address bar, a shell script, a container entrypoint, a build step and a language model with a fetch tool all reach it the same way, and none of them needs a credential first.
Response fields
| Field | Type | Description |
|---|---|---|
| ip | string | The address that was looked up. |
| country | string | Country name. |
| city | string or null | City name when the database has a city-level match. |
| location.lat | string or null | Latitude. The JSON value is a string, not a number. |
| location.lng | string or null | Longitude. The JSON value is a string, not a number. |
| place | string or null | A more specific place name when available. |
| timezone | string or null | IANA timezone identifier such as America/Chicago. |
Six values arrive in a flat object, with the two coordinates nested under location. Watch the types before you do arithmetic. Latitude and longitude come back as quoted strings, so cast them to numbers rather than feeding them straight into a distance calculation.
Nulls are normal, so handle them
This is the part most callers get wrong. A record can arrive with almost nothing in it, and the shape of the response never warns you in advance.
curl https://aisenseapi.com/services/v1/ip_reverse_lookup/1.1.1.1{
"ip": "1.1.1.1",
"country": "Australia",
"city": null,
"location": {
"lat": null,
"lng": null
},
"place": null,
"timezone": null
}That address belongs to one of the best known public resolvers on the internet, and the free IP Reverse Lookup API endpoint answers with a country and nothing else. City, place, both coordinates and the timezone are all null in a single response.
The Google resolver at 8.8.8.8 does only a little better. It returns coordinates and a timezone, yet its city and place fields are null too. Two of the most heavily documented addresses in existence, and neither of them yields a city.
Other addresses fill in far more. Quad9 at 9.9.9.9 comes back with a city name attached:
{
"ip": "9.9.9.9",
"country": "United States",
"city": "Berkeley",
"location": {
"lat": "37.876700",
"lng": "-122.267600"
},
"place": null,
"timezone": "America/Los_Angeles"
}So the structure stays constant while the contents vary from one address to the next. Write your client against fields that may be null instead of against whichever example happened to work during development. An absent city is an ordinary outcome, not a fault, and code that dereferences it blindly will fail in production on the first quiet address it meets.
Read the coordinates with care
Look at the 8.8.8.8 result again. Latitude 37.751000 and longitude -97.822000 land in rural Kansas, close to the geographic center of the United States. No Google server sits there.
Those numbers are a country centroid. When the database has no city-level match, the coordinates fall back to the middle of the country, which is a placeholder rather than a position. That is why a null city matters more than it first appears: it quietly tells you the coordinates beside it are country-level guesses.
Treat a null city as a signal to drop precision. Show the country, skip the map pin, and you avoid dropping a marker in an empty field.
Do not use IP geolocation alone for identity, legal location, fraud decisions or access control. VPNs, mobile carriers and corporate routing regularly report a point hundreds of miles from the person using the connection.
Errors and input rules
One IPv4 address goes in the path. Two failure modes are worth knowing before you ship anything that depends on this call.
First, an address the database cannot resolve. A private range address such as 10.0.0.1 returns an error object, and it does so with HTTP 200:
{"error":"mmdblookup failed or returned non-zero exit code"}A malformed quad such as 999.999.999.999 produces exactly the same body. Private ranges have no public geography to report, so send routable addresses only.
Second, a path segment that is not shaped like an IPv4 address never reaches the route at all. An IPv6 literal or a missing segment returns HTTP 404 with a different body:
{"error":"Unknown endpoint. See https://www.aisense.no/free-public-apis for the reference."}Check for an error key rather than trusting the status code by itself. The free IP Reverse Lookup API endpoint reports a failed lookup with a 200, while every successful response carries an ip field. Testing for that field is the simplest reliable guard.
From an address to a usable answer
- Call once and cache
An address rarely changes country between requests. Store the result keyed on the address and reuse it, which keeps you well inside the daily budget.
- Branch on nulls
Read
countryfirst, then treatcity,place,timezoneand the coordinates as optional extras that may or may not be present. - Degrade in the interface
Offer a suggested timezone when one arrives and a plain picker when it does not. Never let a null field become the string "null" in front of a user.
Going the other way
This route starts from an address. When you start from a hostname instead, reach for the Domain IP Lookup API endpoint, which resolves a name to the addresses behind it. The two chain neatly. Resolve the domain, then geolocate whichever address came back.
To learn the address you are calling from in the first place, the Client IP API endpoint reports the public address this server sees. Feed that value into this lookup and you have a country and, with luck, a timezone for your own egress path.
Response headers
A live call returns HTTP 200 with content-type: application/json. Two further headers shape how you can use it.
access-control-allow-origin: *
cache-control: no-store, no-cache, must-revalidate, max-age=0The open CORS header lets browser JavaScript read the response directly, so a status page or support widget can resolve an address without a backend proxy in the middle. The cache directives stop proxies and browsers from replaying a stale record.
Common uses
Timezone defaults
Suggest a likely timezone before asking a user to confirm it, and keep a fallback ready for the many addresses that return null.
Regional defaults
Pick a country-level default for language, currency or support routing before a visitor has told you anything about themselves.
Log enrichment
Add approximate country and timezone columns to request logs so traffic reports read in local terms rather than raw addresses.
Risk signals
Feed country context into a wider review process as one weak signal among several, never as a verdict on its own.
Agent lookups
Let a language model resolve an address to a country in one unauthenticated call, with no SDK to install and no key to store.
Privacy and limits
The lookup runs against local MaxMind and DB-IP database files. The address you query is not forwarded to a third party geolocation service.
The service-wide limit is 5000 requests per IP per 24 hours, with no key and no account. That is generous for enrichment work and still finite, so cache results instead of resolving the same address on every page view.
This route sits in the same family as the Ping API endpoint and the Health Check API endpoint, and all of them share that quota. To see what a client reports about itself rather than where it sits, read the User Agent API endpoint. The full catalogue lives on the free public REST APIs hub.