The postal field guide

ZIP code lookup API guide

Developers usually need one of two different things from a ZIP code API: a quick city and state for a five-digit code, or a verified, standardized delivery address with ZIP+4. The first can be served from a reference dataset; the second requires an address verification service. Choosing the right one avoids both unnecessary cost and false confidence.

Option 1: a postal reference dataset

For city, state, county association and an approximate coordinate, a downloadable dataset such as GeoNames postal codes (Creative Commons Attribution) is enough. Load it into your own database with the ZIP stored as a five-character string, and serve lookups from there. This site works the same way; see About our ZIP code data for the limits.

Option 2: an address verification API

To confirm that a street address exists, standardize it and return ZIP+4, use the USPS Addresses API, which requires registration and OAuth 2.0 credentials, or a commercial provider licensed to use USPS data. Keep the credentials on your server, never in browser code, and read the provider's permitted-use terms before caching results.

Design the response honestly

Return distinct outcomes rather than a single yes/no:

{ "status": "verified" | "candidates" | "no_match" | "unavailable",
  "zip5": "02108", "zip4": "1234",
  "candidates": [ ... ] }

A provider outage is “unavailable,” not “invalid address.” Never fabricate a ZIP+4 from geography or random digits, and show the standardized address to the user before accepting it.

Validation and normalization

  • Accept ^\d{5}(?:-\d{4})?$; strip spaces around the hyphen.
  • Preserve leading zeros end to end: database column type, JSON strings, CSV exports.
  • Trim and title-case city names for display, but match on normalized values.

Test with the ZIP code validator and sample real codes with the random ZIP code generator.

Performance, caching and privacy

ZIP-level results change slowly, so cache them for days. Address-level results should be cached only as the provider allows. Apply rate limits per client, and do not log full residential addresses by default. For bulk jobs, batch requests and process in the background rather than in the request path; the bulk lookup shows a browser-side example.