# ZIP Code Lookup (`maximedupre/zip-code-lookup`) Actor

Look up ZIP and postal codes in bulk across selected countries, or find postal codes from a city and state or province. Get structured country, place, region, and coordinate data without a source API key.

- **URL**: https://apify.com/maximedupre/zip-code-lookup.md
- **Developed by:** [Maxime Dupré](https://apify.com/maximedupre) (community)
- **Categories:** Developer tools, Business, Automation
- **Stats:** 2 total users, 1 monthly users, 100.0% runs succeeded, 0 bookmarks
- **User rating**: No ratings yet

## Pricing

$0.35 / 1,000 postal codes

This Actor is paid per event. You are not charged for the Apify platform usage, but only a fixed price for specific events.

Learn more: https://docs.apify.com/platform/actors/running/actors-in-store#pay-per-event

## What's an Apify Actor?

Actors are web data automations that power AI and operations. They run on the Apify platform to scrape websites, process data, connect APIs, and automate workflows.
In Batch mode, an Actor accepts a well-defined JSON input, performs an action which can take anything from a few seconds to a few hours,
and optionally produces a well-defined JSON output, datasets with results, or files in key-value store.
In Standby mode, an Actor provides a web server which can be used as a website, API, or an MCP server.
Actors are written with capital "A".

## How to integrate an Actor?

If asked about integration, you help developers integrate Actors into their projects.
You adapt to their stack and deliver integrations that are safe, well-documented, and production-ready.
The best way to integrate Actors is as follows.

- **AI agents and MCP clients** — the [Apify MCP server](https://docs.apify.com/integrations/mcp.md) at `https://mcp.apify.com` (remote, streamable HTTP, OAuth on first use).
- **Agentic workflows and local Actor development** — [Agent Skills](https://apify.com/.well-known/agent-skills/index.json) with the [Apify CLI](https://docs.apify.com/cli/docs.md): `npm install -g apify-cli`, then `apify login`.
- **JavaScript/TypeScript projects** — the official [JS/TS client](https://docs.apify.com/api/client/js/docs.md): `npm install apify-client`.
- **Python projects** — the official [Python client](https://docs.apify.com/api/client/python/docs.md): `pip install apify-client`.
- **Any other language** — the [REST API](https://docs.apify.com/api/v2.md).

For usage examples, see the [API](#api) section below.

For more details, see Apify documentation as [Markdown index](https://docs.apify.com/llms.txt) and [Markdown full-text](https://docs.apify.com/llms-full.txt).

# README

### 📮 Look up ZIP and postal codes

Developers, data teams, and operations users can run a ZIP code lookup on one list and get structured postal identity, country, place, region, and available latitude/longitude data. Use the rows in location filters, country checks, and data cleanup workflows.

**Use cases**

- Check many countries in one run with **[International Postal Code Lookup](https://apify.com/maximedupre/zip-code-lookup/examples/international-postal-code-lookup)** and keep country-specific rows.
- Find a submitted ZIP value and its place details with **[Zip Code Finder](https://apify.com/maximedupre/zip-code-lookup/examples/zip-code-finder)**.
- Resolve postal values to structured country and region fields with **[Postal Code Lookup](https://apify.com/maximedupre/zip-code-lookup/examples/postal-code-lookup)**.
- Find postal codes from a city and state or province with **[Zip Code Lookup by City and State](https://apify.com/maximedupre/zip-code-lookup/examples/zip-code-lookup-by-city-and-state)**.
- Check a U.S. ZIP value and its returned place data with **[USPS Zip Code Lookup](https://apify.com/maximedupre/zip-code-lookup/examples/usps-zip-code-lookup)**.

#### 📦 Returned ZIP lookup rows

Each saved dataset row represents one lookup for one postal value and country code. A row can include the postal code, country, places, region, latitude, longitude, and a `found` flag. The same value checked for several country codes can produce separate rows. When a postal range is expanded, each expanded value is returned as its own lookup row.

#### ▶️ Run a ZIP code lookup

1. Choose **Postal code lookup** or **City and state reverse lookup**.
2. Add `postalCodes` and `countryCodes`, or add `city`, `region`, and `countryCodes` for reverse mode.
3. Choose the result detail, unmatched-value policy, sort field, and optional place limit.
4. Start the run and open the default dataset.

Use one lookup direction per run. Fields in the other Target Options section are ignored. If `maxPlacesPerCode` is empty, the Actor returns all available results until the source is exhausted.

#### ⚙️ Input

The public input uses JSON or the Apify form. `target` and `countryCodes` are required; the other fields depend on the lookup direction.

**Input fields**

| Field | Type | What it does |
| --- | --- | --- |
| `target` | string (required) | Choose `postalCodeLookup` for postal or ZIP values, or `cityStateLookup` for a reverse lookup. |
| `postalCodes` | array of strings | Add one or more exact postal or ZIP values or numeric ranges such as `00501-00503`. Leading zeros are kept. Used for postal lookup mode. |
| `postalCodes[]` | string | One exact postal or ZIP value or numeric range inside `postalCodes`. |
| `maxPlacesPerCode` | integer (optional) | Cap the place records returned for each postal code. Leave it empty to return all available results until the source is exhausted. |
| `city` | string (optional) | City to use for the reverse lookup. |
| `region` | string (optional) | State or province to use for the reverse lookup. |
| `countryCodes` | array of strings (required) | Add one or more ISO 3166-1 alpha-2 country codes. The same lookup values are checked for each code. |
| `countryCodes[]` | string | One ISO 3166-1 alpha-2 country code inside `countryCodes`. |
| `detailLevel` | string | Choose `postalCode`, `place`, or `full` to control how much detail each row keeps. |
| `notFoundPolicy` | string | Choose `omit` to leave out unmatched values or `keep` to save no-result records. |
| `sortBy` | string | Order returned rows by `postalCode`, `place`, `region`, `latitude`, or `longitude`. |

This is the public input from a successful current-beta default-input run:

```json
{
  "target": "postalCodeLookup",
  "postalCodes": [
    "10001"
  ],
  "countryCodes": [
    "US"
  ],
  "detailLevel": "full",
  "notFoundPolicy": "omit",
  "sortBy": "postalCode"
}
```

#### 🧾 Output

Postal lookup and city-and-state reverse lookup use the same dataset row shape. Optional fields can be absent when the selected detail level or source data does not provide them. With `notFoundPolicy` set to `keep`, an unmatched value is saved with `found: false`.

**Dataset fields**

| Field | Type | What it does |
| --- | --- | --- |
| `postalCode` | string | Postal or ZIP value returned by the lookup. |
| `country` | string (optional) | Country name when available. |
| `countryCode` | string | ISO 3166-1 alpha-2 country code used for this row. |
| `places` | array of objects (optional) | Place details linked to the postal code when place data is included. |
| `places[].place` | string | Place name. |
| `places[].region` | string (optional) | State, province, or other region when available. |
| `places[].latitude` | number (optional) | Place latitude when available. |
| `places[].longitude` | number (optional) | Place longitude when available. |
| `found` | boolean | `true` when the lookup found a postal record; `false` for a retained no-result row. |

**Example matched row**

This complete row came from a current-beta full-detail run:

```json
{
  "postalCode": "10001",
  "country": "United States",
  "countryCode": "US",
  "places": [
    {
      "place": "New York City",
      "region": "New York",
      "latitude": 40.7484,
      "longitude": -73.9967
    }
  ],
  "found": true
}
```

With `notFoundPolicy` set to `keep`, a no-match row from the same current-beta run can look like this:

```json
{
  "postalCode": "10001",
  "countryCode": "CA",
  "found": false
}
```

#### 💳 Pricing

**Pay per event**

This Actor uses pay-per-event pricing. The current event price is $0.00035 for one successful postal or ZIP lookup saved to your dataset.

#### 🔌 Integrations

**Apify workflow**

https://www.youtube.com/watch?v=bNACk1\_S\_6w\&list=PLObrtcm1Kw6MUrlLNDbK9QRg8VDJg0gOW\&index=4

Run the Actor from Apify Console or the Apify API, then read the structured rows from the default dataset. You can export the dataset in the formats offered by Apify.

#### ❓ FAQ

##### Can I check the same ZIP values in more than one country?

Yes. Add more than one ISO 3166-1 alpha-2 country code. The same submitted postal values are checked for each code, and each row includes the country code used.

##### Can I find postal codes from a city and state?

Yes. Choose **City and state reverse lookup**, then enter the city, state or province, and one or more country codes.

##### What happens when a postal value has no match?

By default, the unmatched value is omitted. Choose **Keep no-result records** to save its postal code and country code with `found: false`.

##### What does leaving Max places per postal code empty do?

It returns all available results until the source is exhausted. Set a positive value when you want to cap the place records for each postal code.

##### Can I use this for USPS address verification or ZIP code lookup by address?

No. This Actor looks up submitted postal or ZIP values and supports city-and-state reverse lookup. It is not a full street-address geocoder and does not provide USPS address verification for questions such as “what is the ZIP code for this address?”

##### Can it find my ZIP code from my location or Google Maps?

No. The Actor does not detect a location or read Google Maps. Submit a postal or ZIP value, or use city-and-state reverse lookup with a country code.

##### Do I need a source API key?

No source API key is required. Add the country code and the lookup values you want to check.

##### Can one postal code have more than one place?

Yes. When the source returns more than one place, the places are kept in the `places` array. Use `maxPlacesPerCode` if you want to cap that list.

##### Can I sort the returned rows?

Yes. Use `sortBy` to order rows by postal code, place, region, latitude, or longitude.

### 📝 Changelog

**0.0: Initial release**

### 🆘 Support

For issues, questions, or feature requests, [file a ticket](https://console.apify.com/actors/maximedupre~zip-code-lookup/issues) and I'll fix or implement it in less than 24h 🫡

### 🔗 Related Actors

- [U.S. Census Geocoder](https://apify.com/maximedupre/us-census-geocoder) — Match full U.S. street addresses or coordinates to Census geography when postal lookup is not enough.
- [Postal Code & ZIP Lookup Scraper](https://apify.com/chrisp1211/postal-code-scraper-max) — Use another direct bulk postal and ZIP lookup workflow for structured place data.
- [Postal Code Lookup Scraper (60+ Countries)](https://apify.com/parseforge/zippopotam-postal-lookup-scraper) — Resolve postal codes to places, states, and coordinates across supported countries.
- [ZIP/Postal Code Lookup](https://apify.com/moving_beacon-owner1/zippopotam----zip-postal-code-lookup) — Check bulk ZIP or postal values and run a city-to-postal reverse lookup.
- [Postal Code Checker: Global ZIP & Postcode Lookup](https://apify.com/scrapemint/postal-code-checker) — Enrich country-tagged postal codes with place, region, district, and GPS fields.

**Made with ❤️ by Maxime Dupré**

# Actor input Schema

## `target` (type: `string`):

Choose the lookup type for this run.

## `postalCodes` (type: `array`):

Enter one or more postal or ZIP values. Each item can be an exact value or a numeric range such as `00501-00503`; leading zeros stay in place.

## `maxPlacesPerCode` (type: `integer`):

Optionally stop each postal code after this many place records. Leave it empty to return all available results until the source is exhausted.

## `city` (type: `string`):

Enter the city for the reverse lookup.

## `region` (type: `string`):

Enter the state or province for the reverse lookup.

## `countryCodes` (type: `array`):

Enter one or more ISO 3166-1 alpha-2 country codes, such as `US` or `CA`. The same lookup values are checked for each code.

## `detailLevel` (type: `string`):

Choose how much detail each result keeps. Postal code only keeps the code and country. Postal code and place also keeps the place and region. The full choice also keeps available latitude/longitude data.

## `notFoundPolicy` (type: `string`):

Choose whether a value with no match is left out or kept as a record with no result data.

## `sortBy` (type: `string`):

Choose the field used to order returned records after the lookups finish.

## Actor input object example

```json
{
  "target": "postalCodeLookup",
  "postalCodes": [
    "10001"
  ],
  "countryCodes": [
    "US"
  ],
  "detailLevel": "full",
  "notFoundPolicy": "omit",
  "sortBy": "postalCode"
}
```

# Actor output Schema

## `dataset` (type: `string`):

Open lookup records in the default dataset. Rows can include country, place, region, and coordinate data.

# API

You can run this Actor programmatically using our API. Below are code examples in JavaScript, Python, and CLI, as well as the OpenAPI specification and MCP server setup.

## JavaScript example

```javascript
import { ApifyClient } from 'apify-client';

// Initialize the ApifyClient with your Apify API token
// Replace the '<YOUR_API_TOKEN>' with your token
const client = new ApifyClient({
    token: '<YOUR_API_TOKEN>',
});

// Prepare Actor input
const input = {
    "target": "postalCodeLookup",
    "postalCodes": [
        "10001"
    ],
    "countryCodes": [
        "US"
    ],
    "detailLevel": "full",
    "notFoundPolicy": "omit",
    "sortBy": "postalCode"
};

// Run the Actor and wait for it to finish
const run = await client.actor("maximedupre/zip-code-lookup").call(input);

// Fetch and print Actor results from the run's dataset (if any)
console.log('Results from dataset');
console.log(`💾 Check your data here: https://console.apify.com/storage/datasets/${run.defaultDatasetId}`);
const { items } = await client.dataset(run.defaultDatasetId).listItems();
items.forEach((item) => {
    console.dir(item);
});

// 📚 Want to learn more 📖? Go to → https://docs.apify.com/api/client/js/docs

```

## Python example

```python
from apify_client import ApifyClient

# Initialize the ApifyClient with your Apify API token
# Replace '<YOUR_API_TOKEN>' with your token.
client = ApifyClient("<YOUR_API_TOKEN>")

# Prepare the Actor input
run_input = {
    "target": "postalCodeLookup",
    "postalCodes": ["10001"],
    "countryCodes": ["US"],
    "detailLevel": "full",
    "notFoundPolicy": "omit",
    "sortBy": "postalCode",
}

# Run the Actor and wait for it to finish
run = client.actor("maximedupre/zip-code-lookup").call(run_input=run_input)

# Fetch and print Actor results from the run's dataset (if there are any)
print("💾 Check your data here: https://console.apify.com/storage/datasets/" + run["defaultDatasetId"])
for item in client.dataset(run["defaultDatasetId"]).iterate_items():
    print(item)

# 📚 Want to learn more 📖? Go to → https://docs.apify.com/api/client/python/docs/quick-start

```

## CLI example

```bash
echo '{
  "target": "postalCodeLookup",
  "postalCodes": [
    "10001"
  ],
  "countryCodes": [
    "US"
  ],
  "detailLevel": "full",
  "notFoundPolicy": "omit",
  "sortBy": "postalCode"
}' |
apify call maximedupre/zip-code-lookup --silent --output-dataset

```

## MCP server setup

```json
{
    "mcpServers": {
        "apify": {
            "command": "npx",
            "args": [
                "mcp-remote",
                "https://mcp.apify.com/?tools=maximedupre/zip-code-lookup",
                "--header",
                "Authorization: Bearer <YOUR_API_TOKEN>"
            ]
        }
    }
}

```

## OpenAPI specification

Download the OpenAPI definition: https://api.apify.com/v2/actors/sEkUvQGyOdLFFoY1s/builds/mJGw2UzK8sA6w838r/openapi.json
