Adding a Provider
ipwhoami uses a provider pattern that makes adding new sources straightforward. Each provider is a single file that implements one method.
Provider Interface
Section titled “Provider Interface”Every provider exports an object with:
{ name: 'provider-name', // Used in CLI flag displayName: 'Provider Name', // Shown in output url: (ip) => '...', // API endpoint
async lookup(ip) { // Fetch data and return normalized result return { ip: '...', city: '...', region: '...', country: '...', org: '...', location: 'lat, lon', timezone: '...', }; },}Step-by-Step
Section titled “Step-by-Step”1. Create the provider file
Section titled “1. Create the provider file”Create src/providers/my-provider.js:
import { fetchJSON } from './base.js';
export const myProvider = { name: 'my-provider', displayName: 'myprovider.com', url: (ip) => `https://api.myprovider.com/${ip}`,
async lookup(ip) { const data = await fetchJSON(this.url(ip)); return { ip: data.ip, city: data.city, region: data.region, country: data.country, org: data.organization, location: data.lat && data.lng ? `${data.lat}, ${data.lng}` : undefined, timezone: data.timezone, }; },};The fetchJSON helper from base.js handles timeouts and error responses for you.
2. Register it
Section titled “2. Register it”Open src/providers/index.js and add your provider:
import { myProvider } from './my-provider.js';
const providers = new Map([ ['ipinfo', ipinfo], ['ipapi', ipapi], ['ip-api', ipApiCom], ['my-provider', myProvider], // Add this line]);3. Update config
Section titled “3. Update config”Add the name to PROVIDER_NAMES in src/config.js:
export const PROVIDER_NAMES = ['ipinfo', 'ipapi', 'ip-api', 'my-provider'];4. Test it
Section titled “4. Test it”node bin/ipwhoami.js -p my-provider 8.8.8.8That’s it. The new provider automatically works with compare mode, raw output, and all CLI flags.
Guidelines
Section titled “Guidelines”- Always return the normalized shape (all 7 fields). Use
undefinedfor unavailable fields. - Use
fetchJSON()frombase.js— it handles timeouts and HTTP errors. - Map provider-specific field names to the standard names (e.g.,
isp->org).