Show HN: IP Lookup API Company of Craft released an IP lookup API that returns a verdict of human, proxy, bot, ai_crawler, search_bot or spoofed_crawler for a visitor's IP and request headers, letting site operators verify whether traffic claiming to be Googlebot or GPTBot actually originates from the published IP ranges of Google, Bing, Apple, OpenAI, Anthropic and Perplexity. The API draws network and country data from Team Cymru's IP-to-ASN service and Tor exit nodes from the Tor Project list, stores no looked-up IPs, and allows 600 calls per minute per server or browser. A Netlify Edge Function example blocks requests flagged as spoofed_crawler with a 403 response. IP lookup See what a website can tell from an IP address: where it is, whose network it is on, and whether it looks like a VPN, a bot or an AI crawler. Questions How do I check if a request comes from a real Googlebot or GPTBot? Anyone can put Googlebot or GPTBot in a user agent. Google, Bing, Apple, OpenAI, Anthropic and Perplexity publish the IP ranges their crawlers use. A request is real when its IP is in those ranges. Call the API with the ip and ua of the request to check it. Can it tell if someone uses a VPN? Partly. Tor exit nodes are on a public list, so those are certain. VPNs and proxies mostly run on hosting networks like AWS, DigitalOcean, Hetzner or M247, so an IP from one of those is likely a VPN, a proxy or a server. A VPN on a home network looks like any home connection. Why is my location a different city? An IP address belongs to a network, not a house. The location is where your internet provider says that network is, which can be the nearest big city. Mobile networks and VPNs can show a city far away. Why is the city missing when I look up another IP? The city comes from the network your request arrives through, so it is only known for your own IP. For other IPs the country comes from the regional internet registry. Are the IPs I look up saved? No. Nothing is stored. Detect bots on your site Send the visitor's IP and a few request headers from your server to POST /api/ip-lookup . The answer has a verdict : human , proxy , bot , ai crawler , search bot or spoofed crawler , plus isBot , isAiCrawler and isProxy . Send only the headers below, not cookies. curl -X POST https://companyofcraft.com/api/ip-lookup \ -d '{"ip":"66.249.66.1","headers":{"user-agent":"Googlebot/2.1"}}' On Netlify, an Edge Function can check every request: js const HEADERS = "user-agent", "accept", "accept-language", "sec-ch-ua", "sec-fetch-mode" ; export default async request, context = { const headers = Object.fromEntries HEADERS.filter name = request.headers.has name .map name = name, request.headers.get name , ; const response = await fetch "https://companyofcraft.com/api/ip-lookup", { method: "POST", body: JSON.stringify { ip: context.ip, headers } , } ; const { verdict } = await response.json ; if verdict === "spoofed crawler" { return new Response "Forbidden", { status: 403 } ; } return context.next ; }; To check your own request, call GET /api/ip-lookup . Add ?ip= and &ua= to look up another IP. Each server or browser can make 600 calls a minute. How it works The network and its country come from the Team Cymru IP to ASN service https://www.team-cymru.com/ip-asn-mapping . Tor exit nodes come from the Tor Project list https://check.torproject.org/torbulkexitlist . Bots are matched by user agent and checked against the IP ranges each company publishes. The map uses Natural Earth https://www.naturalearthdata.com data. Company of Craft also builds stateofpixel https://stateofpixel.com , which catches UI regressions before they merge.