GeoIP Lookup

Predictable, cacheable geographic IP lookup with explicit parameters

Explicit Parameters Design

ResolveDB uses explicit parameters for all GeoIP queries. The server never infers location from the client's IP address, providing predictability, cache efficiency, and privacy.

BenefitDescription
PredictabilitySame query returns same result from anywhere—CI, staging, production
Cache efficiencyNo ECS fragmentation. One cached response serves all users globally
PrivacyServer never learns your IP. You control what data is shared
CompatibilityWorks through DoH/DoT, VPNs, corporate proxies, Tor

Multi-Region DNS Cluster

ResolveDB operates authoritative nameservers across multiple geographic regions:

User (NYC)              User (LA)              User (Berlin)
        |                       |                       |
        v                       v                       v
   +---------+            +---------+            +---------+
   | Public  |            | Public  |            | Public  |
   |  DNS    |            |  DNS    |            |  DNS    |
   +----+----+            +----+----+            +----+----+
        |                      |                      |
        |    Anycast / GeoDNS routing                 |
        v                      v                      v
   +---------+            +---------+            +---------+
   |  ns01   |            |  ns02   |            |  ns03   |
   |  NYC    |            |  SFO    |            |  AMS    |
   +---------+            +---------+            +---------+

Multi-Region Deployment

ResolveDB runs authoritative nameservers across multiple strategic regions to minimize latency:

ServerLocationCoverage
ns01.resolvedb.netUS EastAmericas
ns02.resolvedb.netUS WestPacific, Asia
ns03.resolvedb.netEuropeEMEA

DNS clients automatically route to the nearest available server via the resolver infrastructure.

GeoIP Lookup

GeoIP lookups require an explicit IP address parameter. The server does NOT infer from the client's source IP.

Query Format

# IPv4: use geoip operation with ip- prefix (dots as hyphens)
dig geoip.ip-8-8-8-8.public.v1.resolvedb.net TXT +short

# HTTP JSON API (explicit IP required)
curl "https://api.resolvedb.io/resolve?name=geoip.ip-8-8-8-8.public.v1.resolvedb.net&type=TXT"

# HTTP GeoIP endpoint
curl "https://api.resolvedb.io/geoip?ip=8.8.8.8"

Response Format

v=rdb1;s=ok;t=data;e=plain;ip=8.8.8.8;cc=US;cn=United States;rg=California;ct=Mountain View;lat=37.386;lon=-122.084;tz=America/Los_Angeles;isp=Google LLC

Response Fields

FieldDescriptionExample
ipIP address looked up"8.8.8.8"
ccCountry code (ISO 3166-1)"US"
cnCountry name"United States"
rgRegion/state"California"
ctCity"Mountain View"
latLatitude37.386
lonLongitude-122.084
tzTimezone"America/Los_Angeles"
ispISP name"Google LLC"

Why Explicit Parameters?

Traditional GeoDNS (Broken)ResolveDB (Explicit)
Server infers from source IPClient provides IP in query
Different results from different networksSame query = same result everywhere
Breaks through VPNs/proxiesWorks through any network path
Thousands of ECS-scoped cache entriesOne cached response serves all users
Can't test in CI (wrong location)Testable and debuggable from anywhere
Server logs reveal your locationYou control what data is shared

Location-Based Queries

For weather and other location-based data, provide explicit location parameters. ResolveDB supports multiple location input formats.

Location Input Formats

FormatExample QueryDescription
City nameget.london.weather...City name, hyphens for multi-word
Coordinatesget.51d5074_-0d1278.weather...Lat/lon with d as decimal point
IP addressget.ip-8-8-8-8.weather...Weather at IP's geolocation
what3wordsget.w3w-filled-count-soap.weather...3m x 3m precision

City-Based Queries

# Query weather by city name (use city name directly, hyphens for multi-word)
dig TXT get.newyork.weather.public.v1.resolvedb.net +short
dig TXT get.london.weather.public.v1.resolvedb.net +short
dig TXT get.tokyo.weather.public.v1.resolvedb.net +short
dig TXT get.san-francisco.weather.public.v1.resolvedb.net +short

Coordinate-Based Queries

# Query weather by latitude/longitude
# Format: {lat}d{decimals}_{lon}d{decimals} where d = decimal point
dig TXT get.51d5074_-0d1278.weather.public.v1.resolvedb.net +short  # London
dig TXT get.40d7128_-74d0060.weather.public.v1.resolvedb.net +short # NYC
dig TXT get.35d6762_139d6503.weather.public.v1.resolvedb.net +short # Tokyo

what3words Queries

what3words divides the world into 3m x 3m squares, each with a unique 3-word address. Perfect for precise location queries.

# Query weather by what3words address
# Format: w3w-{word}-{word}-{word} (hyphens replace dots)
dig TXT get.w3w-filled-count-soap.weather.public.v1.resolvedb.net +short
dig TXT get.w3w-index-home-raft.weather.public.v1.resolvedb.net +short

# Via DoH (HTTPS)
curl -s "https://api.resolvedb.io/resolve?name=get.w3w-filled-count-soap.weather.public.v1.resolvedb.net&type=TXT" | jq

IP-Based Weather Queries

# Get weather for an IP address's location
dig TXT get.ip-8-8-8-8.weather.public.v1.resolvedb.net +short
dig TXT get.ip-1-1-1-1.weather.public.v1.resolvedb.net +short

Example response:

v=rdb1;s=ok;t=data;ttl=300;ts=...;loc=Mountain View, California, United States;tc=12.5;tf=54.5;cnd=clear;wnd=8.0;hum=65;d1=10/18/clear;d2=11/19/partly_cloudy;d3=12/20/clear

Weather Response Fields

FieldDescriptionExample
locResolved location name"London, England, United Kingdom"
tcTemperature (Celsius)8.5
tfTemperature (Fahrenheit)47.3
cndCurrent conditionsclear, cloudy, rain, snow, fog
wndWind speed (km/h)12.0
humHumidity (%)72
d1-d33-day forecast (min/max/conditions)6/10/rain

Use Cases

Region-Specific Configuration

Fetch configuration for a specific region by including the region in the query:

# Fetch US-specific config
dig TXT get.region-us.config.hooli.v1.resolvedb.net +short
# Response: {"currency":"USD","language":"en-US","dateFormat":"MM/DD/YYYY"}

# Fetch EU-specific config
dig TXT get.region-eu.config.hooli.v1.resolvedb.net +short
# Response: {"currency":"EUR","language":"en-GB","dateFormat":"DD/MM/YYYY"}

Edge Server Selection

Get the nearest edge server by specifying a region:

# Get edge server for US East
dig get.region-us-east.edge.cdn.v1.resolvedb.net TXT +short
# Response: {"server":"edge-nyc.example.com","region":"us-east-1"}

# Get edge server for Europe
dig get.region-eu-west.edge.cdn.v1.resolvedb.net TXT +short
# Response: {"server":"edge-ams.example.com","region":"eu-west-1"}

Regional Feature Flags

Fetch feature flags for specific regions:

# EU features (GDPR compliance)
dig TXT get.region-eu.features.hooli.v1.resolvedb.net +short
# Response: {"analytics":false,"thirdPartyCookies":false,"dataExport":true}

# US features
dig TXT get.region-us.features.hooli.v1.resolvedb.net +short
# Response: {"analytics":true,"thirdPartyCookies":true,"dataExport":true}

Key Principle: The client chooses which region's data to fetch. The server never infers region from the client's IP.

Private IP Handling

When looking up private/local IP ranges, the GeoIP service returns a response indicating a private network:

# Looking up a private IP address
dig geoip.ip-192-168-1-100.public.v1.resolvedb.net TXT +short
# Response: v=rdb1;s=ok;t=data;ttl=86400;ip=192.168.1.100;cc=--;co=Private Network;isp=Private

Private IP detection includes:

  • IPv4: 10.0.0.0/8, 172.16.0.0/12, 192.168.0.0/16
  • IPv6: fc00::/7 (unique local), fe80::/10 (link-local)
  • Loopback: 127.0.0.0/8, ::1

Caching

  • GeoIP responses use TTL of 300 seconds (5 minutes) by default
  • Since queries require explicit IP parameters, responses are fully cacheable
  • Same query always returns the same result (cache-friendly)
  • No ECS scope fragmentation since location is explicit in query

Privacy Best Practices

For applications handling sensitive data, use multiple layers of protection:

LayerHow to Use
Transport encryptionQuery via DoH (https://dns.google/resolve?name=...) to encrypt in transit
Client-side encryptionEncrypt data with AES-256-GCM before storing; server never sees plaintext
Token privacyUse h-<hash> prefix instead of exposing tokens in DNS query logs
Authenticated namespacesUse organization namespaces (hooli.v1.resolvedb.net) with JWT auth
// Client-side encryption example
const key = await crypto.subtle.generateKey(
  { name: 'AES-GCM', length: 256 }, true, ['encrypt', 'decrypt']
);
const iv = crypto.getRandomValues(new Uint8Array(12));
const encrypted = await crypto.subtle.encrypt({ name: 'AES-GCM', iv }, key, sensitiveData);

// Store encrypted - server never sees plaintext
await resolvedb.put('secrets.api-key.hooli.v1', base64(iv + encrypted));

Best Practices

  1. Explicit parameters - Always provide IP or location, never rely on implicit detection
  2. Cache responses - Default 5-minute TTL works for most use cases
  3. Handle failures - Design for cases where GeoIP data is unavailable
  4. Test anywhere - Same query from CI, staging, or prod returns same result
  5. Encrypt sensitive data - Use client-side encryption for secrets

Complete Example

// GeoIP lookup with explicit IP address
async function lookupGeoIP(ipAddress) {
  // Encode IP for DNS query (dots -> hyphens)
  const encodedIp = ipAddress.replace(/\./g, '-');
  const query = `geoip.ip-${encodedIp}.public.v1.resolvedb.net`;

  const response = await dnsQuery(query);
  return parseGeoResponse(response);
}

// Location-aware configuration with explicit region
async function getRegionalConfig(region) {
  const query = `get.region-${region}.config.hooli.v1.resolvedb.net`;
  const response = await dnsQuery(query);
  return parseUqrpResponse(response);
}

// Parse UQRP response format
function parseUqrpResponse(response) {
  const dataMatch = response.match(/d=(.+)$/);
  if (dataMatch) {
    return JSON.parse(dataMatch[1]);
  }
  throw new Error('Invalid UQRP response');
}

// Usage: Client explicitly provides the IP they want to look up
const geoInfo = await lookupGeoIP('8.8.8.8');
console.log(`IP ${geoInfo.ip} is in ${geoInfo.ct}, ${geoInfo.cn}`);
// Output: IP 8.8.8.8 is in Mountain View, United States

// Client explicitly chooses which region's config to fetch
const config = await getRegionalConfig('us');
console.log(`Currency: ${config.currency}`);
// Output: Currency: USD

Next Steps