# US Address Geocoder API - Census Tract, FIPS & Block Lookup (`captainhandsome/us-census-geocoder`) Actor

US address geocoding that returns full census geography, not just a pin: state and county FIPS, census tract and block GEOIDs, congressional district, place and CBSA. Built on the official Census Bureau geocoder - public domain, no key, resale safe.

- **URL**: https://apify.com/captainhandsome/us-census-geocoder.md
- **Developed by:** [Joseph McRell](https://apify.com/captainhandsome) (community)
- **Categories:** Developer tools, Business
- **Stats:** 2 total users, 1 monthly users, 100.0% runs succeeded, 0 bookmarks
- **User rating**: No ratings yet

## Pricing

from $7.00 / 1,000 results

This Actor is paid per event. You are not charged for the Apify platform usage, but only a fixed price for specific events.
Since this Actor supports Apify Store discounts, the price gets lower the higher subscription plan you have.

Learn more: https://docs.apify.com/actors/running/actors-in-store.md#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

## US Address Geocoder with Census Tract and Block

Turn a list of US street addresses into coordinates and, more usefully, into the Census geography those addresses sit in: state and county FIPS, census tract, census block, incorporated place, congressional district and combined statistical area. Those GEOIDs are the join keys for every demographic dataset the Census Bureau publishes, so a geocoded address stops being a dot on a map and becomes a row you can enrich. It runs on the Census Bureau's own geocoder, which needs no API key and places no resale restriction on its output.

### What data can I extract?

- Standardised address, latitude and longitude, plus the parsed house number, pre-direction, street name, suffix type and suffix direction
- The TIGER/Line segment ID, which side of it the address sits on, and the address range it was interpolated within
- State FIPS and name, county FIPS (GEOID) and name, and the county subdivision (township) name and GEOID
- Incorporated place name and GEOID, and the ZIP Code Tabulation Area, which is the ZIP-shaped geography the Bureau actually publishes data for
- Census tract, block group and block, each with its full GEOID - the block group GEOID is the one American Community Survey estimates are published at
- Tract land area, water area and internal point, so you can compute density without downloading TIGER/Line shapefiles
- Metro or micropolitan area (CBSA) name, code and type, the metropolitan division, the combined statistical area, and the urban area - plus the Bureau's own urban/rural flag
- School district name, GEOID, type and the grade span it serves
- Congressional district with its national GEOID and Congress number, and the upper and lower state legislative districts
- PUMA name and GEOID for joining to ACS public use microdata, and the Census region and division for national rollups
- The benchmark and geography vintage that actually answered, recorded on every row
- Addresses that failed to match, returned with `matched: false` rather than silently dropped

One flat row of 63 columns per input address, in input order. Every result is written to the default dataset and can be downloaded as JSON, CSV, Excel or XML, or pulled through the Apify API.

### Input example

```json
{
  "addresses": [
    "1600 Pennsylvania Ave NW, Washington, DC",
    "350 Fifth Ave, New York, NY 10118"
  ],
  "benchmark": "Public_AR_Current",
  "vintage": "Current_Current",
  "max_items": 25
}
```

Addresses are one-line strings; the Census parser is tolerant about punctuation but wants at least a street, a city and a state. `benchmark` chooses which Census address file to match against and `vintage` chooses which decade of geography to report the tract and block from. Leave both on Current unless you are deliberately reconciling against 2020 Census boundaries.

### Output example

A real row from a run of this Actor:

```json
{
  "input_address": "1600 Pennsylvania Ave NW, Washington, DC",
  "matched": true,
  "match_count": 1,
  "matched_address": "1600 PENNSYLVANIA AVE NW, WASHINGTON, DC, 20500",
  "latitude": 38.89869893252,
  "longitude": -77.03518753691,
  "tiger_line_id": "76225813",
  "street_side": "L",
  "street_number": "1600",
  "address_range_to": "1648",
  "street": "PENNSYLVANIA AVE NW",
  "street_pre_direction": null,
  "street_name": "PENNSYLVANIA",
  "street_suffix_type": "AVE",
  "street_suffix_direction": "NW",
  "city": "WASHINGTON",
  "state": "DC",
  "zip": "20500",
  "state_fips": "11",
  "state_name": "District of Columbia",
  "county_fips": "11001",
  "county_name": "District of Columbia",
  "county_subdivision_name": "Washington",
  "county_subdivision_geoid": "1100150000",
  "place_name": "Washington",
  "place_geoid": "1150000",
  "tract": "9800",
  "tract_geoid": "11001980000",
  "block_group": "1",
  "block_group_geoid": "110019800001",
  "block": "1034",
  "block_geoid": "110019800001034",
  "urban_rural": "U",
  "tract_land_area_sqm": 6514231,
  "tract_water_area_sqm": 4996397,
  "tract_centroid_lat": 38.8809933,
  "tract_centroid_lon": -77.0363219,
  "zcta": "20006",
  "puma_name": "District of Columbia (South Central)",
  "puma_geoid": "1100106",
  "urban_area_name": "Washington--Arlington, DC--VA--MD",
  "urban_area_code": "92242",
  "metro_area_name": "Washington-Arlington-Alexandria, DC-VA-MD-WV",
  "metro_area_code": "47900",
  "metro_area_type": "Metropolitan",
  "metro_division_name": "Washington, DC-MD",
  "metro_division_code": "47764",
  "cbsa_name": "Washington-Baltimore-Arlington, DC-MD-VA-WV-PA",
  "csa_code": "548",
  "census_region": "South",
  "census_division": "South Atlantic",
  "congressional_district": "Delegate District (at Large)",
  "congressional_district_geoid": "1198",
  "congress_session": "119",
  "state_leg_district_upper": "2",
  "state_leg_district_lower": null,
  "school_district_name": "District of Columbia Public Schools",
  "school_district_geoid": "1100030",
  "school_district_type": "Unified",
  "school_district_lo_grade": "PK",
  "school_district_hi_grade": "12",
  "benchmark_name": "Public_AR_Current",
  "vintage_name": "Current_Current"
}
```

Unmatched addresses are returned too, not dropped. They carry the same 63 columns, with `matched` false, `match_count` 0, your `input_address` echoed back so you can reconcile the batch against your source list, the `benchmark_name` and `vintage_name` that answered, and every remaining column null.

Two field names undersell what they hold. `congressional_district` is a bare number for voting districts (350 Fifth Avenue returns `"12"`) and descriptive text for non-voting jurisdictions, so join on `congressional_district_geoid` instead. And `cbsa_name` is the Combined Statistical Area, which is broader than the metro area inside it - hence Washington coming back joined with Baltimore; the metro area itself is in `metro_area_name`.

### Common use cases

- Appending tract GEOIDs to a customer or patient list so it can be joined to American Community Survey income, age or language tables
- Site selection and catchment analysis, where county FIPS is the key to labour and business statistics
- Political and civic targeting by congressional district without buying a districting file
- Fair-lending, CRA and grant reporting, which are specified in tract terms and expect the tract GEOID verbatim
- Address hygiene: the standardised `matched_address` collapses spelling variants of the same address before de-duplication
- Building a block-level base table for a dashboard, then joining decennial block data onto it

### Use with AI agents and MCP

Apify's MCP server can discover and call this Actor from an AI workflow. Example intent:

> Geocode these 40 branch addresses and tell me which census tract each one is in.

Pass the JSON from **Input example** as the tool arguments. The input schema is strict and rejects unsupported parameters, and every dataset field carries a title, a description and a real example, so an agent can tell `tract` (the human tract number, not unique) from `tract_geoid` (the 11-digit key it should actually join on) without guessing. Because unmatched addresses come back as rows rather than as absences, an agent can count its own failures instead of silently reporting on a shorter list than it was given.

### Pricing and cost control

Output is billed per result at **$0.01 per result** (about $10.00 per 1,000 results), plus a $0.0005 Actor-start charge billed once per gigabyte of memory at run start. Use `max_items` to cap both output volume and charges. The price shown on the Apify Store listing is authoritative.

Cost control here is simple and slightly unusual: this Actor emits exactly one row per address, so **the length of your address list is your bill**. There is no pagination to overshoot and no query that can quietly return ten times what you expected. Unmatched addresses are charged too, because they are still rows - clean obvious rubbish out of your list before submitting it, not after. Be aware that `max_items` here is a declared ceiling rather than an enforced one: this Actor does not truncate the address list to it, so the list itself is the only real cap. Trim the list to the number of rows you are willing to pay for.

### Reliability

Requests run five at a time against the Census Bureau's public geocoder with a 60-second timeout each, and results are pushed in input order so the output lines up with the list you supplied. A request that times out, errors or returns no candidate does not abort the batch: the address is logged and written out with `matched: false`, which is why a run of 500 addresses always produces 500 rows.

The upstream service is a free government endpoint with no published service level. It is occasionally slow and does go down, usually briefly. A failed batch is cheap to repeat, and because the Actor is deterministic for a given address list you can re-run the unmatched subset on its own.

### Limitations and responsible use

- United States only. There is no international coverage, and Puerto Rico and the territories depend on Census address file coverage rather than on this Actor.
- Coordinates are interpolated along the matched TIGER street segment, not rooftop or parcel points. Expect a position on the street frontage, which is fine for tract and block assignment and wrong for anything needing metre-level precision.
- A match is only as good as the Census address file. New construction and rural route addresses are the usual misses, and `Public_AR_Current` is refreshed by the Bureau, not by this Actor.
- `place_name` is null in unincorporated territory and `cbsa_name` is null outside any combined statistical area. Both are legitimately empty rather than missing.
- Census output is US federal government work, so there is no licence obstacle to reselling or redistributing the results. Your own input addresses are a different matter: if they are personal data, geocoding them to block level is a meaningful increase in precision and should be handled accordingly.

### FAQ

#### Do I need an API key or a Census account?

No. The Census Bureau geocoder is open and unauthenticated, and this Actor supplies no credentials of its own.

#### Can I resell or publish the results?

Yes. Output produced by a US federal agency is in the public domain, which is the main practical difference between this and free geocoders whose licences impose attribution or share-alike terms on what you build.

#### What happens to addresses that do not match?

They are returned with `matched: false` and every other field null, in their original position in the list. They count as results and are charged as results, so a failed match is visible in the data rather than inferred from a row that is not there.

#### Is this rooftop-accurate geocoding?

No. It is street-segment interpolation. Use it to assign an address to a tract, block, county or district; do not use it to measure a distance of a few metres.

#### What is the difference between `tract` and `tract_geoid`?

`tract` is the tract number as a person writes it, for example 76, and repeats across counties. `tract_geoid` is the 11-digit state-county-tract key, for example 36061007600, and is what Census tables join on. The same distinction applies to `block` and `block_geoid`.

#### Why is `cbsa_name` showing two cities?

Because it is the Combined Statistical Area layer, which groups adjacent metro and micro areas. It is deliberately broader than the single metro area an address sits in.

#### Can an AI agent call it?

Yes. The Actor has a strict input schema and a fully described dataset schema, and can be called through Apify's MCP tooling like any other Store Actor.

# Actor input Schema

## `addresses` (type: `array`):

One-line US addresses, e.g. '1600 Pennsylvania Ave NW, Washington, DC'.

## `benchmark` (type: `string`):

Which Census address file to match against.

## `vintage` (type: `string`):

Which geography vintage to report tract and block from.

## `max_items` (type: `integer`):

The number of result rows you are willing to pay for. This Actor returns exactly one row per address, matched or not, and does not truncate the list, so the length of your address list is what actually sets output volume and cost - keep it at or below this number.

## Actor input object example

```json
{
  "addresses": [
    "1600 Pennsylvania Ave NW, Washington, DC",
    "350 Fifth Ave, New York, NY 10118"
  ],
  "benchmark": "Public_AR_Current",
  "vintage": "Current_Current",
  "max_items": 25
}
```

# Actor output Schema

## `results` (type: `string`):

One flat row per input address, matched or not.

# 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 = {
    "addresses": [
        "1600 Pennsylvania Ave NW, Washington, DC",
        "350 Fifth Ave, New York, NY 10118"
    ]
};

// Run the Actor and wait for it to finish
const run = await client.actor("captainhandsome/us-census-geocoder").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 = { "addresses": [
        "1600 Pennsylvania Ave NW, Washington, DC",
        "350 Fifth Ave, New York, NY 10118",
    ] }

# Run the Actor and wait for it to finish
run = client.actor("captainhandsome/us-census-geocoder").call(run_input=run_input)

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

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

```

## CLI example

```bash
echo '{
  "addresses": [
    "1600 Pennsylvania Ave NW, Washington, DC",
    "350 Fifth Ave, New York, NY 10118"
  ]
}' |
apify call captainhandsome/us-census-geocoder --silent --output-dataset

```

## MCP server setup

```json
{
    "mcpServers": {
        "apify": {
            "type": "http",
            "url": "https://mcp.apify.com/?tools=fetch-actor-details,captainhandsome/us-census-geocoder"
        }
    }
}

```

The hosted server signs you in with OAuth on first connect, so no API token belongs in this config. Clients without OAuth support can send an `Authorization: Bearer <APIFY_API_TOKEN>` header instead, using a token from API & Integrations in Apify Console (https://console.apify.com/settings/integrations).

## OpenAPI specification

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