GeoIP Service is a Next.js application that analyzes both IP addresses and website targets through a single lookup flow. It combines geolocation, ISP enrichment, device and connection signals, website DNS/HTTP/TLS inspection, and interactive Swagger documentation.
- Overview
- Features
- Endpoints
- Getting Started
- Usage
- Response Notes
- Project Structure
- Development
- Troubleshooting
- License
The service supports two main analysis modes:
- IP lookup: analyzes the current client IP or a provided IPv4/IPv6 address.
- Website lookup: accepts a domain or full HTTP/HTTPS URL, then inspects DNS, redirects, HTTP response metadata, TLS certificate data, and basic SEO/security signals.
The web UI is designed for progressive disclosure. Summary cards surface the most important interpretation first, while deeper technical panels stay collapsed until needed.
- Unified target detection for IPs, domains, and full URLs
- Geographic location estimates with country, region, city, timezone, and coordinates
- ISP enrichment with ASN, organization, proxy, hosting, and mobile connection signals
- Device and browser parsing from request headers
- Risk scoring, suspicious header detection, and bot heuristics
- Optional Turso-backed persistence for target lookup history and latest resolved IP inventory
- In-memory rate limiting with
Retry-AfterandX-RateLimit-*headers for lookup and Swagger traffic - Website inspection for DNS, redirects, status codes, headers, TLS, robots.txt, sitemap.xml, and HTML metadata
- Interactive Swagger UI backed by a live OpenAPI spec
- JSON-first API responses that mirror what the UI renders
GET /api/lookupReturns analysis for the current client IP.GET /api/lookup?target={target}Accepts an IP address, domain, or full URL and auto-detects the appropriate analysis mode.GET /api/lookup/{target}Compatibility route for manual path-based targets.GET /api/swaggerReturns the OpenAPI JSON spec used by Swagger UI.GET /docsLoads the embedded Swagger UI page.
- Node.js 22 or newer
- npm 8 or newer
git clone https://github.com/aliyilmazco/geoip-service.git
cd geoip-service
npm installnpm run update-geocp .env.example .env.localRecommended defaults:
- Keep
TRUST_PROXY_HEADERS=falseduring local development unless you are behind a trusted reverse proxy. - Leave
GEOIP_DATA_PATHempty unless you need to force a custom GeoIP data directory. - Keep
ALLOW_INSECURE_IP_API=falseunless you explicitly want the optionalip-api.comISP enrichment fallback. - Set
PUBLIC_APP_URLandSUPPORT_EMAILso the generated OpenAPI document matches your deployment. - Set
TURSO_LOGGING_ENABLED=true,TURSO_DATABASE_URL, andTURSO_AUTH_TOKENif you want target lookups written to Turso.
npm run devThe app runs on http://localhost:3001.
- Open
http://localhost:3001. - Enter an IP address, domain, or full URL.
- Review the summary cards first.
- Expand the advanced panels if you need HTTP, TLS, request context, or connection detail.
Analyze the current client IP:
curl http://localhost:3001/api/lookupAnalyze a specific IP address:
curl "http://localhost:3001/api/lookup?target=8.8.8.8"Analyze a domain:
curl "http://localhost:3001/api/lookup?target=example.com"Analyze a full URL:
curl "http://localhost:3001/api/lookup?target=https://openai.com"Use the compatibility path route:
curl "http://localhost:3001/api/lookup/8.8.8.8"Fetch the OpenAPI spec:
curl http://localhost:3001/api/swaggerconst response = await fetch("/api/lookup?target=example.com");
const data = await response.json();
if (!response.ok) {
console.error(data.error);
} else {
console.log(data.lookupType, data.requestId, data);
}- Field names remain stable across UI and API usage.
- Responses now include stable
status,requestId, andtimestampfields. - Lookup responses include top-level
rateLimitmetadata, and public endpoints expose matchingX-RateLimit-*orRetry-Afterheaders. - Repeated requests can return
429 Too Many RequestswithRetry-Afterguidance. - Error responses always include a structured
details.codevalue. - Human-readable values such as
error,reason,recommendations, and risk labels are English. - Website lookups may return partial technical data even when a full fetch fails.
- When location data cannot be produced,
location.diagnosiscan explain whether the GeoIP database was unavailable, the IP had no GeoIP match, or ISP fallback was disabled/missed. - Local or private IP addresses can return limited location data while still exposing device, request, and risk signals.
- Bare
GET /api/lookupcurrent-IP requests are not persisted, but target-based lookups can be retained in Turso when logging is enabled. - Website probes reject loopback, private, link-local, and other non-public targets before DNS, HTTP, or TLS probing continues.
app/
api/lookup/ Query-based lookup endpoint (GET /api/lookup)
api/lookup/[...target]/ Path-based catch-all route (GET /api/lookup/{target})
api/swagger/ OpenAPI spec endpoint
docs/ Embedded Swagger UI page
page.tsx Main lookup interface
layout.tsx Root layout with metadata
globals.css Global styles and CSS custom properties
components/
geoip-result-view.tsx Result rendering and advanced technical panels
location-map-panel.tsx Map container with dynamic loading
location-map-canvas.tsx Leaflet-based interactive map
site-chrome.tsx Shared hero and footer UI
swagger-ui-embed.tsx Swagger UI React wrapper
lib/
geoip-safe.ts GeoIP database wrapper with fallback
ip-analysis.ts IP, device, risk, and network helpers
ip-lookup.ts Targeted IP lookup flow
logger.ts Event logging utility
lookup-dispatch.ts Route target dispatcher
lookup-log-store.ts Turso persistence layer
lookup-response.ts Structured response builders
lookup-target.ts Target classification and normalization
lookup-types.ts TypeScript type definitions
network-policy.ts IP scope and hostname policy checks
request-utils.ts Request context and client IP utilities
runtime-config.ts Environment variable parsing with defaults
security.ts Rate limiting, URL validation, sanitization
swagger.ts OpenAPI schema definition
ttl-cache.ts In-memory TTL cache
turso.ts Turso database client
website-analysis.ts Website DNS, HTTP, TLS probing
scripts/
dev-preflight.js Pre-dev port conflict detection
clean-next.js Build artifact cleanup
port-guard.js Port availability checker
tests/
routes.test.ts API route integration tests
lookup-target.test.ts Target classification tests
security.test.ts Rate limiting and security tests
lookup-persistence.test.ts Turso persistence tests
public/
brand/ Logo and brand assets
sw.js Cleanup service worker
npm run devstarts the development server on port3001using.next-devnpm run dev:cleanclears both.next-devand.nextbefore startingnpm run buildcreates a production buildnpm run startstarts the production server on port3001npm run lintruns Next.js lintingnpm testruns the Node.js test suite with TypeScript strippingnpm run update-georefreshes thegeoip-litedata
After starting the app locally:
- Home page:
http://localhost:3001 - Swagger UI:
http://localhost:3001/docs - OpenAPI JSON:
http://localhost:3001/api/swagger
- Check whether the IP is private or local.
- Try a public IP address such as
8.8.8.8. - Refresh the GeoIP dataset with
npm run update-geo.
- Verify that the target domain resolves publicly.
- Confirm the site is reachable over HTTP or HTTPS.
- Retry with a full URL if the domain redirects in a non-standard way.
- Loopback, private, link-local, and internal targets are rejected by design.
- Make sure port
3001is available. - Reinstall dependencies with
npm installif the lockfile changed. - Stop any older Next.js process before starting a new one on the same port.
- Run
npm run dev:cleanafter switching branches, afternpm run build, or after editing routes, layouts, or global CSS.
- This usually means a running dev server is reading stale server chunks.
- Development output now lives in
.next-dev, while production build output stays in.next. - Do not run
next devdirectly; usenpm run devornpm run dev:cleanso the guard scripts can stop port and chunk drift issues.
- Older browsers may still try to update a previously registered service worker.
- This project now serves a cleanup worker at
/sw.jsto clear stale caches and unregister that old worker. - After one refresh cycle, the repeated
sw.js404 log should disappear.
- The API can continue to respond even if
geoip-litecannot load its local database. - At runtime the service checks
GEOIP_DATA_PATH,GEODATADIR,node_modules/geoip-lite/data,public/data,.next/server/data, and.next-dev/server/datain that order. - Check that at least one of those directories contains the GeoIP
.datfiles, and refresh the package data withnpm run update-geoif needed. - If a lookup still returns no coordinates, inspect
location.diagnosisin the API response for the immediate cause.
npm testuses a small custom loader so Node can resolve the repo's@/import alias during the test run.- On newer Node versions you may still see experimental loader warnings; these warnings do not fail the suite.
This project is licensed under the MIT License. See LICENSE for details.


