Postal Code Area Lookup for Agent Data Enrichment avatar

Postal Code Area Lookup for Agent Data Enrichment

Pricing

$0.10 / 1,000 postal areas

Go to Apify Store
Postal Code Area Lookup for Agent Data Enrichment

Postal Code Area Lookup for Agent Data Enrichment

Postal-area lookup from Zippopotam.us for country and postal-code pairs. Export attributed place names, state codes and approximate place centroids as JSON; does not validate street addresses.

Pricing

$0.10 / 1,000 postal areas

Rating

0.0

(0)

Developer

Grit

Grit

Maintained by Community

Actor stats

0

Bookmarked

2

Total users

1

Monthly active users

7 days ago

Last modified

Categories

Share

Enrich country/postal-code pairs with attributed postal place names, state codes and approximate place centroids from the anonymous Zippopotam.us API.

Use this actor for postal-area labels and coarse geographic enrichment. A postal code may map to several places: each source place becomes its own row. Postal codes stay strings, including leading zeros. This is separate from OSM place or business discovery and does not validate street addresses or delivery eligibility.

Input

The prefilled example is:

{
"lookups": [{"country": "US", "postalCode": "90210"}],
"maxItems": 1
}

For a mixed-country batch:

{
"lookups": [
{"country": "US", "postalCode": "01001"},
{"country": "DE", "postalCode": "01067"}
],
"maxItems": 20,
"concurrency": 3,
"maxRetries": 2,
"timeoutSecs": 15
}
InputMeaning
lookupsRequired array of 1–10,000 objects containing only country and postalCode.
countryTwo-letter country code. Outer whitespace is trimmed and country letters are uppercased. Actual coverage belongs to the source.
postalCodeRequired string of 1–20 letters, digits, spaces or hyphens. Outer whitespace is trimmed; leading zeros remain. Numbers are rejected.
maxItemsTotal output-row cap, including errors: 1–100,000, default 1,000. The Store prefill is 1.
concurrencySimultaneous lookups: 1–10, default 3.
maxRetriesExtra attempts for network errors, HTTP 429 or 5xx: 0–3, default 2.
timeoutSecsTimeout per HTTP operation: 1–60 seconds, default 15.

Street/address fields, residents, households, reverse-person searches, contact fields and POI/business queries are unsupported. Unknown input fields are rejected. Malformed pairs produce input_error rows; an invalid overall input fails the run with a clear message. lookupIndex identifies the original pair even when its values cannot be used.

Returned fields

FieldMeaning
countryCode, postalCodeNormalized input country and string postal code; null for an unusable input pair.
placeNamePostal place name reported by the source.
state, stateCodeSource state/region name and abbreviation; null when unavailable.
latitude, longitudeNumeric approximate place centroid, or both null if the source pair is unusable. These are not rooftop coordinates or postal boundaries.
coordinateAccuracyapproximate_place_centroid or unavailable.
coordinateWarningsReasons source coordinates were omitted.
lookupIndexZero-based input index. Duplicate pairs remain separate inputs.
matchIndexZero-based source place index; null for a lookup-level error.
matchedPlaceCountNumber of source places before the output cap.
matchesTruncatedTrue when the cap or charge budget omitted places from this lookup.
statusok, coverage_missing, input_error or source_error.
errorCode, errorMachine-readable error category and explanatory text; null on success.
httpStatusSource HTTP status, or null if no response/request was available.
source, sourceUrlZippopotam.us and the exact country/postal-code API URL.
sourceAttribution, sourceLicenseUrlAttribution to Zippopotam.us/GeoNames and source database license link.
retrievedAtUTC timestamp for the lookup result.

SUMMARY in the default key-value store records row totals and whether the run stopped at the output cap, charge limit or end of input. The default dataset is available through the actor's Results output link and Apify dataset export.

Real output example

This row comes from the local run saved in sample_output.json:

{
"lookupIndex": 0,
"countryCode": "US",
"postalCode": "90210",
"placeName": "Beverly Hills",
"state": "California",
"stateCode": "CA",
"latitude": 34.0901,
"longitude": -118.4065,
"coordinateAccuracy": "approximate_place_centroid",
"coordinateWarnings": [],
"matchIndex": 0,
"matchedPlaceCount": 1,
"matchesTruncated": false,
"status": "ok",
"errorCode": null,
"error": null,
"httpStatus": 200,
"source": "Zippopotam.us",
"sourceUrl": "https://api.zippopotam.us/us/90210",
"sourceAttribution": "Zippopotam.us; postal reference data from GeoNames (https://www.geonames.org/).",
"sourceLicenseUrl": "https://opendatacommons.org/licenses/odbl/1-0/",
"retrievedAt": "2026-10-06T09:08:17.749118+00:00"
}

Pricing proposal

The proposed postal_area event is $0.0001 per delivered ok place row, or $0.10 for 1,000 successful rows. A code with three saved places incurs three events. A successful postal place with unavailable coordinates is still billed because its place/state data was returned. Coverage gaps, invalid inputs, source errors and discarded rows do not incur this event. Duplicate successful inputs incur their own events.

See PRICING.md for the current Store comparison, the free competitor caveat and the proposed event configuration. This local build does not activate Store pricing. Apify's separate platform costs or automatic start events depend on the final account configuration.

Limits and source quality

  • The actor requests only https://api.zippopotam.us/{country}/{postalCode} without login, API key, proxy, reverse search or additional enrichment sources.
  • HTTP 404 means missing source coverage. It does not establish that a delivery address or postal code is invalid.
  • Raise maxItems to preserve all source matches. Truncation is explicit. Input order and source place order are retained; a small batch may already be in flight when the row cap is reached.
  • Retry waits grow as 1, 2, then 4 seconds. Retry-After can extend a wait to a maximum of 30 seconds. Other HTTP errors and malformed responses become item-level errors.
  • Missing, nonnumeric, nonfinite or out-of-range coordinate pairs become null with a warning. Values within the numeric ranges can still be wrong; the actor cannot independently certify source accuracy. No guessed correction is made.
  • In the captured DE/01067 response, all three places had source latitude 14612; their names were preserved and both coordinates were omitted. This case is included in the real response fixtures and sample.
  • Coverage and precision vary by country. Some countries expose postal prefixes or incomplete datasets. Consult the source coverage notes and endpoint documentation.
  • Zippopotam.us is a public third-party service with data supplied as-is. Keep concurrency low; availability and source changes can affect runs.

Attribution

Data is supplied by Zippopotam.us, derived from GeoNames. The Zippopotam.us source page identifies the Open Database License and Database Contents License. Attribution and a source-license link accompany each row; retain them when reusing or exporting data. Source terms apply to derived data.

FAQ

Can this verify an address for shipping? No. It provides a postal-area reference match, not a delivery-address verdict.

Why does my country or full postal code return no match? The public source may not cover it or may expose only a prefix. A 404 is saved as coverage_missing; no alternate source is queried.

Why are there multiple rows for one code? The source can associate a code with several places. Join on lookupIndex and retain matchIndex rather than silently picking a single city.

Why are coordinates missing on an ok row? A usable place name was returned, but the source coordinate pair failed numeric/range checks. Read coordinateWarnings.

Are repeated pairs deduplicated? No. Each input retains its own index and successful output events.

Use with AI agents / MCP

For an Apify-connected agent or MCP client, supply the JSON input above to this actor and read the Results dataset. Keep postalCode a JSON string. Handle coverage_missing as an unknown coverage state, retain all place matches, and check coordinateAccuracy before using coordinates. maxItems is an output-row budget, so choose a larger value than the pair count when several places may match. This actor does not implement its own MCP server; the connection is provided by the client's Apify integration.

Local development

Use the existing virtual environment; do not install packages into it:

& C:/GritWork/earn/.venv/Scripts/python.exe evidence/run_tests.py
& C:/GritWork/earn/.venv/Scripts/python.exe evidence/run_tests.py live
apify validate-schema

Put the JSON input in storage/key_value_stores/default/INPUT.json, then run:

$env:APIFY_LOCAL_STORAGE_DIR = "$PWD/storage"
& C:/GritWork/earn/.venv/Scripts/python.exe -m src

The scripts in evidence/ retain the exact local-run commands, build digests, observations and test results. Real response fixtures and their capture metadata are under tests/fixtures/. Cloud builds and real billing require a separate owner-run publication/configuration step.