API Documentation

Free IP geolocation API. 10,000 req/day. Zero logs. Powered by Cloudflare.

Overview

whatsmy.fyi provides a single REST endpoint that returns IP address, geolocation, and connection metadata for the requesting IP. All data comes directly from the Cloudflare edge network β€” no third-party databases, no caching, no IP query logging.

  • Free tier β€” 10,000 requests/day per key (Enterprise for unlimited)
  • No IP query logging β€” we never store the IPs you look up
  • Powered by Cloudflare Workers β€” global sub-50ms latency
  • Three scopes: ip, geo, full

Infrastructure & Reliability

whatsmy.fyi runs on Cloudflare Workers β€” the same global edge network that serves millions of production applications. There are no intermediate servers, no external database queries on the hot path, and no third-party IP lookup services.

Edge locations

300+ globally

Response time

p50 < 20ms worldwide

Infrastructure SLA

99.99% (Cloudflare)

IP data source

Native CF request context

Key validation

KV cache β€” no D1 on hot path

Health monitoring

Pinged every 5 minutes

Keyless endpoint

Just need your bare IP β€” no signup, no key? Use GET /ip. It returns plain text by default, or JSON with ?format=json β€” the same response shape as api.ipify.org, so it works as a drop-in replacement.

# Plain text
curl https://whatsmy.fyi/ip
# β†’ 203.0.113.42

# JSON (ipify-compatible)
curl "https://whatsmy.fyi/ip?format=json"
# β†’ {"ip":"203.0.113.42"}

CORS is enabled, both IPv4 and IPv6 are supported, and nothing is logged. For geolocation, ASN, and timezone data, use the authenticated /api/v1/ip endpoint below. See how we stack up against other IP APIs on the comparison page β†’

Base URL

https://whatsmy.fyi/api/v1

Authentication

All requests require an API key. Pass it as a Bearer token in the Authorization header (preferred) or as a key query parameter.

# Header (preferred)
curl https://whatsmy.fyi/api/v1/ip \
  -H "Authorization: Bearer wmf_your_api_key"

# Query parameter (fallback)
curl "https://whatsmy.fyi/api/v1/ip?key=wmf_your_api_key"

Don't have a key? Create a free account β†’

Scopes

Each API key has a scope that controls which fields are returned. You choose the scope when creating a key and can change it anytime from the dashboard.

IPIP address only

status, ip, ipv6

GeoIP address + location + networkdefault

status, ip, ipv6, city, region, region_code, country, country_name,
continent, latitude, longitude, timezone, timezone_offset, postal_code,
asn, org, as, is_eu, currency

FullGeo + connection details

Everything in Geo, plus: http_protocol, tls_version, tls_cipher, rtt, colo, proxy, hosting

You can also narrow the scope per request with the ?scope= query parameter β€” useful when one key serves multiple use cases. A request can never widen beyond the key's scope: a geo key with ?scope=full still returns geo fields.

# Key has "full" scope, but this request only needs the IP:
curl "https://whatsmy.fyi/api/v1/ip?scope=ip" \
  -H "Authorization: Bearer wmf_your_api_key"

Endpoint

GET/api/v1/ip

Returns IP metadata for the caller. The response shape depends on the key's scope.

Request

GET /api/v1/ip HTTP/1.1
Host: whatsmy.fyi
Authorization: Bearer wmf_your_api_key

Response by scope

{
  "status": "success",
  "ip": "203.0.113.42",
  "ipv6": null,
  "city": "Amsterdam",
  "region": "North Holland",
  "region_code": "NH",
  "country": "NL",
  "country_name": "Netherlands",
  "continent": "EU",
  "latitude": 52.374,
  "longitude": 4.8897,
  "timezone": "Europe/Amsterdam",
  "timezone_offset": 7200,
  "postal_code": "1011",
  "asn": 1101,
  "org": "SURF B.V.",
  "as": "AS1101 SURF B.V.",
  "is_eu": true,
  "currency": "EUR"
}

Response fields

The Scope column shows which key scope includes each field. ALL = all scopes, GEO+ = geo and full, FULL = full only.

FieldTypeScopeDescription
statusstringALLAlways "success" on a valid response
ipstringALLIPv4 address of the request (null if IPv6)
ipv6stringALLIPv6 address of the request (null if IPv4)
citystringGEO+City name
regionstringGEO+Region / state name
region_codestringGEO+ISO 3166-2 subdivision code (e.g. "NH", "34")
countrystringGEO+ISO 3166-1 alpha-2 country code (e.g. "NL")
country_namestringGEO+Full country name in English (e.g. "Netherlands")
continentstringGEO+Two-letter continent code (e.g. "EU")
latitudenumberGEO+Latitude (decimal degrees)
longitudenumberGEO+Longitude (decimal degrees)
timezonestringGEO+IANA timezone identifier (e.g. "Europe/Amsterdam")
timezone_offsetnumberGEO+UTC offset in seconds (e.g. 7200 = UTC+2)
postal_codestringGEO+Postal / ZIP code
asnnumberGEO+Autonomous System Number
orgstringGEO+AS organisation name (ISP)
asstringGEO+Formatted AS string (e.g. "AS1101 SURF B.V.")
is_eubooleanGEO+Whether the IP is located in the EU
currencystringGEO+ISO 4217 currency code for the country (e.g. "EUR")
http_protocolstringFULLHTTP protocol version (e.g. "HTTP/3", "HTTP/2")
tls_versionstringFULLTLS version (e.g. "TLSv1.3")
tls_cipherstringFULLTLS cipher suite
rttnumberFULLRound-trip time from client to Cloudflare edge (ms)
colostringFULLCloudflare datacenter IATA code that handled the request
proxybooleanFULLWhether the ASN is a known VPN or proxy provider
hostingbooleanFULLWhether the ASN is a known hosting or cloud provider

Error reference

StatusErrorMeaning
401missing_api_keyNo API key was provided in the request
401invalid_api_keyThe key does not exist or was deleted
403inactive_api_keyThe key exists but has been deactivated
429rate_limit_exceededDaily quota (10,000 req/day) reached, or burst limit (300 req/min) exceeded β€” burst pauses the key until you resume it
500internal_errorUnexpected server error β€” please try again

Code examples

curl https://whatsmy.fyi/api/v1/ip \
  -H "Authorization: Bearer wmf_your_api_key"

Rate limits

Two limits apply to every API key:

  • Daily quota β€” 10,000 requests per day on the free tier. The counter resets at midnight UTC.
  • Burst limit β€” 300 requests per minute per key. This protects against runaway loops and applies to all keys, including enterprise.

Rate limit status is returned on every response via headers:

X-RateLimit-Limit: 10000
X-RateLimit-Remaining: 9987
X-RateLimit-Reset: 1749081600  # Unix timestamp of next reset

When the daily quota is exceeded, the API returns a 429 response and requests resume automatically at midnight UTC:

{
  "error": "rate_limit_exceeded",
  "message": "You have reached the free tier limit of 10,000 requests/day. Resets at midnight UTC.",
  "docs": "https://whatsmy.fyi/docs#rate-limits",
  "enterprise": "https://whatsmy.fyi/enterprise"
}

When the burst limit is exceeded, the key is automatically paused β€” exceeding 300 req/min almost always indicates a bug (an infinite loop, a missing cache). The 429 response includes Retry-After: 60, and you can review and resume the key from your dashboard with one click. Tip: cache responses on your side β€” a visitor's IP data rarely changes within a session.

Need more? Enterprise plan β†’

API Stability & Versioning

The /api/v1/ip endpoint follows a strict stability contract. Production integrations can rely on it long-term.

  • πŸ”’Breaking changes are never made to /api/v1/ β€” existing integrations keep working.
  • βž•New response fields may be added at any time (additive only β€” safe to ignore).
  • πŸ“£Deprecations are announced at least 6 months in advance via the changelog.
  • πŸ”’/api/v2/ will be introduced for any breaking change β€” /v1/ stays live in parallel.
  • πŸ“‹All changes are documented at whatsmy.fyi/changelog.

For enterprise SLA requirements β†’ Contact us

Official Node.js SDK

Install the official @whatsmyfyi/sdk package for TypeScript-first access with automatic retries and full type definitions.

npm install @whatsmyfyi/sdk
import { WhatsMyFyi } from '@whatsmyfyi/sdk'

const client = new WhatsMyFyi({ apiKey: 'wmf_your_api_key' })

// Full response
const data = await client.ip.lookup()
console.log(data.city)      // "Amsterdam"
console.log(data.country)   // "NL"

// Quick helpers
const ip  = await client.ip.address()   // "203.0.113.42"
const loc = await client.ip.location()  // { city, country, countryCode, lat, lng }
const org = await client.ip.org()       // { asn, name }
  • Keyless mode β€” new WhatsMyFyi() without a key still serves ip.address()
  • Zero dependencies β€” uses native fetch
  • Works in Node.js, Deno, Bun, and the browser
  • Auto-retry on 5xx with exponential backoff (max 3 attempts)
  • Typed WhatsMyFyiError with code, message, status
View on npm β€” @whatsmyfyi/sdkView on GitHub

OpenAPI Specification

The full OpenAPI 3.1 spec is available for import into Postman, Insomnia, or any compatible tool. In Postman, go to File β†’ Import β†’ Link and paste the URL below.

https://whatsmy.fyi/openapi.json
Download OpenAPI spec

Badge

Add a badge to your README or website to show that you use the whatsmy.fyi API.

Powered by whatsmy.fyi

HTML

<a href="https://whatsmy.fyi">
  <img src="https://whatsmy.fyi/api/badge" alt="Powered by whatsmy.fyi" height="40" />
</a>

Markdown (GitHub README)

[![Powered by whatsmy.fyi](https://whatsmy.fyi/api/badge)](https://whatsmy.fyi)

For light backgrounds, append ?theme=light:

Powered by whatsmy.fyi (light)
[![Powered by whatsmy.fyi](https://whatsmy.fyi/api/badge?theme=light)](https://whatsmy.fyi)

Try it live

Make a real API request right here β€” no account or API key needed. You'll see your own IP data returned directly from the Cloudflare edge.

Live demo β€” no API key needed

This returns your real IP data from the Cloudflare edge.

Hit "Send Request" to see your real IP data.

Get started

Create a free account to get your API key in under a minute.

Create a free account β†’