A few months ago, I got tired of visiting IP lookup sites that were bloated with ads, required sign-ups, or gave vague answers about what an IP address actually reveals.
So I built my own: IPCheck.app - a single-page tool that shows your public IPv4/IPv6, ISP, approximate location, and includes a few extra network utilities.
This post isn't a sales pitch. It's an honest breakdown of what I built, the technical decisions I made, and the parts that were harder than I expected.
The Stack (Spoiler: No Framework)
I made a deliberate choice to avoid React, Vue, or any build tools. Why?
First, hosting simplicity. The site is a single index.html file. No build step, no npm install, no CI/CD.
Second, load speed. No framework overhead means the page renders almost instantly, even on slow connections.
Third, longevity. Vanilla JS from 2024 will still work in 2034. A React app from 2019 might not.
External dependencies are minimal and loaded from CDNs. Leaflet.js for the interactive map. Font Awesome for icons. Inter font from Google Fonts.
That's it. Everything else is hand-written.
The IP Detection Logic
This was trickier than I expected. Here's the core problem: you cannot get your own public IP address from JavaScript alone. The browser doesn't expose it. You have to ask an external server.
I ended up using three endpoints to handle edge cases. ipapi.co for primary geolocation. ipwho.is as a fallback. And two ipify endpoints for separate IPv4 and IPv6 detection.
The IPv6 Problem
Here's something most tutorials don't tell you: api.ipify.org and api64.ipify.org behave differently.
api.ipify.org resolves to an IPv4-only endpoint. It will never return IPv6.
api64.ipify.org returns IPv6 if your network supports it, otherwise falls back to IPv4.
So to detect both addresses on a dual-stack connection, you need both endpoints. I learned this the hard way when my IPv6 address field kept showing the same IPv4 from the main API.
The Map: Approximate, Not Exact
The map uses Leaflet with CARTO tiles. It plots a marker at the coordinates returned by the IP API.
But here's the thing I had to be careful about: IP geolocation is not GPS. The coordinates might point to a data center 200 km away, or to your ISP's regional office. Mobile and VPN connections can be off by hundreds of kilometers.
So I made two deliberate choices.
First, I added a circle with a 25 km radius around the marker as a visual cue that the location is approximate.
Second, I wrote the disclaimer directly into the popup, so no way to miss it.
It's not just honest, it's better UX. Users who understand the limitation don't get frustrated when the map isn't precise.
The Speed Test (Cloudflare Endpoints)
This one surprised me. Cloudflare exposes public test endpoints that anyone can hit. I use these to measure download, upload, and latency, with no API key required.
For latency, I send 5 small requests and take the median, not the average, because one slow request shouldn't ruin the whole result.
The Password Breach Checker (k-Anonymity)
This is the tool I'm most proud of, because it's a beautiful example of privacy-preserving design.
Here's how it works. The user types a password. I hash it with SHA-1 in the browser using the Web Crypto API. I take the first 5 characters of the hash and send only those to the Have I Been Pwned API. The API returns hundreds of hash suffixes that share the same prefix. Then I check locally if the user's full hash is in that list.
The password never leaves the browser. The server never sees the full hash.
If you're building anything that handles sensitive data, k-anonymity is a pattern worth learning.
Things That Were Harder Than Expected
First, Blogger's XML parser is not HTML.
I initially deployed to Blogger, thinking it would be easy. It wasn't. Blogger parses templates as strict XML, which means every meta tag must be self-closed. Every ampersand must be escaped as and-amp-semicolon, even in URLs. Named entities like copy-semicolon are not defined in XML, you must use numeric codes. And JavaScript must be wrapped in CDATA.
I spent three days debugging issues that a static HTML host would never have.
The lesson: if you're deploying a custom-built page, don't use a blogging platform. Use Netlify, Vercel, Cloudflare Pages, or just plain shared hosting. The technical debt isn't worth the free hosting.
Second, IP geolocation accuracy is unpredictable.
I tested the site from 4 different networks: home fiber, mobile 4G, corporate WiFi, and VPN. The results ranged from spot-on city to wrong country. Mobile networks were the worst. One 4G test showed my location 800 km away.
There's no fix for this. You have to design for inaccuracy, which is why I added the disclaimer, the circle on the map, and the approximate label everywhere.
Third, speed test results vary wildly.
The same 25 MB download can return 47 Mbps or 190 Mbps depending on time of day, Cloudflare edge server proximity, WiFi signal strength, and background processes.
I now label the results as approximate and warn users that the numbers aren't comparable to dedicated speed test services like Speedtest.net.
What I'd Do Differently
If I started over, I would skip Blogger entirely. A static HTML file on Netlify would have saved me a week.
I would add the geolocation disclaimer from day one. I added it after user confusion, and it should have been there from the start.
And I would test on mobile earlier. I built for desktop first, then had to rework the layout.
Try It, Tell Me What Breaks
The site is live at ipcheck.app. All four tools are free, no sign-up, no tracking beyond what's technically required.
If you find a bug, or if a tool doesn't work on your network, I'd love to hear about it. The best feedback I've gotten so far came from a comment saying your IPv6 detection is wrong on a dual-stack connection, which led me to rewrite the detection logic.
What's your experience with IP geolocation APIs? Have you found one that's more accurate than the others? I'm always looking for better data sources.
Building in public. If you're working on something similar, drop a link in the comments, I'd love to try it.
Top comments (0)