Address to Census Tract & Demographics (ACS) avatar

Address to Census Tract & Demographics (ACS)

Pricing

from $1.00 / 1,000 location matched to a census tracts

Go to Apify Store
Address to Census Tract & Demographics (ACS)

Address to Census Tract & Demographics (ACS)

Geocode US addresses or coordinates to Census tract and block group GEOIDs with the U.S. Census Geocoder, then append ACS 5-year demographics: population, median income, median age, poverty rate, education, housing and unemployment. Batch CSV or list input, per-row status, built for AI agents.

Pricing

from $1.00 / 1,000 location matched to a census tracts

Rating

0.0

(0)

Developer

Killis Haraway

Killis Haraway

Maintained by Community

Actor stats

0

Bookmarked

2

Total users

1

Monthly active users

3 hours ago

Last modified

Share

Address to Census Tract & Demographics

Turn US addresses or latitude/longitude points into Census tract and block group IDs (GEOIDs), then append American Community Survey (ACS) 5-year estimates for that area: population, median age, median household income, per capita income, poverty rate, education, housing and unemployment.

All data comes from free U.S. Census Bureau services: the Census Geocoder for matching and the Census Data API for ACS tables. The Actor handles the parts that take time to get right: batch limits, retries, matching the tract year to the data year (Connecticut changed its county codes in 2022), the ACS "no estimate" codes, and a clear status on every row.

It was built to be called by AI agents as well as people. You get one dataset item per input row, in input order, with a status and a message.

What you can do

OperationInputOutput per row
geocodeAddresses: one-line strings, structured records, or a CSV fileMatched address, coordinates, state/county/tract/block group codes, GEOIDs, demographics
coordinatesLatitude/longitude pointsTract/block group and demographics for the area containing each point
demographicsTract (11-digit) or block group (12-digit) GEOIDsDemographics only

Typical uses: append neighborhood income and poverty data to a customer or donor list, check eligibility rules that are set by census tract, site selection, grant applications, and research datasets.

Input examples

A few addresses:

{
"operation": "geocode",
"addresses": ["125 N Main St, Memphis, TN 38103", "4600 Silver Hill Rd, Washington, DC 20233"]
}

A CSV file (columns such as address, or street/city/state/zip, plus an optional id, are detected automatically):

{
"operation": "geocode",
"csvUrl": "https://example.com/customers.csv",
"csvColumns": {"street_column": "Addr 1", "zip_column": "Postal", "id_column": "Account"},
"fields": ["income", "housing"]
}

Structured records from an agent, block group level, with margins of error:

{
"operation": "geocode",
"addressRecords": [{"id": "c1", "street": "165 Capitol Ave", "city": "Hartford", "state": "CT", "zip": "06106"}],
"geoLevel": "block_group",
"includeMoe": true
}

Coordinates:

{"operation": "coordinates", "points": [{"id": "store-12", "latitude": 35.1495, "longitude": -90.049}]}

IDs only (cheaper, no demographics): add "demographics": false.

Output

One dataset item per input row. Example (demographic values shortened; real values come from the ACS release you choose):

{
"row": 1,
"id": "c1",
"input": "125 N Main St, Memphis, TN, 38103",
"status": "matched",
"message": null,
"match_type": "Exact",
"matched_address": "125 N MAIN ST, MEMPHIS, TN, 38103",
"latitude": 35.148562911373,
"longitude": -90.05155413782,
"state_fips": "47",
"county_fips": "157",
"tract": "004200",
"block_group": null,
"tract_geoid": "47157004200",
"block_group_geoid": null,
"geo_name": "Census Tract 42; Shelby County; Tennessee",
"total_population": 2154,
"median_age": 34.1,
"median_household_income": 51234,
"poverty_rate": 21.7,
"pct_bachelors_or_higher": 38.2,
"median_home_value": 245000,
"median_gross_rent": 1180,
"unemployment_rate": 5.4,
"demographics_notes": null
}

(The demographic numbers above are illustrative, not real ACS values.)

Rows that don't match still appear, so you can join results back to your list by row or id:

statusMeaningmessage tells you
matchedFound; IDs (and demographics) filled inNothing, or a note
no_matchThe Census address database has no matchCheck the house number and street; add city + state or ZIP
tieSeveral addresses match equallyAdd the ZIP or city and state
invalidNot usable as given (empty, PO Box, no house number, over 100 characters)What's wrong
errorThe geocoder returned nothing for this rowRetry later

Also saved:

  • OUTPUT (key-value store): totals per status, match rate, ACS release used, warnings, and an error code if the run failed.
  • results.csv: the same rows as a spreadsheet, demographics as columns.

Demographic fields

FieldUnitACS variables
total_populationpeopleB01003_001
median_ageyearsB01002_001
median_household_incomeUSD (inflation-adjusted to the end year)B19013_001
per_capita_incomeUSDB19301_001
poverty_rate% of people below the poverty levelC17002_001–003
population_25_pluspeopleB15003_001
pct_high_school_or_higher% of people 25+B15003_017–025
pct_bachelors_or_higher% of people 25+B15003_022–025
housing_unitsunitsB25001_001
vacancy_rate% of housing unitsB25002_001, _003
owner_occupied_rate, renter_occupied_rate% of occupied unitsB25003_001–003
median_home_valueUSDB25077_001
median_gross_rentUSD per monthB25064_001
unemployment_rate% of civilian labor forceB23025_003, _005

Use fields to pick groups (population, income, education, housing, employment) or individual field names. includeMoe adds *_moe columns (90% margin of error) for the direct estimates.

When the Census publishes no estimate for an area (too few survey responses, or a tract with no residents such as a park or an airport), the value is null and demographics_notes explains why. It never contains the Census placeholder codes like -666666666.

When a run fails

The run ends as Failed, the status message starts with an error code, and OUTPUT.error has details. You are not charged for failed runs.

CodeMeaning
NO_VALID_INPUTNo usable rows (empty input, or all rows invalid)
NO_MATCHESNothing matched; check the per-row messages in the dataset
COLUMN_NOT_FOUNDThe CSV has no address/street column, or a column you named doesn't exist. The message lists the available columns
CSV_PARSE_ERRORThe CSV couldn't be read
ACS_YEAR_UNAVAILABLEThat ACS release isn't published yet
CENSUS_KEY_INVALIDOnly if you supplied your own censusApiKey and the Census rejected it
UPSTREAM_RATE_LIMITED, UPSTREAM_UNAVAILABLEThe Census service is busy or down. Rows already finished are kept

Pricing (pay per event)

EventPrice
Location matched to a Census tract (primary event)$0.001 ($1.00 per 1,000)
ACS demographics appended$0.0006 ($0.60 per 1,000)
Actor start (set by Apify)$0.00005

You pay only for matched rows. no_match, tie and invalid rows are free. 1,000 addresses with a 92% match rate and demographics cost $1.47. IDs only would cost $0.92.

The Actor never spends past your maximum cost per run. It processes rows in chunks of 1,000, sizes each chunk to the remaining budget, and stops cleanly with a status message when the budget runs out.

Limits and accuracy

  • Up to 100,000 rows per run. CSV files up to 50 MB. Each address part up to 100 characters (a Census Geocoder limit).
  • US addresses only (50 states, DC, Puerto Rico and the Island Areas). The Census Geocoder matches by interpolating along address ranges. It's good at street addresses and weak at new construction, rural routes and PO Boxes. Typical match rates for clean lists are high, but check match_rate in OUTPUT.
  • Speed: roughly 25 seconds per 1,000 addresses for the geocoding step (one measurement; the Census service speed varies). Block groups add a second pass.
  • Default data year: ACS 5-year 2020–2024 (acsYear: 2024). Tract codes are matched to the same year's boundaries. Older releases back to 2017 are available.
  • Tract estimates are more reliable than block group estimates. Block group values can have large margins of error, so use includeMoe when the numbers matter.
  • These are area estimates for the tract or block group, not facts about any address or household.

Use it from an AI agent (MCP)

claude mcp add --transport http apify "https://mcp.apify.com/?actors=errandkit/census-tract-demographics" \
--header "Authorization: Bearer <APIFY_TOKEN>"

Agent tips: pass small lists in addresses or addressRecords; read the dataset items; check status per row; read OUTPUT.summary.match_rate.

Use it from the API

curl -X POST "https://api.apify.com/v2/acts/errandkit~census-tract-demographics/run-sync-get-dataset-items?token=<APIFY_TOKEN>" \
-H "Content-Type: application/json" \
-d '{"operation":"geocode","addresses":["125 N Main St, Memphis, TN 38103"],"fields":["income"]}'

Data sources, attribution and acceptable use

  • U.S. Census Bureau Geocoder (geocoding.geo.census.gov) and Census Data API, ACS 5-year detailed tables (api.census.gov). Both are free public services.
  • This product uses the Census Bureau Data API but is not endorsed or certified by the Census Bureau.
  • Census terms prohibit using these data, alone or combined with other data, to identify any individual person, household or business. Don't use the output to do that.
  • Your addresses are sent to the Census Geocoder to be matched. The Actor stores results only in your own Apify run storage and keeps nothing after the run.

Support

Open an issue on the Issues tab with the run ID. We usually reply within 1–2 business days.