npm package discovery and stats viewer.

Discover Tips

  • General search

    [free text search, go nuts!]

  • Package details

    pkg:[package-name]

  • User packages

    @[username]

Sponsor

Optimize Toolset

I’ve always been into building performant and accessible sites, but lately I’ve been taking it extremely seriously. So much so that I’ve been building a tool to help me optimize and monitor the sites that I build to make sure that I’m making an attempt to offer the best experience to those who visit them. If you’re into performant, accessible and SEO friendly sites, you might like it too! You can check it out at Optimize Toolset.

About

Hi, 👋, I’m Ryan Hefner  and I built this site for me, and you! The goal of this site was to provide an easy way for me to check the stats on my npm packages, both for prioritizing issues and updates, and to give me a little kick in the pants to keep up on stuff.

As I was building it, I realized that I was actually using the tool to build the tool, and figured I might as well put this out there and hopefully others will find it to be a fast and useful way to search and browse npm packages as I have.

If you’re interested in other things I’m working on, follow me on Twitter or check out the open source projects I’ve been publishing on GitHub.

I am also working on a Twitter bot for this site to tweet the most popular, newest, random packages from npm. Please follow that account now and it will start sending out packages soon–ish.

Open Software & Tools

This site wouldn’t be possible without the immense generosity and tireless efforts from the people who make contributions to the world and share their work via open source initiatives. Thank you 🙏

© 2026 – Pkg Stats / Ryan Hefner

@actovision/nodejs-ip-api

v1.0.0

Published

A lightweight Node.js wrapper for IP-API.com IP geolocation service

Readme

@actovision/nodejs-ip-api

A lightweight Node.js wrapper for the IP-API.com IP geolocation service. Get location, network, and other information about IP addresses with a simple TypeScript/JavaScript API.

Features

  • 🚀 Simple and lightweight - minimal dependencies
  • 💪 TypeScript support with full type definitions
  • 🔄 Support for both free and pro IP-API.com tiers
  • 🎯 Flexible field selection to optimize API usage
  • ✅ Built-in validation for IP addresses (IPv4 and IPv6)
  • ⚡ Promise-based async/await API
  • 🛡️ Comprehensive error handling
  • 💾 Optional caching with configurable TTL
  • 🚦 Built-in rate limiting to respect API limits

Installation

npm install @actovision/nodejs-ip-api

or

yarn add @actovision/nodejs-ip-api

Quick Start

import { IPApiService, IPAPIField } from '@actovision/nodejs-ip-api';

// Create service instance
const ipApi = new IPApiService();

// Lookup an IP address
async function lookupIP() {
  try {
    const result = await ipApi.get({ ip: '8.8.8.8' });
    console.log(result);
    // {
    //   status: 'success',
    //   country: 'United States',
    //   countryCode: 'US',
    //   city: 'Mountain View',
    //   lat: 37.386,
    //   lon: -122.0838,
    //   timezone: 'America/Los_Angeles',
    //   isp: 'Google LLC',
    //   ...
    // }
  } catch (error) {
    console.error('Error:', error.message);
  }
}

lookupIP();

Usage

Basic Usage

import { IPApiService } from '@actovision/nodejs-ip-api';

const ipApi = new IPApiService();

// Get geolocation data with default fields
const data = await ipApi.get({ ip: '1.1.1.1' });

With API Key (Pro Tier)

For production use, it's recommended to use an API key to access the pro tier with HTTPS and higher rate limits.

import { IPApiService } from '@actovision/nodejs-ip-api';

// Pass API key in constructor
const ipApi = new IPApiService({ 
  apiKey: 'your-api-key-here' 
});

// Or use environment variable
// IP_API_KEY=your-api-key-here
const ipApi = new IPApiService();

Custom Field Selection

Request only specific fields to reduce bandwidth and improve performance:

import { IPApiService, IPAPIField } from '@actovision/nodejs-ip-api';

const ipApi = new IPApiService();

const data = await ipApi.get({
  ip: '8.8.8.8',
  fields: [
    IPAPIField.COUNTRY,
    IPAPIField.CITY,
    IPAPIField.LAT,
    IPAPIField.LON,
    IPAPIField.ISP
  ]
});

Custom Timeout

const ipApi = new IPApiService({
  timeout: 10000 // 10 seconds
});

With Caching

Enable caching to reduce API calls for repeated lookups:

import { IPApiService } from '@actovision/nodejs-ip-api';

const ipApi = new IPApiService({
  enableCache: true,
  cacheTTL: 60 * 60 * 1000 // Cache for 1 hour
});

// First call hits the API
const result1 = await ipApi.get({ ip: '8.8.8.8' });

// Second call uses cached data
const result2 = await ipApi.get({ ip: '8.8.8.8' });

// Check cache stats
const stats = ipApi.getCacheStats();
console.log(`Cached entries: ${stats?.size}`);

// Clear cache if needed
ipApi.clearCache();

With Rate Limiting

Automatically respect API rate limits:

import { IPApiService } from '@actovision/nodejs-ip-api';

const ipApi = new IPApiService({
  enableRateLimiting: true,
  rateLimitPerMinute: 45 // Free tier: 45 requests/minute
});

// Automatically waits if rate limit is reached
for (const ip of ipList) {
  const result = await ipApi.get({ ip });
  
  // Check remaining quota
  const status = ipApi.getRateLimitStatus();
  console.log(`Remaining: ${status?.remaining}/${status?.limit}`);
}

Standalone Cache Usage

import { IPCache } from '@actovision/nodejs-ip-api';

const cache = new IPCache(24 * 60 * 60 * 1000); // 24 hour TTL

// Store data
cache.set('8.8.8.8', responseData);

// Retrieve data
const cached = cache.get('8.8.8.8');

// Check if cached
if (cache.has('8.8.8.8')) {
  console.log('Data is cached');
}

// Get cache statistics
const stats = cache.stats();
console.log(`Size: ${stats.size}, Expired: ${stats.expired}`);

Standalone Rate Limiter Usage

import { RateLimiter } from '@actovision/nodejs-ip-api';

// Create for free tier (45 req/min)
const limiter = RateLimiter.forFreeTier();

// Or create for pro tier
const proLimiter = RateLimiter.forProTier(300);

// Check if request is allowed
if (limiter.canMakeRequest()) {
  limiter.recordRequest();
  // Make API call
}

// Or use tryAcquire (atomic check + record)
if (limiter.tryAcquire()) {
  // Make API call
}

// Or wait for next available slot
await limiter.waitAndAcquire();
// Make API call

// Get status
const status = limiter.getStatus();
console.log(`${status.remaining}/${status.limit} remaining`);
console.log(`Wait time: ${status.waitTime}ms`);

Error Handling

import { IPApiService, IPAPIError } from '@actovision/nodejs-ip-api';

const ipApi = new IPApiService();

try {
  const data = await ipApi.get({ ip: '8.8.8.8' });
  console.log(data);
} catch (error) {
  if (error instanceof IPAPIError) {
    console.error('IP-API Error:', error.message);
    console.error('Status Code:', error.statusCode);
    console.error('Response:', error.response);
  } else {
    console.error('Unexpected error:', error);
  }
}

API Reference

IPApiService

Main service class for interacting with IP-API.com.

Constructor

constructor(config?: IPAPIConfig)

Parameters:

  • config.apiKey (optional): API key for pro tier access
  • config.timeout (optional): Request timeout in milliseconds (default: 5000)

Methods

get(query: IPAPIQuery): Promise<IPAPIResponse>

Retrieves geolocation data for the specified IP address.

Parameters:

  • query.ip (required): IP address to lookup (IPv4 or IPv6)
  • query.fields (optional): Array of fields to include in response

Returns: Promise resolving to IPAPIResponse

Throws: IPAPIError if the request fails or validation errors occur

setApiKey(apiKey: string): void

Updates the API key for this service instance.

hasApiKey(): boolean

Returns true if an API key is configured, false otherwise.

clearCache(): void

Clears all cached entries (only available when caching is enabled).

getCacheStats(): { size: number; expired: number } | undefined

Returns cache statistics or undefined if caching is disabled.

getRateLimitStatus(): { remaining: number; limit: number; resetAt: number; waitTime: number } | undefined

Returns rate limiter status or undefined if rate limiting is disabled.

resetRateLimiter(): void

Resets the rate limiter (only available when rate limiting is enabled).

Available Fields

The IPAPIField enum includes all available fields:

enum IPAPIField {
  STATUS = 'status',
  MESSAGE = 'message',
  CONTINENT = 'continent',
  CONTINENT_CODE = 'continentCode',
  COUNTRY = 'country',
  COUNTRY_CODE = 'countryCode',
  REGION = 'region',
  REGION_NAME = 'regionName',
  CITY = 'city',
  DISTRICT = 'district',
  ZIP = 'zip',
  LAT = 'lat',
  LON = 'lon',
  TIMEZONE = 'timezone',
  OFFSET = 'offset',
  CURRENCY = 'currency',
  ISP = 'isp',
  ORG = 'org',
  AS = 'as',
  ASNAME = 'asname',
  REVERSE = 'reverse',
  MOBILE = 'mobile',
  PROXY = 'proxy',
  HOSTING = 'hosting',
  QUERY = 'query'
}

Default Fields

If no fields are specified, the following default fields are returned:

  • status, query
  • country, countryCode, continent, continentCode
  • region, regionName, city, zip
  • lat, lon, timezone
  • isp, org, as

Rate Limiting

Free Tier

  • Rate limit: 45 requests per minute
  • Protocol: HTTP only
  • No API key required

Pro Tier

  • Rate limit: Higher limits (varies by plan)
  • Protocol: HTTPS
  • API key required

Sign up for a pro account at IP-API.com for production use.

Examples

Get Location of Multiple IPs

import { IPApiService } from '@actovision/nodejs-ip-api';

const ipApi = new IPApiService();
const ips = ['8.8.8.8', '1.1.1.1', '208.67.222.222'];

async function lookupMultiple() {
  for (const ip of ips) {
    const result = await ipApi.get({ ip });
    console.log(`${ip}: ${result.city}, ${result.country}`);
    
    // Add delay to respect rate limits (free tier: 45/min)
    await new Promise(resolve => setTimeout(resolve, 2000));
  }
}

lookupMultiple();

Check if IP is a Proxy

import { IPApiService, IPAPIField } from '@actovision/nodejs-ip-api';

const ipApi = new IPApiService();

const result = await ipApi.get({
  ip: '1.2.3.4',
  fields: [
    IPAPIField.QUERY,
    IPAPIField.PROXY,
    IPAPIField.HOSTING,
    IPAPIField.MOBILE
  ]
});

if (result.proxy) {
  console.log('This IP is likely a proxy');
}

License

MIT

Contributing

Contributions are welcome! Please feel free to submit a Pull Request.

Support

For issues and questions:

  • GitHub Issues: https://github.com/Actovision-ORG/nodejs-ip-api/issues
  • IP-API.com Documentation: https://ip-api.com/docs

Credits

This package is a wrapper for the excellent IP-API.com service.