API Documentation

Build powerful location-aware applications with our simple and reliable IP geolocation API

<50ms

Avg Response Time

99.9%

Uptime SLA

Weekly

Database Updates

HTTPS

Encrypted Requests

Quick Start

Get started with our IP Geolocation API in minutes. No credit card required for the free tier.

3 Simple Steps
1
Sign Up

Create a free account to get your API token

2
Get Your Key

Copy your API token from the dashboard

3
Make Requests

Start making API calls immediately

Try it now! You can make unauthenticated requests to test the API immediately with 60 requests per minute.

Base URL

All API endpoints are relative to the base URL:

https://ip-api.in/api/v1

Authentication

Authenticate your API requests using a Bearer token in the Authorization header. This gives you higher rate limits and access to usage analytics.

Authentication Header
Authorization: Bearer YOUR_API_TOKEN
Accept: application/json
With Authentication
  • ✓ 200 requests/min
  • ✓ Usage analytics
  • ✓ Priority support
  • ✓ Account management
Without Authentication
  • • 60 requests/min
  • • No analytics
  • • Community support
  • • Limited by IP address
Pro Tip: Get your API token from your dashboard after signing up. It's completely free!

GET

/ip/{ip_address}

Retrieve comprehensive geolocation information for any IPv4 or IPv6 address.

Path Parameters
Parameter Type Required Description
ip_address string Required The IPv4 or IPv6 address to lookup (e.g., 8.8.8.8 or 2001:4860:4860::8888)
Example Request
curl -X GET "https://ip-api.in/api/v1/ip/8.8.8.8" \
  -H "Authorization: Bearer YOUR_API_TOKEN" \
  -H "Accept: application/json"
$client = new GuzzleHttp\Client();
$response = $client->request('GET', 'https://ip-api.in/api/v1/ip/8.8.8.8', [
    'headers' => [
        'Authorization' => 'Bearer YOUR_API_TOKEN',
        'Accept' => 'application/json',
    ],
]);

$data = json_decode($response->getBody(), true);
echo $data['data']['country'];
import requests

url = "https://ip-api.in/api/v1/ip/8.8.8.8"
headers = {
    "Authorization": "Bearer YOUR_API_TOKEN",
    "Accept": "application/json"
}

response = requests.get(url, headers=headers)
data = response.json()
print(data['data']['country'])
fetch('https://ip-api.in/api/v1/ip/8.8.8.8', {
    headers: {
        'Authorization': 'Bearer YOUR_API_TOKEN',
        'Accept': 'application/json'
    }
})
.then(response => response.json())
.then(data => console.log(data.data.country));
Success Response (200 OK)
{
  "success": true,
  "message": "IP lookup successful",
  "api_version": "v1",
  "data": {
    "ip": "8.8.8.8",
    "country": "United States",
    "country_code": "US",
    "region": "California",
    "region_code": "CA",
    "city": "Mountain View",
    "postal_code": "94035",
    "latitude": 37.386,
    "longitude": -122.0838,
    "timezone": "America/Los_Angeles",
    "continent": "North America",
    "continent_code": "NA",
    "asn": "AS15169",
    "organization": "GOOGLE",
    "is_in_european_union": false
  }
}

GET

/ip

Automatically detect and geolocate the IP address making the request. Perfect for client-side integrations.

Example Request
curl -X GET "https://ip-api.in/api/v1/ip" \
  -H "Accept: application/json"
No authentication required! This endpoint works without an API token and returns information about the requester's IP address.

POST

/ip/bulk

Look up multiple IP addresses in a single request. More efficient than making individual calls.

Request Body
Field Type Required Description
ips array Required Array of IP addresses to lookup (max 100 per request)
Example Request
curl -X POST "https://ip-api.in/api/v1/ip/bulk" \
  -H "Authorization: Bearer YOUR_API_TOKEN" \
  -H "Content-Type: application/json" \
  -d '{
    "ips": ["8.8.8.8", "1.1.1.1", "208.67.222.222"]
  }'
Example Response
{
  "success": true,
  "message": "Bulk lookup successful",
  "api_version": "v1",
  "count": 3,
  "data": {
    "8.8.8.8": {
      "ip": "8.8.8.8",
      "country": "United States",
      "country_code": "US",
      ...
    },
    "1.1.1.1": {
      "ip": "1.1.1.1",
      "country": "Australia",
      "country_code": "AU",
      ...
    },
    "208.67.222.222": {
      "ip": "208.67.222.222",
      "country": "United States",
      "country_code": "US",
      ...
    }
  }
}

Rate Limits

Our API uses rate limiting to ensure fair usage and maintain service quality for all users.

Unauthenticated
60

requests per minute

  • No signup required
  • Limited by IP address
  • Resets every minute
Authenticated
200+

requests per minute

  • Free tier available
  • 3.3x higher limits
  • Upgrade for more
Rate Limit Headers

Every response includes headers showing your current rate limit status:

X-RateLimit-Limit: 60
X-RateLimit-Remaining: 59
X-RateLimit-Reset: 1734088620
When you exceed your rate limit, you'll receive a 429 Too Many Requests response. Wait for the reset time or upgrade your plan for higher limits.

Error Handling

Our API uses standard HTTP status codes and returns detailed error messages in JSON format.

Common HTTP Status Codes
Code Status Description
200 OK Request successful
400 Bad Request Invalid request parameters
401 Unauthorized Invalid or missing API token
404 Not Found IP address not found in database
429 Too Many Requests Rate limit exceeded
500 Server Error Internal server error
Error Response Format
{
  "success": false,
  "message": "Too Many Requests",
  "error": "Rate limit exceeded",
  "code": 429,
  "retry_after": 60
}

Response Fields

Detailed description of all fields returned in a successful response.

Field Type Description
ip string The IP address that was queried
country string Full country name
country_code string ISO 3166-1 alpha-2 country code
region string|null Region or state name
region_code string|null Region or state code
city string|null City name
postal_code string|null Postal or ZIP code
latitude float Latitude coordinate
longitude float Longitude coordinate
timezone string Timezone identifier (e.g., America/New_York)
continent string Continent name
continent_code string Two-letter continent code
asn string|null Autonomous System Number
organization string|null ISP or organization name
is_in_european_union boolean Whether the country is in the EU

Code Examples

Ready-to-use code examples in popular programming languages. Copy and paste to integrate our API into your application.

cURL
curl -X GET "https://ip-api.in/api/v1/ip/8.8.8.8" \
  -H "Authorization: Bearer YOUR_API_TOKEN" \
  -H "Accept: application/json"
PHP (with Guzzle)
$client = new \GuzzleHttp\Client([
    'base_uri' => 'https://ip-api.in/api/v1',
    'headers' => [
        'Authorization' => 'Bearer YOUR_API_TOKEN',
        'Accept' => 'application/json',
    ],
]);

try {
    $response = $client->get('/ip/8.8.8.8');
    $data = json_decode($response->getBody(), true);
    
    if ($data['success']) {
        echo "Country: " . $data['data']['country'] . "\n";
        echo "City: " . $data['data']['city'] . "\n";
        echo "Latitude: " . $data['data']['latitude'] . "\n";
        echo "Longitude: " . $data['data']['longitude'] . "\n";
    }
} catch (\Exception $e) {
    echo "Error: " . $e->getMessage();
}
PHP (Native - file_get_contents)
$url = "https://ip-api.in/api/v1/ip/8.8.8.8";

$options = [
    'http' => [
        'header' => "Authorization: Bearer YOUR_API_TOKEN\r\n" .
                    "Accept: application/json\r\n",
        'method' => 'GET'
    ]
];

$context = stream_context_create($options);
$response = file_get_contents($url, false, $context);
$data = json_decode($response, true);

if ($data['success']) {
    echo "Country: " . $data['data']['country'] . "\n";
    echo "City: " . $data['data']['city'] . "\n";
}
Python (with requests)
import requests

url = "https://ip-api.in/api/v1/ip/8.8.8.8"
headers = {
    "Authorization": "Bearer YOUR_API_TOKEN",
    "Accept": "application/json"
}

response = requests.get(url, headers=headers)

if response.status_code == 200:
    data = response.json()
    if data['success']:
        print(f"Country: {data['data']['country']}")
        print(f"City: {data['data']['city']}")
        print(f"Latitude: {data['data']['latitude']}")
        print(f"Longitude: {data['data']['longitude']}")
else:
    print(f"Error: {response.status_code}")
JavaScript (Fetch API - Browser/Node.js)
fetch('https://ip-api.in/api/v1/ip/8.8.8.8', {
    method: 'GET',
    headers: {
        'Authorization': 'Bearer YOUR_API_TOKEN',
        'Accept': 'application/json'
    }
})
.then(response => response.json())
.then(data => {
    if (data.success) {
        console.log('Country:', data.data.country);
        console.log('City:', data.data.city);
        console.log('Latitude:', data.data.latitude);
        console.log('Longitude:', data.data.longitude);
    }
})
.catch(error => console.error('Error:', error));
Node.js (with Axios)
const axios = require('axios');

axios.get('https://ip-api.in/api/v1/ip/8.8.8.8', {
    headers: {
        'Authorization': 'Bearer YOUR_API_TOKEN',
        'Accept': 'application/json'
    }
})
.then(response => {
    const data = response.data;
    if (data.success) {
        console.log('Country:', data.data.country);
        console.log('City:', data.data.city);
        console.log('Latitude:', data.data.latitude);
        console.log('Longitude:', data.data.longitude);
    }
})
.catch(error => {
    console.error('Error:', error.message);
});
Ruby
require 'net/http'
require 'json'

url = URI("https://ip-api.in/api/v1/ip/8.8.8.8")

http = Net::HTTP.new(url.host, url.port)
http.use_ssl = true

request = Net::HTTP::Get.new(url)
request["Authorization"] = "Bearer YOUR_API_TOKEN"
request["Accept"] = "application/json"

response = http.request(request)
data = JSON.parse(response.body)

if data['success']
  puts "Country: #{data['data']['country']}"
  puts "City: #{data['data']['city']}"
  puts "Latitude: #{data['data']['latitude']}"
  puts "Longitude: #{data['data']['longitude']}"
end
Go (Golang)
package main

import (
    "encoding/json"
    "fmt"
    "io/ioutil"
    "net/http"
)

type Response struct {
    Success bool   `json:"success"`
    Message string `json:"message"`
    Data    struct {
        IP        string  `json:"ip"`
        Country   string  `json:"country"`
        City      string  `json:"city"`
        Latitude  float64 `json:"latitude"`
        Longitude float64 `json:"longitude"`
    } `json:"data"`
}

func main() {
    url := "https://ip-api.in/api/v1/ip/8.8.8.8"
    
    client := &http.Client{}
    req, err := http.NewRequest("GET", url, nil)
    if err != nil {
        fmt.Println("Error creating request:", err)
        return
    }
    
    req.Header.Add("Authorization", "Bearer YOUR_API_TOKEN")
    req.Header.Add("Accept", "application/json")
    
    resp, err := client.Do(req)
    if err != nil {
        fmt.Println("Error making request:", err)
        return
    }
    defer resp.Body.Close()
    
    body, err := ioutil.ReadAll(resp.Body)
    if err != nil {
        fmt.Println("Error reading response:", err)
        return
    }
    
    var response Response
    json.Unmarshal(body, &response)
    
    if response.Success {
        fmt.Printf("Country: %s\n", response.Data.Country)
        fmt.Printf("City: %s\n", response.Data.City)
        fmt.Printf("Latitude: %.2f\n", response.Data.Latitude)
        fmt.Printf("Longitude: %.2f\n", response.Data.Longitude)
    }
}
Java (with HttpURLConnection)
import java.io.BufferedReader;
import java.io.InputStreamReader;
import java.net.HttpURLConnection;
import java.net.URL;
import org.json.JSONObject;

public class IPLookup {
    public static void main(String[] args) {
        try {
            URL url = new URL("https://ip-api.in/api/v1/ip/8.8.8.8");
            HttpURLConnection conn = (HttpURLConnection) url.openConnection();
            
            conn.setRequestMethod("GET");
            conn.setRequestProperty("Authorization", "Bearer YOUR_API_TOKEN");
            conn.setRequestProperty("Accept", "application/json");
            
            BufferedReader in = new BufferedReader(
                new InputStreamReader(conn.getInputStream())
            );
            String inputLine;
            StringBuilder response = new StringBuilder();
            
            while ((inputLine = in.readLine()) != null) {
                response.append(inputLine);
            }
            in.close();
            
            JSONObject json = new JSONObject(response.toString());
            
            if (json.getBoolean("success")) {
                JSONObject data = json.getJSONObject("data");
                System.out.println("Country: " + data.getString("country"));
                System.out.println("City: " + data.getString("city"));
                System.out.println("Latitude: " + data.getDouble("latitude"));
                System.out.println("Longitude: " + data.getDouble("longitude"));
            }
            
        } catch (Exception e) {
            e.printStackTrace();
        }
    }
}
C# (.NET)
using System;
using System.Net.Http;
using System.Net.Http.Headers;
using System.Threading.Tasks;
using Newtonsoft.Json.Linq;

class Program
{
    static async Task Main(string[] args)
    {
        using (var client = new HttpClient())
        {
            client.DefaultRequestHeaders.Authorization = 
                new AuthenticationHeaderValue("Bearer", "YOUR_API_TOKEN");
            client.DefaultRequestHeaders.Accept.Add(
                new MediaTypeWithQualityHeaderValue("application/json"));
            
            try
            {
                var response = await client.GetAsync(
                    "https://ip-api.in/api/v1/ip/8.8.8.8"
                );
                response.EnsureSuccessStatusCode();
                
                string responseBody = await response.Content.ReadAsStringAsync();
                JObject json = JObject.Parse(responseBody);
                
                if ((bool)json["success"])
                {
                    Console.WriteLine($"Country: {json["data"]["country"]}");
                    Console.WriteLine($"City: {json["data"]["city"]}");
                    Console.WriteLine($"Latitude: {json["data"]["latitude"]}");
                    Console.WriteLine($"Longitude: {json["data"]["longitude"]}");
                }
            }
            catch (HttpRequestException e)
            {
                Console.WriteLine($"Error: {e.Message}");
            }
        }
    }
}
Swift (iOS/macOS)
import Foundation

let url = URL(string: "https://ip-api.in/api/v1/ip/8.8.8.8")!
var request = URLRequest(url: url)
request.httpMethod = "GET"
request.setValue("Bearer YOUR_API_TOKEN", forHTTPHeaderField: "Authorization")
request.setValue("application/json", forHTTPHeaderField: "Accept")

let task = URLSession.shared.dataTask(with: request) { data, response, error in
    if let error = error {
        print("Error: \(error.localizedDescription)")
        return
    }
    
    guard let data = data else { return }
    
    do {
        if let json = try JSONSerialization.jsonObject(with: data) as? [String: Any],
           let success = json["success"] as? Bool, success == true,
           let dataDict = json["data"] as? [String: Any] {
            
            print("Country: \(dataDict["country"] ?? "")")
            print("City: \(dataDict["city"] ?? "")")
            print("Latitude: \(dataDict["latitude"] ?? 0)")
            print("Longitude: \(dataDict["longitude"] ?? 0)")
        }
    } catch {
        print("JSON Error: \(error.localizedDescription)")
    }
}

task.resume()
Kotlin (Android)
import okhttp3.OkHttpClient
import okhttp3.Request
import org.json.JSONObject

fun getIPLocation() {
    val client = OkHttpClient()
    
    val request = Request.Builder()
        .url("https://ip-api.in/api/v1/ip/8.8.8.8")
        .addHeader("Authorization", "Bearer YOUR_API_TOKEN")
        .addHeader("Accept", "application/json")
        .build()
    
    client.newCall(request).execute().use { response ->
        if (response.isSuccessful) {
            val responseBody = response.body?.string()
            val json = JSONObject(responseBody)
            
            if (json.getBoolean("success")) {
                val data = json.getJSONObject("data")
                println("Country: ${data.getString("country")}")
                println("City: ${data.getString("city")}")
                println("Latitude: ${data.getDouble("latitude")}")
                println("Longitude: ${data.getDouble("longitude")}")
            }
        }
    }
}
Rust
use reqwest;
use serde_json::Value;

#[tokio::main]
async fn main() -> Result<(), Box> {
    let client = reqwest::Client::new();
    
    let response = client
        .get("https://ip-api.in/api/v1/ip/8.8.8.8")
        .header("Authorization", "Bearer YOUR_API_TOKEN")
        .header("Accept", "application/json")
        .send()
        .await?;
    
    let json: Value = response.json().await?;
    
    if json["success"].as_bool().unwrap_or(false) {
        println!("Country: {}", json["data"]["country"]);
        println!("City: {}", json["data"]["city"]);
        println!("Latitude: {}", json["data"]["latitude"]);
        println!("Longitude: {}", json["data"]["longitude"]);
    }
    
    Ok(())
}
PowerShell
$headers = @{
    "Authorization" = "Bearer YOUR_API_TOKEN"
    "Accept" = "application/json"
}

$response = Invoke-RestMethod -Uri "https://ip-api.in/api/v1/ip/8.8.8.8" -Headers $headers -Method Get

if ($response.success) {
    Write-Host "Country: $($response.data.country)"
    Write-Host "City: $($response.data.city)"
    Write-Host "Latitude: $($response.data.latitude)"
    Write-Host "Longitude: $($response.data.longitude)"
}
Note: Replace YOUR_API_TOKEN with your actual API token from your dashboard. For production use, ensure you handle errors appropriately and never expose your API token in client-side code.

Ready to Get Started?

Create a free account and start building with our IP Geolocation API