← back to Nationalrealestate
PARCEL-COVERAGE.md
129 lines
# Parcel-level coverage (M-P2)
Property-detail layer sources per county. Everything here is **$0 genuinely-open
bulk data** — no paid APIs, no registration-gated feeds ingested. Registry of
record: the `parcel_source` PG table (what `/api/property/coverage` serves).
LA reads in place from CRCP's SQLite (`source_kind='sqlite'`); every other
covered county lives in the generic `parcel` PG table (`source_kind='pg'`,
migration 004, adapters in `src/ingest/parcels/`).
## Live coverage snapshot (2026-07-29) — 6.6M parcels, 28 counties, 11 states
Coverage has expanded significantly via the ArcGIS-sales pipeline (arcgis_sales.ts)
and dedicated adapters. The hourly loop (`src/jobs/hourly_loop.ts`) runs these
ingests continuously. Current state from `parcel` + `ingest_cursor` tables:
| State | County (FIPS) | Rows | Status | Notes |
|---|---|---|---|---|
| AZ | Maricopa (04013) | 874,899 | ✅ Complete | Phoenix metro; free priced deeds (ArcGIS) |
| CA | Los Angeles (06037) | 2,427,010 | ✅ Complete | CRCP SQLite; no owner/price |
| CA | Sonoma (06097) | 135,722 | ✅ Complete | Free priced deeds (ArcGIS) |
| CA | Alameda (06001) | 54,467 | 🔄 Partial | 187k total; free priced deeds (ArcGIS) |
| CA | San Diego (06073) | 16,422+sweep | 🔄 In progress | Poway done; county-wide sweep at 2k/1.09M |
| CO | Statewide (08001) | 122,000 | 🔄 In progress | 1.12M total; composite ArcGIS |
| FL | Miami-Dade (12086) | 937,248 | ✅ Complete | Owner, zoning, 3 sales/parcel |
| FL | Palm Beach (12099) | 1,000 | 🔄 Stub | 43k total; pagination in progress |
| GA | Fulton (13121) | ~373,000 | ✅ Complete | Atlanta; owner, address |
| IL | Cook (17031) | 1,863,530 | ✅ Complete | Chicago; owner, assessed value |
| NC | Wake (37183) | 437,115 | ✅ Complete | Raleigh; owner, assessed, sale history |
| NY | 5 boroughs (36005/36047/36061/36081/36085) | 858,602 | ✅ Complete | MapPLUTO; owner, zoning |
| OH | Franklin (39049) | 122,047 | ✅ Complete | Columbus; owner, sale 2020-2023 |
| OR | Portland tri-county (41051/41067/41005) | 41,000 | 🔄 Partial | Oregon Metro RLIS; 428k total |
| OR | Deschutes (41017) | 59,032 | ✅ Complete | Bend |
| OR | Marion (41047) | 2,000 | 🔄 Stub | 96k total |
| OR | Klamath (41035) | 1,000 | 🔄 Stub | 38k total |
| TX | Tarrant (48439) | ~714,982 | ✅ Complete | Fort Worth; owner, market value |
| TX | Bexar (48029) | ~721,005 | ✅ Complete | San Antonio; owner, address |
| UT | Salt Lake (49035) | 391,370 | ✅ Complete | Market value; no owner/price |
| WA | King (53033) | 628,417 | ✅ Complete | Seattle; full deed history w/ prices |
| WA | Thurston (53067) | 80,124 | ✅ Complete | Olympia; free priced deeds |
| WA | Yakima (53077) | 1,921 | 🔄 Stub | 56k total |
| WA | Spokane (53063) | 500 | 🔄 Stub | 146k total |
## Covered counties
| County (FIPS) | Rows | Source | Refresh | Fills |
|---|---|---|---|---|
| Los Angeles, CA (06037) | 2,427,010 | CRCP SQLite export of the 2025 secured roll (read in place) | via CRCP | Details (beds/baths/sqft/yr), Tax (1 roll yr), recording date; **no owner / zoning / sale price** (see LA probe below) |
| NYC — Manhattan 36061 (42,544), Bronx 36005 (89,496), Brooklyn 36047 (276,311), Queens 36081 (324,559), Staten Island 36085 (125,692) = **858,602 lots** | | MapPLUTO via NYC Open Data Socrata `64uk-42ks` (JSON paging; `ingest:parcels nyc`) | re-run adapter (PLUTO versioned, currently 26v1) | Details (lot-level: sqft/yr/units — no beds/baths), Tax (assessed land/imp/total), **Ownership (owner of record)**, **Zoning (zonedist1)**, Map (parcel lat/lng) |
| King, WA — Seattle (53033) | 628,417 | Assessor EXTR bulk zips, `aqua.kingcounty.gov/extranet/assessor` (Parcel / ResBldg / RPAcct / RPSale / Lookup; `ingest:parcels king`) | re-run adapter (extracts refresh weekly) | Details (beds/baths/sqft/yr — 525k w/ address), Tax (2026 appraised land+imp), **Property History: REAL recorded deed sales w/ price+buyer+seller (536k parcels)**, Zoning (627k), Owner = latest deed buyer (names file is `_NoName` by policy) |
| Salt Lake, UT (49035) | 393,521 | Utah LIR standardized parcel FeatureServer (keyless ArcGIS; `ingest:parcels saltlake`) | re-run adapter (remote-runnable) | Details (sqft 88%, year-built 88%, use, floors, acres, construction material), **MARKET total+land value (99%)**, site address+city (99%), Map (polygon centroid). No owner name or sale feed in the public LIR layer (UT withholds owner) |
| Wake, NC — Raleigh (37183) | 437,112 | County Assessor authoritative ArcGIS MapServer (`ingest:parcels wake`) | re-run adapter (remote-runnable) | **Richest layer: Details (sqft 86%, year-built 87%, use, units), Ownership (owner 100%), assessed LAND+BLDG+TOTAL value (96%), Property History (sale price+date+deed → 355k events, current to 2024+), Map (polygon centroid)**. No beds/baths or zoning. 62,147 multi-parcel-deed sales flagged bulk |
| Miami-Dade, FL (12086) | 937,182 | Property Appraiser GIS `MDC.PaGis` (keyless ArcGIS MapServer; `ingest:parcels miami`) | re-run adapter (remote-runnable, no GDAL) | Details (use class), **Ownership (TRUE_OWNER1, current)**, **Zoning**, **Property History: up to 3 real sales each w/ price+grantor+grantee+deed → 2.06M parcel_event rows, dates current to 2025**, Map (point lat/lng). Assessed value/beds/baths/sqft/year-built NULL in the public layer. 62,745 multi-folio-deed (assemblage) latest sales flagged bulk + price nulled |
| Franklin, OH — Columbus (39049) | 122,047 | Auditor monthly FileGeoDatabase, `TaxParcelSale` layer (GDAL-extracted; `ingest:parcels franklin`) — see FRANKLIN-RUNBOOK.md | re-run adapter on a GDAL machine, push rows to prod | Details (site address, res sqft, use class), **Ownership (latest grantee)**, **Property History: real sale date+price**, Map (point lat/lng). **Sale window fixed 2020-01..2023-05** (owner = latest-in-window, not current-day); no assessed value/year-built/beds-baths; ~341k geometry-only parcels are a full-coverage TODO |
| Cook, IL — Chicago (17031) | 1,863,530 | Assessor Socrata: universe `pabr-t5kh` (2026, lat/lng+class) + addresses/owner `3723-97qp` (2026) + certified ASSESSED values `uzyt-m557` (2025) + res characteristics `x54s-btds` (2026) (`ingest:parcels cook`) | re-run adapter (annual cycle) | Details (beds/baths/sqft/yr for 1.1M res pins), Tax (2025 certified **assessed** value — 10%/25% of market, labeled), **Ownership (owner/taxpayer name + mailing)**, Map (parcel lat/lng); no zoning (municipal), no sale feed |
| Tarrant, TX — Fort Worth (48439) | ~714,982 | TAD appraisal roll via City-of-Fort-Worth hosted `Parcels_Public_Vview` FeatureServer (keyless ArcGIS, `COUNTYNAME='Tarrant'` filter; `ingest:parcels tarrant`) | re-run adapter (remote-runnable, no GDAL) | Details (sqft/living-area 89%, year-built 90%, state use code), **Ownership (owner 100%)**, site address + real city name, LAND+IMPR + **TRUE MARKET value (99%)** + appraised value, **Property History: deed/ownership-change DATE (98%, no price in this feed) → parcel_event `deed` rows w/ amount NULL**, Map (polygon centroid). **No beds/baths or sale PRICE** (TAD withholds them in the public view). Feed sentinel `12-31-1900` (~18k, "no deed on record") dropped. The TAD county's own `gis.tad.org` 000s to plain curl — this CFW-hosted public view is the reachable authoritative copy |
| Bexar, TX — San Antonio (48029) | ~721,005 | BCAD appraisal roll via City-of-San-Antonio open-data hosted `BCAD_Parcels` FeatureServer (keyless ArcGIS, `PropID>0` filter, `outSR=4326` server-side reproject; `ingest:parcels bexar`) | re-run adapter (remote-runnable, no GDAL) | Details (living-area sqft 87%, state use code, land sqft, legal acreage), **Ownership (owner 99%)**, `Situs` **property** address parsed → street+city+zip (99%; the mailing `addr_*` fields are the owner's, so we read situs instead), Map (polygon centroid, WGS84). **No appraised value / year-built / beds-baths / sale-or-deed feed** in this CoSA-hosted BCAD open view → parcel-DETAIL-only (like Salt Lake); **zero parcel_event rows** (no fabricated sales). The authoritative `maps.bcad.org` PAMapSearch service DOES carry appraised value + owner but blocks bulk paging (no offset/orderBy) — so the pageable CoSA layer is the full-universe backfill source (Tarrant precedent) |
| Fulton, GA — Atlanta (13121) | ~373,004 | Board of Assessors tax digest via Fulton County DoIT/GIS hosted `Tax_Parcels` FeatureServer (keyless ArcGIS, `ParcelID<>''` filter, `outSR=4326`; `ingest:parcels fulton`) | re-run adapter (remote-runnable, no GDAL) | Details (living/dwelling units `LivUnits` 86%, land-use `LUCode` 100%, class code, land acres), **Ownership (owner 99.98%)**, property address assembled from the structured `AddrNumber`/`AddrPreDir`/`AddrStreet`/`AddrSuffix`/`AddrPosDir`/unit components (100%), tax year 2026, Map (polygon centroid, WGS84). **No market/assessed value / year-built / building sqft / beds-baths / sale-or-deed feed** in this open assessor view → parcel-DETAIL-only (like Bexar/Salt Lake); **zero parcel_event rows** (no fabricated sales). The layer serviceDescription self-identifies as the Fulton Board of Assessors annual tax digest. No separate city column (county spans Atlanta + ~14 municipalities) — city left null rather than guessed |
## Probed — gated or absent
| Target | Verdict | Detail |
|---|---|---|
| Maricopa, AZ (04013) | **DONE (2026-07-29 via ArcGIS)** | Previously marked GATED (the mcassessor.maricopa.gov SPA download center is registration-gated). Subsequently landed via ArcGIS FeatureServer adapter (arcgis_sales.ts) — 874,899 parcels, full owner + deed + price. See live coverage table above. |
| LA ownership enrichment | **ABSENT (by policy)** | data.lacounty.gov Socrata is DEAD (redirects to hub.arcgis.com/legacy — URL drift). The live public layer `public.gis.lacounty.gov/.../LACounty_Cache/LACounty_Parcel/MapServer/0` exposes 92 fields — situs, use, beds/baths/sqft (5 bldgs), roll values, legal desc, CENTER_LAT/LON — but **no owner-name field anywhere**. LA County excludes owner names from public bulk data. |
| LA zoning enrichment | **ABSENT (city-scoped)** | No zoning field in the county parcel layer. ZIMAS zoning is City-of-LA GIS only (doesn't cover the other 87 cities); deferred, not rabbit-holed. Upgrade path noted: the county layer's CENTER_LAT/LON could geocode LA parcels (map precision parcel-level) — 2.4M features at maxRecordCount=1000 ≈ 2.4k requests, future pass. |
| NYC DCP zip (bytes of the big apple) | **URL drift** | `s-media.nyc.gov/.../nyc_pluto_25v{1,2}_csv.zip` → 404. Socrata `64uk-42ks` is the stable path (858,602 rows verified vs ~850k expected). |
## Opportunistic top-20 probes (not ingested this pass)
| County | Signal | Note |
|---|---|---|
| Miami-Dade, FL | promising | opendata.miamidade.gov Socrata + ArcGIS open data respond; property-appraiser GIS extracts exist. Next candidate. |
| Franklin, OH (Columbus) | promising | `apps.franklincountyauditor.com/GIS_Shapefiles/` open directory (200) — auditor publishes open extracts. |
| Wake, NC (Raleigh) | promising | wake.gov real-estate data files page live (200) — RE data files are open CSVs. |
| Travis, TX (Austin) | drifted | traviscad.org export page moved (404 on known path); TCAD publishes appraisal-roll exports but the entry point needs re-discovery. |
### 2026-07-26 re-probe (curl, open-files-only)
| County | Verdict | Detail |
|---|---|---|
| Franklin, OH | **DONE 2026-07-26 (via .gdb + GDAL)** | The polygon shapefile turned out geometry-only (PARCELID + Shape). The rich CAMA data is inside the 603MB monthly **FileGeoDatabase**; parsed with GDAL/ogr2ogr (local-only dep) → 122,047 parcels from the `TaxParcelSale` layer. Landed via `ingest:parcels franklin`. See the covered-counties table above + FRANKLIN-RUNBOOK.md. |
| Wake, NC | **DONE 2026-07-26** | The www.wake.gov data PAGE 404s, but the authoritative ArcGIS MapServer (maps.wakegov.com) is live + paginated + rich. Landed via wake_nc.ts → 437,112 parcels. See covered table above. |
| Broward, FL | **GATED (WAF)** | `gis.broward.org` ArcGIS returns 000 to curl; hosted-org guesses empty. BCPA rich data not reachable via direct probe — needs a real-browser or the BCPA bulk-download route (future). |
| Palm Beach, FL | **thin (cached-only)** | `maps.co.palm-beach.fl.us` responds with PAO/Parcels folders, but every layer (Parcels, salesovertime) is geometry-only cached tiles (FID/Shape/Id, no attributes, pagination:false). Rich PAPA data is behind the WAF'd `gisservices.pbcgov.org` (000). Not a clean load — defer to a PAPA-bulk / real-browser pass. |
| Miami-Dade, FL | **DONE 2026-07-26 (ArcGIS)** | Socrata is dead there, but the Property Appraiser's keyless ArcGIS MapServer layer `MDC.PaGis` (`gisweb.miamidade.gov`) serves the full 943k universe with owner+address+use+zoning+3 sales. Landed via dedicated `miami_dade.ts` (`ingest:parcels miami`) → 937,182 parcels, 2.06M sale events. See covered-counties table above. |
## Sale-history depth
| County | History detail | Record count |
|---|---|---|
| King WA | EXTR_RPSale deed chain, 10 most recent priced sales per parcel in `parcel.extra.sales` | 536k parcels with history |
| Miami-Dade FL | Up to 3 real sales each with price+grantor+grantee+deed → `parcel_event` rows, dates to 2025 | 2.06M parcel_event rows |
| Wake NC | Real sale price+date+deed per parcel (355k events), current to 2024+ | 355k events |
| Franklin OH | Sale date+price window 2020–2023 (fixed window from the FileGDB TaxParcelSale layer) | 122k parcels |
| Tarrant TX | Deed/ownership-change date only — no price in the public view | 99% coverage |
NYC ACRIS (open, large) is queued as the next priced-history enrich. Cook sale
prices live with the Recorder (paid/bulk-request) — pending. LA: recording date only.
## West-coast extension candidates (TK-16)
Active pipeline:
- **CA/San Diego county** — in-progress sweep via `ingestSanDiego('county')`, 2k/1.09M
- **CO statewide** — in-progress, 122k/1.12M
Next candidates (all have open ArcGIS or bulk feeds):
| County | Pop. | Source hint |
|---|---|---|
| Riverside CA (06065) | 2.5M | SoCal ArcGIS FeatureServer |
| Sacramento CA (06067) | 1.6M | county GIS open data |
| Santa Clara CA (06085) | 1.9M | county Assessor ArcGIS |
| San Bernardino CA (06071) | 2.2M | county GIS |
| Contra Costa CA (06013) | 1.2M | county open data (Socrata) |
| Multnomah OR (41051) | 820k | already in RLIS sweep |
| Clark WA (53011) | 520k | county Assessor ArcGIS |
| Snohomish WA (53061) | 870k | county open data |
| Pierce WA (53053) | 950k | county Assessor ArcGIS |
## Refresh
`npm run ingest:parcels -- <adapter>` where adapter names are registered in
`src/ingest/parcels/engine.ts`. Each adapter is idempotent (upsert on
`(county_fips, source_id)`), opens/closes an `ingest_runs` row, and
re-registers `parcel_source` counts. Failures close the run `failed` (red),
never silent.
The hourly loop (`src/jobs/hourly_loop.ts`, launchd or pm2) re-drives in-progress
ingests; check `ingest_cursor` table for per-source pagination state.