Skip to content

US ZIP ​

@eusilvio/zip-lookup applies the same architecture to US postal codes: provider racing, circuit breaker, cache with stale-if-error, rate limiting, events and metrics.

bash
npm install @eusilvio/zip-lookup

Usage ​

ts
import { ZipLookup } from "@eusilvio/zip-lookup";
import { zippopotamProvider, zippopotamPlusProvider } from "@eusilvio/zip-lookup/providers";

const zip = new ZipLookup({
  providers: [zippopotamProvider, zippopotamPlusProvider],
  circuitBreaker: { enabled: true, failureThreshold: 3, cooldownMs: 30_000 },
  retries: 1,
});

const address = await zip.lookup("90210");
// {
//   zip: '90210',
//   city: 'Beverly Hills',
//   state: 'California',
//   stateAbbr: 'CA',
//   country: 'United States',
//   latitude: '34.0901',
//   longitude: '-118.4065',
//   service: 'Zippopotam'
// }

ZipAddress ​

ts
interface ZipAddress {
  zip: string;
  city: string;
  state: string;      // full name
  stateAbbr: string;  // 2-letter abbreviation
  county?: string;
  country: string;
  latitude?: string;
  longitude?: string;
  timezone?: string;
  service: string;
}

Providers ​

ts
import {
  zippopotamProvider,
  zippopotamPlusProvider,
  createZipcodestackProvider,
  createUspsProvider,
} from "@eusilvio/zip-lookup/providers";
ProviderAPI keyNote
zippopotamProvidernofree, no signup
zippopotamPlusProvidernovariant with extra place data
createZipcodestackProvider(apiKey)yesfactory: pass the key
createUspsProvider(apiKey)yesofficial USPS API
ts
const zip = new ZipLookup({
  providers: [
    zippopotamProvider,
    createZipcodestackProvider(process.env.ZIPCODESTACK_KEY!),
  ],
});

ZipProvider accepts a per-provider fetcher - useful when an API speaks XML instead of JSON, like the USPS one:

ts
const provider: ZipProvider = {
  name: "MyAPI",
  buildUrl: (zip) => `https://api.example.com/zip/${zip}`,
  transform: (raw) => ({ /* ... */ }),
  fetcher: async (url, signal) => parseXml(await (await fetch(url, { signal })).text()),
};

Differences from cep-lookup ​

cep-lookupzip-lookup
ClassCepLookupZipLookup
ResultAddressZipAddress
Not-found errorCepNotFoundErrorZipNotFoundError
Offline fallbackyes (Correios map)no
Reverse searchyes (ViaCEP)no
Persistent cache adaptersyesInMemoryCache only
Per-provider fetcherno (global only)yes
Eventsincludes offline:fallbacksuccess, failure, cache:hit, cache:stale

Everything else - staleIfError, negativeCacheTtl, coalescing, warmup(), getProviderHealth(), getProviderMetrics(), rate limiting with strategy - behaves identically. See Resilience and Observability.

Errors ​

ts
import {
  ZipValidationError,      // INVALID_ZIP
  ZipNotFoundError,        // NOT_FOUND
  ProviderTimeoutError,    // TIMEOUT
  RateLimitError,          // RATE_LIMITED
  AllProvidersFailedError, // ALL_PROVIDERS_FAILED
  ProviderUnavailableError,// PROVIDER_UNAVAILABLE
} from "@eusilvio/zip-lookup";

Released under the MIT License.