One endpoint enriches any IPv4 or IPv6 address with geolocation, ASN, mobile/satellite, VPN/proxy/Tor, cloud, crawler, spam, anycast/multicast, and RIPE network data.
Prefer to see it first? Try the API live — no signup — then come back for the details. The full field list is in the API reference.
GET https://ipquery.info/api
Every request requires an apiKey query parameter. Create and manage keys on the API Keys page. Keep secret keys on your server; for public/client-side use, enable the Record-Only option so the key returns only an acknowledgement.
| Parameter | Required | Description |
|---|---|---|
apiKey | Yes | API key issued by IpQuery.Info. |
ip | No | A single IPv4/IPv6 address. Omit all selectors to query the caller's own IP. |
ipList | No | Comma-separated batch of addresses (whitespace stripped). The same list can be sent in a POST body for larger batches. |
fields | No | Comma-separated response fields to include, for example country_iso_code,is_vpn,risk_score. query_ip_address is always returned. |
tag | No | Arbitrary label (max 20 chars) recorded with single-address queries for analytics segmentation. |
ua | No | User-Agent string to use for crawler detection instead of the request header. Only meaningful with ip. |
reverse | No | Set to true to request bounded reverse-DNS enrichment. |
curl "https://ipquery.info/api?apiKey=YOUR_API_KEY&ip=8.8.8.8&tag=signup-flow"
const res = await fetch(
"https://ipquery.info/api?apiKey=YOUR_API_KEY&ip=8.8.8.8"
);
const data = await res.json();
console.log(data[0].country, data[0].is_vpn);
import requests
r = requests.get("https://ipquery.info/api", params={
"apiKey": "YOUR_API_KEY",
"ip": "8.8.8.8",
})
result = r.json()[0]
print(result["country"], result["asn_name"])
const https = require("https");
https.get(
"https://ipquery.info/api?apiKey=YOUR_API_KEY&ip=8.8.8.8",
(res) => {
let body = "";
res.on("data", (chunk) => (body += chunk));
res.on("end", () => {
const result = JSON.parse(body)[0];
console.log(result.country, result.is_vpn);
});
}
);
<?php
$query = http_build_query([
"apiKey" => "YOUR_API_KEY",
"ip" => "8.8.8.8",
]);
$json = file_get_contents("https://ipquery.info/api?$query");
$result = json_decode($json, true)[0];
echo $result["country"] . " " . $result["asn_name"];
package main
import (
"encoding/json"
"fmt"
"net/http"
)
func main() {
resp, _ := http.Get("https://ipquery.info/api?apiKey=YOUR_API_KEY&ip=8.8.8.8")
defer resp.Body.Close()
var results []map[string]interface{}
json.NewDecoder(resp.Body).Decode(&results)
fmt.Println(results[0]["country"], results[0]["asn_name"])
}
require "net/http"
require "json"
require "uri"
uri = URI("https://ipquery.info/api")
uri.query = URI.encode_www_form(apiKey: "YOUR_API_KEY", ip: "8.8.8.8")
result = JSON.parse(Net::HTTP.get(uri)).first
puts "#{result['country']} #{result['asn_name']}"
import java.net.URI;
import java.net.http.*;
HttpClient client = HttpClient.newHttpClient();
HttpRequest request = HttpRequest.newBuilder()
.uri(URI.create("https://ipquery.info/api?apiKey=YOUR_API_KEY&ip=8.8.8.8"))
.build();
HttpResponse<String> response =
client.send(request, HttpResponse.BodyHandlers.ofString());
System.out.println(response.body());
using System.Net.Http;
using System.Text.Json;
using var client = new HttpClient();
var json = await client.GetStringAsync(
"https://ipquery.info/api?apiKey=YOUR_API_KEY&ip=8.8.8.8");
using var doc = JsonDocument.Parse(json);
var first = doc.RootElement[0];
Console.WriteLine(first.GetProperty("country").GetString());
Pass a comma-separated ipList, or send a POST body containing a JSON array, JSON object with ips, or plain text/CSV list. The response is an array with one object per address, in order. Batch lookups are capped at 1,000 addresses, consume one unit of quota per address, and are not recorded in your analytics charts.
curl "https://ipquery.info/api?apiKey=YOUR_API_KEY&ipList=8.8.8.8,1.1.1.1,2606:4700:4700::1111"
curl -X POST "https://ipquery.info/api?apiKey=YOUR_API_KEY&fields=country_iso_code,is_vpn,risk_score" \
-H "Content-Type: application/json" \
-d '["8.8.8.8","1.1.1.1"]'