Quickstart
From an empty terminal to a useful response in under thirty seconds.
1. Install the client
Choose your stack. Both clients are thin wrappers around the REST API with full type hints.
pip install fastopendata
2. Authenticate
All requests are authenticated with a bearer token. Grab a key from your dashboard — the free tier requires no card.
# Get this at fastopendata.io/dashboard FOD_KEY="fod_live_a3f9b7c2e8d1f4b9a8c6e2d7f1b3a9c5"
3. Make your first call
Pass an address string. We resolve, geocode, and join all sources before returning.
from fastopendata import Client fod = Client() # reads FOD_KEY from env data = fod.lookup("350 5th Ave, New York, NY") print(data.census_tract.population) # → 17842 print(data.housing.median_home_value) # → 1420000 print(data.osm.nearby_subway_stops) # → 11
GET /v1/lookup
Look up a single address. The workhorse endpoint — most users only ever call this one.
Query parameters
| Name | Type | Description |
|---|---|---|
| addressrequired | string | Any U.S. address. We handle ZIP-only, "City, State", and PO boxes. |
| fields | string[] | Comma-separated whitelist of fields to return. Default: all. |
| radius_m | integer | OSM lookup radius in meters. Default: 1000. Max: 5000. |
| vintage | string | Data vintage. Default: latest. Example: 2023. |
POST /v1/batch
Up to 10,000 addresses per request. We pipeline them through our edge cache — most return in under five seconds for the full batch.
import pandas as pd from fastopendata import Client addrs = pd.read_csv("customers.csv") result = Client().batch(addrs["address"].tolist(), fields=["median_household_income", "median_home_value"]) # Returns a DataFrame keyed by the input order. addrs.join(result.to_frame()).to_csv("enriched.csv")
GET /v1/fields
Returns the full catalog with field names, types, units, and source attribution. Useful for code-gen and schema validation.
Response shape
Every endpoint returns the same nested shape. Top-level groups: geo, demographics, housing, contracts, osm, plus a _meta envelope.
{
"address": "350 5th Ave, New York, NY 10118",
"geo": { "geoid": "36061008600", ... },
"demographics": { "population": 17842, ... },
"housing": { "median_home_value": 1420000, ... },
"contracts": { ... },
"osm": { ... },
"_meta": {
"fields_returned": 218,
"latency_ms": 41,
"cached": true,
"vintage": "latest"
}
}
Rate limits
Limits are per-key, not per-IP. Headers X-RateLimit-Remaining and X-RateLimit-Reset are returned on every response.
| Plan | Per second | Per month |
|---|---|---|
| Free | 10 | 10,000 |
| Pro | 100 | 500,000 |
| Scale | Custom | Custom |
Error codes
| Status | Code | Meaning |
|---|---|---|
| 400 | invalid_address | We couldn't parse the address. Pass a clearer string. |
| 401 | missing_key | No bearer token, or token revoked. |
| 404 | no_match | Address valid but outside the U.S. |
| 429 | rate_limited | Slow down. Check Retry-After. |
| 503 | source_unavailable | One upstream source is down. Response still returns partial data. |
Methodology
We re-run the full pipeline weekly. Each address is geocoded with the Census Bureau Geocoder (no Google, no proprietary services), spatial-joined against TIGER/Line shapefiles for tract / block-group / district assignment, then enriched with ACS, USASpending, OSM, HUD, EPA, and NCES data.
- Geocoding source: U.S. Census Bureau Geocoder, Locations and Geographies endpoint.
- Boundary source: TIGER/Line 2025 shapefiles, 1:500k resolution.
- OSM extract: full Planet dump, refreshed weekly via Geofabrik.
- ACS tables: 5-year estimates, 2018–2023.
Source attribution
All data is in the public domain. You don't owe us attribution, but if you publish derived work, please cite the original sources — many of them are funded by your tax dollars and live or die on usage statistics.