Overview

This API is built for developers who require high performance, low latency, and production-grade reliability at scale.
Our platform runs on a proprietary Anycast network with globally distributed, redundant, and self-scaling infrastructure, ensuring low-latency responses worldwide. The core is built with a highly optimized stack combining OpenResty and Rust, designed for maximum throughput and minimal overhead.
Geolocation databases are stored in a compact binary format and loaded directly into ultra-fast DDR5 RAM, enabling constant-time lookups without disk access. This architecture allows the API to process over 1 billion requests per day with stable performance.
Our database is updated multiple times per day and enhanced using AI-driven data aggregation and validation techniques, improving accuracy by continuously analyzing signals from multiple trusted sources.
With a clean and developer-friendly interface, flexible integration options, and predictable performance under heavy load, this API is designed to integrate seamlessly into modern production environments.


API Endpoints

Single IP Lookup

You can call the API by sending HTTP GET requests to http://ipwho.is/[IP address]

[IP address] can be an IPv4 or IPv6 address, or none to use the current IP address.

# Get details for 8.8.4.4
$ curl "http://ipwho.is/8.8.4.4"

# Get details for your own IP address
$ curl "http://ipwho.is/"

Our API is available over a secure HTTPS connection. Simply add https:// to the request URLs to make the requests secure.


Usage limits

This endpoint does not impose a monthly request limit. No API key is required.
To ensure fair usage, requests are limited to 1 request per second (~2.5M+ requests/month) per client IP address.
Short bursts are allowed; however, no more than 60 requests within any 60-second window are permitted.

CORS (JavaScript requests from your website) is not supported on this endpoint. This endpoint must be accessed from your backend (server-to-server), not directly from the browser.

If you exceed the rate limit, your requests will be rate-limited and will return HTTP 429 (Too Many Requests).
Your IP address will then be temporarily blocked for 5 minutes. If rate limit violations continue during the block period, additional 5-minute blocks will be applied consecutively after each expiration until the excessive activity stops.

The response includes a Retry-After header indicating the number of seconds until the rate limit resets.

Commercial use of this endpoint is not permitted.

Unlock the full power of our platform with the Premium Service — including access to the Bulk Endpoint, detailed usage analytics, advanced features, and commercial support.

The Premium Service also includes Currency Data, Security Data, CORS support, higher-accuracy results, and a 99.9% SLA to meet production-grade requirements.


Live demo

You can edit this query and experiment with the options:

GET
Actual response
{
    "ip": "8.8.4.4",
    "success": true,
    "type": "IPv4",
    "continent": "North America",
    "continent_code": "NA",
    "country": "United States",
    "country_code": "US",
    "region": "California",
    "region_code": "CA",
    "city": "Mountain View",
    "latitude": 37.3860517,
    "longitude": -122.0838511,
    "is_eu": false,
    "postal": "94039",
    "calling_code": "1",
    "capital": "Washington D.C.",
    "borders": "CA,MX",
    flag {
        "img": "https://cdn.ipwhois.io/flags/us.svg",
        "emoji": "🇺🇸",
        "emoji_unicode": "U+1F1FA U+1F1F8"
    },
    connection {
        "asn": 15169,
        "org": "Google LLC",
        "isp": "Google LLC",
        "domain": "google.com"
    },
    timezone {
        "id": "America/Los_Angeles",
        "abbr": "PDT",
        "is_dst": true,
        "offset": -25200,
        "utc": "-07:00",
        "current_time": "2022-04-22T14:31:48-07:00"
    },
    currency {
        "name": "US Dollar",
        "code": "USD",
        "symbol": "$",
        "plural": "US dollars",
        "exchange_rate": 1
    },
    security {
        "anonymous": false,
        "proxy": false,
        "vpn": false,
        "tor": false,
        "hosting": false
    },
    rate {
        "limit": 250000,
        "remaining": 50155
    }
}

Please note: For illustration purposes, we have included all available fields in the above API response. Depending on your subscription plan, the API response may vary.


Returned data

Depending on your subscription plan and the options you choose for your API request, the response will contain a number of different fields. Below is a list of all available API response fields:

name description
ip IP used for the query (e.g. 8.8.4.4)
success If the query is successful, true will be returned, and false if it fails.
message Included only when success is false
Can be one of the following: See error codes
type IP address type (IPv4 or IPv6)
continent The name of the continent (e.g. North America)
continent_code Two-letter (ISO 3166-1) continent code (e.g. NA)
country The name of the сountry (e.g. United States)
country_code Two-letter (ISO 3166-1) country code (e.g. US)
region The name of the region/state (e.g. California)
region_code The state/region code (ISO 3166-2), when available (e.g. CA)
city The name of the city (e.g. Mountain View)
latitude The approximate (WGS84) latitude of the location associated with the IP (e.g. 37.3860517)
longitude The approximate (WGS84) longitude of the location associated with the IP (e.g. -122.0838511)
is_eu Returns true or false depending on whether the country associated with the IP is in the European Union.
postal The ZIP code associated with location.
calling_code The calling/dial code of the country (e.g. 1)
capital The capital city of the country (e.g. Washington)
borders Two-letter (ISO 3166-1) code of the countries that border the country associated with this IP (e.g. CA,MX)
flag > img Returns an HTTP URL leading to an SVG-flag icon for the country.
flag > emoji An emoji version of the flag of the country (e.g. 🇺🇸)
flag > emoji_unicode The unicode value of the emoji icon for the flag.
connection > asn The Autonomous System (AS) Number (e.g. 15169)
connection > org The name of the organization that owns the Autonomous System for the IP address that is analyzed (e.g. Google LLC)
connection > isp The name of the ISP associated with the IP (e.g. Google LLC)
connection > domain The domain name associated with the organization that owns the connection IP (e.g. google.com)
timezone > id The ID of the time zone associated with location (e.g. America/Los_Angeles)
timezone > abbr The Abbreviation of the Timezone (e.g. PDT)
timezone > is_dst true or false depending on whether or not Daylight Savings have been accounted for.
timezone > offset The offset from UTC (in seconds) for the given location (e.g. -25200 for PDT's -7h UTC offset)
timezone > utc The UTC offset of the Timezone (e.g. -07:00)
timezone > current_time The exact current date and time (ISO 8601 format) associated with location (e.g. 2022-04-22T14:31:48-07:00)
currency > name The name of the currency (e.g. US Dollar)
currency > code The 3-letter (ISO 4217) currency code (e.g. USD)
currency > symbol The native (local) symbol of the given currency (e.g. $)
currency > plural The plural version of the currency (e.g. US dollars)
currency > exchange_rate The current exchange rate against the US dollar.
security > anonymous Boolean with true value if proxy, vpn OR tor is satisfied.
security > proxy true or false depending on whether the IP Address is a known proxy or any type.
security > vpn Returns true when the IP address under search is used by a VPN, false otherwise.
security > tor true or false depending on whether the IP Address is a known Tor exit node or relay.
security > hosting true or false depending on whether the IP address is used for hosting purposes.
rate > limit The total number of API requests that your account is limited to over the given time period (month).
rate > remaining The number of API requests remaining in the given time period (month).

Specify Output Format

Using the GET parameter output, you can switch the API result format between JSON (default), XML and CSV. If you are using JSON, this parameter can be omitted.

For example:
output=xml
output=csv
output=json

Specify response fields

You can restrict API results to specific data fields if you don’t need to keep track of all the data. In this case, you need to add the GET parameter fields to the API request's URL and set a specific field or fields list with a comma.

For example:
fields=country,city,flag.emoji
fields=city,timezone
fields=ip,timezone.current_time

Localization

Localized city, region, country, capital and continent can be requested by setting the GET parameter lang to one of the following:

lang description demo
en English (default)
ru Русский (Russian)
de Deutsch (German)
es Español (Spanish)
pt-BR Português - Brasil (Portuguese)
fr Français (French)
zh-CN 中国 (Chinese)
ja 日本語 (Japanese)

Enable Threat Detection

Available in: Business and Premium Plan

Security Data return fields (proxy, vpn, tor, hosting) for threat detection. This will allow you to protect your site or application from abuse in the form of bypassing a ban, hiding the real IP address, site parsing, etc. In order to use this feature, append the GET parameter security to your API request URL and set it to 1.

{
    [...],
    security {
        "anonymous": true,
        "proxy": false,
        "vpn": true,
        "tor": false,
        "hosting": false,
    }
}
For example:
security=1

Rate information in the API response

Available in: Basic, Business and Premium Plan

In order to use this feature, append the GET parameter rate to your API request URL and set it to 1.
Here is an example (in JSON format) of the information in the API response body:

{
    [...],
    rate {
        "limit": 250000,
        "remaining": 50155
    }
}
For example:
rate=1

Error codes

The API may return the following standard HTTP 4xx client error codes:

CodeReasonResponse
400Bad Request{"success":false,"message":"Bad Request"}
403CORS not allowed{"success":false,"message":"CORS is not supported on the Free plan"}
403Access denied{"success":false,"message":"The current subscription plan does not support this API endpoint"}
404URL Not Found{"success":false,"message":"404 not found"}
405HTTP method is not allowed{"success":false,"message":"HTTP method is not allowed"}
414Request-URI Too Large{"success":false,"message":"URI Too Long"}
429The limit has been exceeded{"success":false,"message":"Rate limit exceeded"}

In general, a 2xx HTTP status code indicates that the request was successfully processed.

However, in some cases the API may return a 200 OK response while indicating an application-level error in the response body. In such cases, the request was technically valid, but the operation could not be completed.

These responses include a JSON object with "success":false and an explanatory "message", for example:

HTTP Status CodeReasonResponse
200Incorrect IP address{"success":false,"message":"Invalid IP address"}
200Reserved IP address{"success":false,"message":"Reserved range"}

Code examples

Simple code examples in popular languages are given below:

  • PHP
  • Python
$ip = '8.8.4.4';
$ch = curl_init('http://ipwho.is/'.$ip);
curl_setopt($ch, CURLOPT_RETURNTRANSFER, true);
curl_setopt($ch, CURLOPT_HEADER, false);
$ipwhois = json_decode(curl_exec($ch), true);
curl_close($ch);
echo $ipwhois['country'] . ' ' . $ipwhois['flag']['emoji']; // Output: United States 🇺🇸
var ip = '8.8.4.4'; // Leave blank to lookup current IP address
var XMLHttp = new XMLHttpRequest();
XMLHttp.onreadystatechange = function() {
	if(this.readyState == 4 && this.status == 200) {
		var ipwhois = JSON.parse(this.responseText);
		console.log(ipwhois.country + ' ' + ipwhois.flag.emoji); // Output: United States 🇺🇸
	}
};
XMLHttp.open('GET', 'https://ipwho.is/' + ip, true);
XMLHttp.send();
var ip = '8.8.4.4'; // Leave blank to lookup current IP address
$.ajax({
	method: 'GET',
	url: 'https://ipwho.is/' + ip,
	dataType: 'json',
	success: function(ipwhois) {
		console.log(ipwhois.country + ' ' + ipwhois.flag.emoji); // Output: United States 🇺🇸
	}
});
import re
import json
from urllib2 import urlopen
ip = '8.8.4.4';
response = urlopen('http://ipwho.is/'+ip)
ipwhois = json.load(response)

# Output: United States 🇺🇸
print '{0} {1}'.format(ipwhois['country'],ipwhois['flag']['emoji'])
  • PHP
  • Javascript
// List of IP addresses to query, up to 100
$ips = array('8.8.4.4','1.1.1.1','2c0f:fb50:4003::');
$endpoint = 'http://ipwho.is/bulk?key=YOUR_API_KEY';
$options = array(
	'http' => array(
		'method' => 'POST',
		'header' => 'Content-Type: application/json',
		'content' => json_encode($ips)
	)
);
$response = json_decode(file_get_contents($endpoint, false, stream_context_create($options)), true);
foreach($response as $ipwhois)
{
	echo $ipwhois['ip'] . ' - ' . $ipwhois['country'] . ' ' . $ipwhois['flag']['emoji']."\n";
	// Output:
	// 8.8.4.4 - United States 🇺🇸
	// 1.1.1.1 - Australia 🇦🇺
	// 2c0f:fb50:4003:: - Kenya 🇰🇪
}
// List of IP addresses to query, up to 100
var IPs = ['8.8.4.4','1.1.1.1','2c0f:fb50:4003::'];
var endpoint = 'https://ipwho.is/bulk?key=YOUR_API_KEY';
var xhr = new XMLHttpRequest();
xhr.onreadystatechange = function() {
	if(this.readyState == 4 && this.status == 200) {
		var response = JSON.parse(this.responseText);
		response.forEach(function(ipwhois) {
			console.log(ipwhois.ip + ' - ' + ipwhois.country + ' ' + ipwhois.flag.emoji);
			// Output:
			// 8.8.4.4 - United States 🇺🇸
			// 1.1.1.1 - Australia 🇦🇺
			// 2c0f:fb50:4003:: - Kenya 🇰🇪
		});
	}
};
var data = JSON.stringify(IPs);
xhr.open('POST', endpoint, true);
xhr.send(data);