Fuses IP intelligence, reverse geocoding, and radio/Wi-Fi triangulation into a single, real-time, precision-crafted API. Trace a single packet’s origin, map a million connections, or power real-time location-aware apps with elegance, accuracy, and streami
npm install @trap_stevo/geotideipwhois, ipapi, ipinfo, ipgeolocation) with scoring and failover
lookup(ip) | lookup(ip: string) | Promise | Resolves a public IP into normalized location metadata. Uses provider race + scoring + TTL cache. | Yes |
lookupMany(ips, opts?) | lookupMany(ips: string[], opts?: { concurrency?: number }) | Promise<(GeoResult \| null)[]> | Batch IP lookup with bounded concurrency (default = maxConcurrency). | Yes |
reverse(lat, lon, opts?) | reverse(lat: number, lon: number, opts?: { deadlineMs?: number, cacheTtlMs?: number }) | Promise | Reverse-geocodes coordinates to a human address by racing Mapbox/Google/Nominatim with caching. | Yes |
getClientIP(req) | getClientIP(req: IncomingMessage \| Express.Request) | string \| null | Extracts the client's IP from HTTP request headers and connection info, supporting proxies and IPv6 normalization. | No |
on(event, handler) | on(event: GeoTideEvent, handler: (payload: any) => void) | this | Subscribe to real-time events (telemetry, results, cache hits, health). | No |
off(event, handler) | off(event: GeoTideEvent, handler: Function) | this | Unsubscribe a previously registered listener. | No |
ts
type GeoResult = {
source: string; // provider name
ip: string;
city: string | null;
region: string | null;
country: string | null;
org: string | null;
isp: string | null;
loc: string | null; // "lat,lon"
timezone: string | null;
postal: string | null;
flag: string | null; // emoji when available
continent: string | null;
confidence: number; // 0..1
};
type ReverseResult = {
provider: string; // provider name
formatted: string;
components: any;
lat: number;
lon: number;
};
`
---
$3
| Event | Payload | Description |
|---|---|---|
| lookup:start | { ip } | A lookup has started. |
| lookup:cache_hit | { ip, result } | Result served from cache. |
| lookup:result | { ip, result } | Fresh lookup result returned. |
| provider:success | { provider, ip, durationMs, score } | A provider returned data successfully. |
| provider:fail | { provider, ip, error } | A provider failed. |
| provider:unhealthy | { provider, reason } | Provider marked temporarily unhealthy. |
| reverse:start | { lat, lon } | Reverse geocoding started. |
| reverse:cache_hit | { lat, lon, result } | Reverse geocoding served from cache. |
| reverse:result | { lat, lon, result } | Fresh reverse geocoding result returned. |
---
📦 Installation
`bash
npm install @trap_stevo/geotide
`
---
🛠️ Usage
$3
`js
const GeoTide = require("@trap_stevo/geotide");
const geo = new GeoTide({ enableGeoDebug : true });
const result = await geo.lookup("203.0.113.42");
console.log(result);
// {
// source: 'ipwhois',
// ip: '203.0.113.42',
// city: 'Sample City',
// region: 'Sample Region',
// country: 'Sample Country',
// org: 'Sample ISP Org',
// isp: 'Sample ISP',
// loc: '37.4221,-122.0841',
// timezone: 'America/Los_Angeles',
// postal: '94043',
// flag: '🌍',
// continent: 'North America',
// confidence: 1
// }
`
---
$3
`js
const results = await geo.lookupMany([
"203.0.113.42",
"8.8.8.8"
]);
console.log(results);
`
---
$3
`js
const address = await geo.reverse(40.712776, -74.005974);
console.log(address.formatted);
// "Example Building, 123 Example Street, Sample City, NY, United States"
`
---
$3
`js
geo.on("lookup:result", ({ ip, result }) => {
console.log([GeoTide] ${ip} → ${result.city}, ${result.country});
});
``