Comparing Geographies
The /v1/compare endpoint is built for when you need the same variables across multiple places at once — and you want the response structured for easy comparison rather than iteration.
Compare vs. /v1/data
Both endpoints query ACS data. The difference is structure:
/v1/data | /v1/compare | |
|---|---|---|
| Primary use | Single geography, flexible output | Multiple geographies, tabular output |
| Response shape | Flat variable map per geography | Column-oriented table with geographies as rows |
| Best for | Detailed single-place analysis | Ranking, benchmarking, dashboards |
If you're building a table where each row is a geography and each column is a variable, use /v1/compare. If you're pulling a deep variable set for one place, use /v1/data.
Basic Example: Population Across Three States
Compare total population for Texas, California, and New York.
curl -G "https://api.prairiecloud.io/v1/compare" \
-H "X-API-Key: pck_live_your_key_here" \
--data-urlencode "variables=pop_total" \
--data-urlencode "geo=state:48,state:06,state:36" \
--data-urlencode "vintage=2024" \
--data-urlencode "dataset=acs5"
import requests
resp = requests.get(
"https://api.prairiecloud.io/v1/compare",
headers={"X-API-Key": "pck_live_your_key_here"},
params={
"variables": "pop_total",
"geo": "state:48,state:06,state:36",
"vintage": "2024",
"dataset": "acs5",
},
)
data = resp.json()
Response:
{
"vintage": 2024,
"dataset": "acs5",
"columns": ["geography", "geo_id", "pop_total", "pop_total_moe"],
"rows": [
{ "geography": "Texas", "geo_id": "state:48", "pop_total": 30503301, "pop_total_moe": null },
{ "geography": "California", "geo_id": "state:06", "pop_total": 38965193, "pop_total_moe": null },
{ "geography": "New York", "geo_id": "state:36", "pop_total": 19571216, "pop_total_moe": null }
]
}
Margin of error (_moe fields) is null for state-level estimates because the sample size is large enough that Census suppresses the MOE. At smaller geographies, you'll see real values.
Multi-Variable Example
Add median household income and median age to the same request:
curl -G "https://api.prairiecloud.io/v1/compare" \
-H "X-API-Key: pck_live_your_key_here" \
--data-urlencode "variables=pop_total,income_median_household" \
--data-urlencode "geo=state:48,state:06,state:36" \
--data-urlencode "vintage=2024" \
--data-urlencode "dataset=acs5"
resp = requests.get(
"https://api.prairiecloud.io/v1/compare",
headers={"X-API-Key": "pck_live_your_key_here"},
params={
"variables": "pop_total,income_median_household",
"geo": "state:48,state:06,state:36",
"vintage": "2024",
"dataset": "acs5",
},
)
Response:
{
"vintage": 2024,
"dataset": "acs5",
"columns": [
"geography", "geo_id",
"pop_total", "pop_total_moe",
"income_median_household", "income_median_household_moe"
],
"rows": [
{
"geography": "Texas",
"geo_id": "state:48",
"pop_total": 30503301,
"pop_total_moe": null,
"income_median_household": 73035,
"income_median_household_moe": 312
},
{
"geography": "California",
"geo_id": "state:06",
"pop_total": 38965193,
"pop_total_moe": null,
"income_median_household": 84097,
"income_median_household_moe": 289
},
{
"geography": "New York",
"geo_id": "state:36",
"pop_total": 19571216,
"pop_total_moe": null,
"income_median_household": 75157,
"income_median_household_moe": 404
}
]
}
Each requested variable gets its own column, plus a corresponding _moe column. To exclude MOE columns in your own processing, just filter on column names that don't end in _moe.
Real-World Use Case: Highest-Income Texas Counties
Question: Which Texas counties have the highest median household income?
Texas has 254 counties (FIPS codes 48001–48507 in odd increments). Rather than hardcoding all of them, use the geography catalog to fetch the list first:
import requests
API_KEY = "pck_live_your_key_here"
HEADERS = {"X-API-Key": API_KEY}
BASE = "https://api.prairiecloud.io"
# 1. Get all Texas counties
geo_resp = requests.get(
f"{BASE}/v1/geographies",
headers=HEADERS,
params={"type": "county", "state": "48"},
)
counties = geo_resp.json()["data"]
geo_ids = ",".join(c["geo_key"] for c in counties)
# 2. Compare median income across all of them
compare_resp = requests.get(
f"{BASE}/v1/compare",
headers=HEADERS,
params={
"variables": "income_median_household",
"geo": geo_ids,
"vintage": "2024",
"dataset": "acs5",
},
)
rows = compare_resp.json()["rows"]
# 3. Rank by income, drop suppressed values
ranked = sorted(
[r for r in rows if r["income_median_household"] is not None],
key=lambda r: r["income_median_household"],
reverse=True,
)
for rank, row in enumerate(ranked[:10], 1):
print(f"{rank}. {row['geography']}: ${row['income_median_household']:,}")
Output:
1. Collin County: $107,432
2. Fort Bend County: $103,218
3. Williamson County: $99,871
4. Rockwall County: $97,603
5. Hays County: $89,240
...
When querying many geographies at once, check the suppressed count in the response metadata. Counties with very small populations may return null for income variables — filter those out before ranking.
Tips
Maximum geographies per request: The /v1/data endpoint supports up to 5,000 geographies per request on Pro, 25,000 on Business, and 50,000 on Enterprise. The /v1/compare endpoint is limited to 10 geographies per request across all tiers. For state-level analysis with all 3,000+ U.S. counties, paginate using the offset and limit parameters on /v1/geographies to batch your geo IDs.
Finding the right variable names: Not sure what api_name to use? Search the variable catalog:
curl -G "https://api.prairiecloud.io/v1/variables" \
-H "X-API-Key: pck_live_your_key_here" \
--data-urlencode "q=median income"
This returns matching variables with their api_name, description, and Census source code — copy the api_name directly into your variables parameter.
Consistent vintage across geographies: All geographies in a single /v1/compare request must use the same vintage. Cross-vintage comparison is what /v1/timeseries is for.
Next Steps
- Tracking Change Over Time — use
/v1/timeseriesto see how a variable shifts across vintages - Variable Catalog — full reference for browsing and filtering variables
- API Reference: /v1/compare — complete parameter docs er docs