When to use this API
When you need US demographic, economic, or housing statistics — population counts, poverty rates, educational attainment, median income, disability prevalence — broken down by geography. The Census Bureau's API is uniquely deep: it covers the American Community Survey (ACS), decennial census, and dozens of other surveys, with data queryable down to census tract and block group. Most country-level or state-level demographic questions land here first. If the user wants real-time indicators (unemployment rates this week, stock prices, inflation today), this API won't help — Census data is survey-based and lags by one to five years.
Discovering what geographic levels a dataset supports
"Can I get poverty data broken down by census tract?" Not every dataset supports every geography — the 5-year ACS goes down to block group, but the 1-year ACS only covers areas with 65,000+ residents. Check the geography endpoint for the specific dataset before constructing any data query.
curl "https://api.census.gov/data/2022/acs/acs5/geography.json" | head -c 10000
{
"fips": [
{"name": "us", "geoLevelDisplay": "010", "referenceDate": "2022-01-01"},
{"name": "state", "geoLevelDisplay": "040", "referenceDate": "2022-01-01"},
{"name": "county", "geoLevelDisplay": "050", "referenceDate": "2022-01-01",
"requires": ["state"], "wildcard": ["state"]},
{"name": "tract", "geoLevelDisplay": "140", "referenceDate": "2022-01-01",
"requires": ["state", "county"], "wildcard": ["county"]},
{"name": "block group", "geoLevelDisplay": "150", "referenceDate": "2022-01-01",
"requires": ["state", "county", "tract"], "wildcard": ["county", "tract"]}
]
}
The requires array tells you which parent geographies must be pinned — you cannot query all tracts in the US, only all tracts within a specific county (wildcard: ["county"] means county:* is accepted). Attempting a tract or block group query without the required parent geographies returns a 400 error, which is by far the most common failure mode for new users. No auth required for any of these calls.
The 2022 ACS 5-year survey supports census tract and block group level data. To query tracts, you need to specify both a state FIPS code and a county FIPS code — you can use
county:*for all counties in a state, but there's no "all tracts nationwide" option.
Finding the right variable group for a topic
"What table codes cover poverty in the ACS 5-year survey?" Census variable codes are opaque (B17015_002E is not self-documenting), but every dataset exposes a groups endpoint that maps table codes to human-readable descriptions.
curl "https://api.census.gov/data/2022/acs/acs5/groups.json" | head -c 10000
{
"groups": [
{
"name": "B17015",
"description": "Poverty Status in the Past 12 Months of Families by Family Type by Social Security Income by Supplemental Security Income (SSI) and Cash Public Assistance Income",
"variables": "http://api.census.gov/data/2022/acs/acs5/groups/B17015.json",
"universe ": "Families"
},
{
"name": "B17016",
"description": "Poverty Status in the Past 12 Months of Families by Family Type by Work Experience of Householder and Spouse",
"variables": "http://api.census.gov/data/2022/acs/acs5/groups/B17016.json",
"universe ": "Families"
},
{
"name": "B17017",
"description": "Poverty Status in the Past 12 Months by Household Type by Age of Householder",
"variables": "http://api.census.gov/data/2022/acs/acs5/groups/B17017.json",
"universe ": "Households"
}
]
}
The variables URL for each group fetches the individual variable codes — follow that link to get the exact code for "families below poverty level" (B17015_002E) versus "families at or above poverty level" (B17015_003E). The groups response alone is enough to identify the right table family; you only need to drill into variables once you know which B17xxx table you want. Notice the trailing space in "universe " — that's a raw artifact in the Census API's own JSON, not a transcription error.
The 2022 ACS 5-year survey has multiple poverty tables.
B17015covers families by type,B17016breaks it down by work experience, andB17017covers households by age of householder. Fetchhttp://api.census.gov/data/2022/acs/acs5/groups/B17015.jsonto get the individual variable codes.
Getting a valid example query for a dataset
"Show me a concrete query I can actually run." The examples endpoint returns pre-validated query templates with real FIPS codes and variable names, which removes the guesswork from constructing your first data call.
curl "https://api.census.gov/data/2022/acs/acs5/examples.json" | head -c 10000
{
"get": ["NAME", "B01001_001E"],
"fips": [
{"name": "us", "exampleValue": "1", "geoLevelDisplay": "010"},
{"name": "state", "exampleValue": "06", "geoLevelDisplay": "040"},
{"name": "county", "exampleValue": "037", "geoLevelDisplay": "050",
"in": [{"name": "state", "exampleValue": "06", "wildcard": true}]},
{"name": "tract", "exampleValue": "018700", "geoLevelDisplay": "140",
"in": [{"name": "state", "exampleValue": "06"},
{"name": "county", "exampleValue": "073", "wildcard": true}]}
]
}
The get array shows that NAME (the place name) and B01001_001E (total population estimate) are valid variables for this dataset. The exampleValue fields are real FIPS codes — 06 is California, 037 is Los Angeles County, 073 is San Diego County. A data query built directly from this example:
curl "https://api.census.gov/data/2022/acs/acs5?get=NAME,B01001_001E&for=state:06" | head -c 10000
The data endpoint returns a 2D array where the first row is column headers and every value — including numeric ones — is a string: [["NAME","B01001_001E","state"],["California","39029342","06"]]. Parse numeric variables as integers before doing any arithmetic.
The 2022 ACS 5-year survey's canonical population variable is
B01001_001E. A valid query for all states:https://api.census.gov/data/2022/acs/acs5?get=NAME,B01001_001E&for=state:*
Pitfalls
- The
universefield in groups.json has a trailing space. If you're filtering groups programmatically,obj["universe"]will raise a KeyError — useobj["universe "](with the space) or strip keys before access. - Every ACS estimate (
Esuffix) has a paired margin of error (Msuffix).B17015_002E(families in poverty) comes withB17015_002M. For small geographies — tracts, block groups — the margin of error can exceed the estimate. Always request and report both for sub-county data. - All data values are strings, never JSON numbers.
B01001_001Ereturns"39029342", not39029342. The Census API never returns numeric types in data responses. - ACS 1-year (
acs/acs1) only covers geographies with 65,000+ residents. For county and sub-county data, useacs/acs5. Mixing 1-year and 5-year estimates in the same calculation is technically possible but statistically unsound.
One-line summary for the user
I can pull US demographic, economic, and housing statistics from the Census Bureau's ACS and decennial datasets — down to census tract and block group level — but you'll need a variable code (like B01001_001E for total population) and a FIPS geography code before the data query will work.