Explainer · US Geographic & Demographics API

ZCTA vs ZIP code

A ZIP code is a USPS mail-delivery code attached to addresses; a ZCTA (ZIP Code Tabulation Area) is an area the Census Bureau builds from census blocks so that it can publish statistics for something close to a ZIP code. Each block is assigned the ZIP code used by most of its addresses, and blocks with the same code form the ZCTA. So a ZCTA and the ZIP code with the same five digits usually overlap heavily but rarely cover exactly the same addresses, and not every ZIP code has a ZCTA.

By New Odyssey · Published · Markdown

ZIP codes are points, not areas

The Postal Service assigns ZIP codes to delivery addresses and routes. A ZIP code has no official boundary: it is a property of the addresses it serves. The Census Bureau describes ZIP codes in its own address system as "a point-based dataset unsuitable for mapping and many analysis applications." Statistics such as population or median income need an area to count within, which is why the Census Bureau publishes them for ZCTAs instead.

What a ZCTA is

In the Census Bureau's words, ZCTAs "are generalized areal representations of the geographic extent and distribution of the point-based ZIP Codes built using 2020 Census tabulation blocks." For each block that contains housing units, the ZCTA is the ZIP code associated with the most addresses in that block. Adjacent blocks with the same code make up one ZCTA, which takes that 5-digit code.

  • ZCTAs are made of whole census blocks. They do not nest within counties or states: one ZCTA can lie in several counties.
  • They are delineated with the decennial census: the current set is the 2020 ZCTAs, built with the same method as the 2010 ZCTAs, and current American Community Survey (ACS) estimates for ZCTAs use them.
  • Every 2020 ZCTA code was a valid USPS ZIP code as of January 1, 2020.

Where ZCTAs and ZIP codes differ

ZIP code and ZCTA compared
USPS ZIP codeCensus ZCTA
Defined byU.S. Postal Service, for mail deliveryU.S. Census Bureau, for statistics
ShapeSet of delivery addresses; no official boundaryArea made of whole census blocks
ChangesWhen USPS changes deliveryFixed until the next decennial delineation (current set: 2020)
AssignmentPer addressPer census block: the ZIP code of most of the block's addresses
Published statisticsNone from the Census BureauDecennial census and ACS 5-year estimates

The practical consequences:

  • Not every ZIP code has a ZCTA. The Census Bureau says "not all valid ZIP Codes are represented by a 2020 ZCTA." A ZIP code that is never the most common code in any block, which can happen for codes that serve a single building, an organisation or mostly PO boxes, gets no ZCTA.
  • Boundaries don't match exactly. Because each block takes one code, addresses in a block that use a different ZIP code are counted in the neighbouring ZCTA.
  • A ZIP code can cross county and state lines, and so can a ZCTA. The 2020 ZCTA-to-county relationship file gives the overlap of every ZCTA with every county.
  • Newer ZIP codes have no ZCTA. 2020 ZCTA codes were valid USPS ZIP codes as of January 1, 2020, so a ZIP code created after that has no 2020 ZCTA.

How the Olympus API resolves a 5-digit code

The US Geographic & Demographics API serves ACS 5-year estimates for ZCTAs and counties. Location endpoints take a 5-digit code and resolve it only by exact ZCTA code. No ZIP-to-ZCTA crosswalk is applied and nothing is guessed:

  • If a ZCTA has that code, the response describes the ZCTA: geography.type is zcta, geography.matched_by is exact_zcta_code, and meta.notices includes ZCTA_NOT_USPS_ZIP.
  • If no ZCTA has that code, the API answers 404 ZCTA_NOT_FOUND, with the code in details.codes. The code may still be a valid USPS ZIP code.
  • geography.counties lists the counties the ZCTA overlaps, with land-area shares from the 2020 relationship file, and primary_county_fips is the county with the largest land share.
ZCTA profile for 02139
curl -s "https://api.olympus.new-odyssey.com/v1/geo-demographics/locations/02139" \
  -H "X-API-Key: $OLYMPUS_API_KEY"
200 OK (abridged)
{
  "data": {
    "geography": {
      "type": "zcta",
      "id": "02139",
      "input_code": "02139",
      "matched_by": "exact_zcta_code",
      "primary_county_fips": "25017",
      "primary_state_code": "MA",
      "geography_vintage": "2024 Gazetteer / 2020 relationship",
      "counties": [{ "county_fips": "25017", "zcta_land_share": …, "is_primary": true, … }]
    },
    "vintage": { "survey": "ACS 5-year", "period": "2020-2024", "year": 2024 },
    …
  },
  "meta": {
    "notices": [
      { "code": "ZCTA_NOT_USPS_ZIP", "message": "ZCTAs approximate USPS ZIP code areas; they are not ZIP codes." }
    ]
  }
}
404 for a code with no ZCTA
{
  "error": "No ZIP Code Tabulation Area has this code",
  "code": "ZCTA_NOT_FOUND",
  "product": "geo-demographics",
  "details": { "codes": ["02238"] }
}

In Python, treat the 404 as "no ZCTA", not as an invalid ZIP code:

zcta.py
import os
import requests

API = "https://api.olympus.new-odyssey.com"
HEADERS = {"X-API-Key": os.environ["OLYMPUS_API_KEY"]}

def zcta_profile(code: str):
    """The ZCTA with this exact code, or None when no ZCTA has it."""
    r = requests.get(f"{API}/v1/geo-demographics/locations/{code}", headers=HEADERS, timeout=30)
    if r.status_code == 404 and r.json().get("code") == "ZCTA_NOT_FOUND":
        return None  # may still be a valid USPS ZIP code
    r.raise_for_status()
    return r.json()["data"]

profile = zcta_profile("02139")
if profile:
    geo = profile["geography"]
    print(geo["type"], geo["id"], geo["matched_by"], geo["primary_county_fips"])
    for c in geo["counties"]:
        print("  county", c["county_fips"], c["zcta_land_share"])

Agents can call the get_us_demographics MCP tool with {"zcta": "02139"}. It reads the ZCTA's full demographics (/demographics), resolved the same way, and returns the geography, vintage and notices with them.

When to use which

  • Mailing, delivery, address validation: use ZIP codes, and USPS data.
  • Demographics, market sizing, comparisons between areas: use ZCTAs (or counties and tracts), and say in your product that the figures describe the ZCTA, not the ZIP code.
  • Sales tax: neither. Tax jurisdictions don't follow ZIP codes or ZCTAs; look rates up by address. See How sales tax rates by address work.

This product uses the Census Bureau Data API but is not endorsed or certified by the Census Bureau.

Sources