Recipe: Postal code → place lookup

Resolve a postal code to a city/state/coordinates. Reverse: find postal codes for a city.

Tools used: zippopotam.lookup_zipcode, zippopotam.lookup_city. Geocoding fallback: weather.get_weather (Open-Meteo geocoder).

Calls: 1.

Decision tree

QuestionTool
”What city is ZIP 90210?”lookup_zipcode({ country: "us", zipcode: "90210" })
”What’s the postal code for Beverly Hills, CA?”lookup_city({ country: "us", state: "ca", city: "beverly hills" })
”Coordinates for SW1A 1AA?”lookup_zipcode({ country: "gb", zipcode: "SW1A 1AA" })
Postal code in unsupported countryUse weather.get_weather({location: "...zipcode..., country"}) — Open-Meteo’s geocoder is broader

Country coverage

Zippopotam has good coverage for:

  • US, GB, CA, AU, DE, FR, NL, BE, ES, IT, JP, MX, BR
  • ~60 countries total

Spotty or no coverage for many other countries. Calls return {found: false, hint: ...} (cleanly handled — no crash) but the agent burns a call.

For countries outside this set, use Open-Meteo’s geocoder via the weather pack. It accepts city + country strings and returns coordinates with hierarchy (city, state/region, country).

The shapes of failure

// Wrong: zipcode that doesn't exist
zippopotam.lookup_zipcode({ country: "us", zipcode: "00000" })
// → {found: false, hint: "Postal code not found..."}

// Wrong: country not in zippopotam's index
zippopotam.lookup_zipcode({ country: "ke", zipcode: "00100" })  // Kenya
// → {found: false, hint: "...coverage varies by country..."}

Both return {found: false} instead of crashing — but you’ve still wasted a call. Pre-check coverage if you can.

Worked examples

US ZIP

zippopotam.lookup_zipcode({ country: "us", zipcode: "90210" })
// → {
//   post_code: "90210",
//   country: "United States",
//   country_abbreviation: "US",
//   found: true,
//   places: [{ name: "Beverly Hills", state: "California", state_abbreviation: "CA", lat: 34.0901, lon: -118.4065 }]
// }

UK postcode

zippopotam.lookup_zipcode({ country: "gb", zipcode: "SW1A 1AA" })
// → resolves to Westminster

Reverse: city → postal codes

zippopotam.lookup_city({ country: "us", state: "ca", city: "beverly hills" })
// → multiple postal codes for the city

Note: state is the abbreviation ("ca", not "California"). City name is case-insensitive; spaces become +.

Fallback: country not supported

// Skip zippopotam entirely. Use Open-Meteo's geocoder:
weather.get_weather({ location: "00100, Nairobi, Kenya" })
// → coordinates resolved by Open-Meteo's broader geocoder, plus current weather

If you only need coordinates (not weather), this is overkill but it works.

Pattern: validated lookup

async function resolvePostalCode(country, zipcode) {
  const result = await zippopotam.lookup_zipcode({ country, zipcode })
  if (result.found) return result.places[0]

  // Fallback: build a query string and let Open-Meteo geocode
  const fallback = await weather.get_weather({ location: `${zipcode}, ${country}` })
  if (fallback.location) {
    return {
      name: fallback.location.name,
      lat: fallback.location.latitude,
      lon: fallback.location.longitude,
    }
  }

  return null
}

Citation pattern

90210 resolves to Beverly Hills, CA (34.09°N, 118.41°W) per Zippopotam.

Caveats

  • Country code is ISO-3166-1 alpha-2, lowercase. "us" not "USA", "gb" not "UK".
  • State abbreviation, not full name. "ca" for California, "ny" for New York.
  • City names are case-insensitive but have to match. “St. Louis” might need to be “saint louis”; “New York” usually works as “new york” (often the API normalizes).
  • Postal code formats vary by country. US is 5 digits or 5+4. UK is alphanumeric with a space. Check the upstream Zippopotam docs for any country before relying on a specific format.
  • Multiple places per code. US ZIPs can map to multiple cities (e.g. boundary zips). Returns are an array — don’t assume .places[0] is canonical.

Last reviewed May 8, 2026