[object Object]

← back to Nationalrealestate

parcels: add Miami-Dade FL (12086) via keyless ArcGIS PaGis — 937k parcels + 2.06M sales

7dfbf4ffade119fc33831a8819f7102106c7dd53 · 2026-07-26 09:50:48 -0700 · Steve Abrams

DTD verdict B (unanimous 5/5): dedicated full-universe adapter over extending the generic sale-cursor one. Streams the Property Appraiser MDC.PaGis layer (memory-safe batch upsert after a first attempt OOM'd holding 943k in RAM). 937,182 parcels: current owner (99.9%), address (95%), zoning (100%), use; up to 3 recorded sales each -> 2,064,976 parcel_event rows w/ price+grantor+grantee+deed+qualified flag, dates current to 2025. Bulk guard: 62,745 multi-folio-deed assemblages detected in-DB -> price nulled + flagged (no ParcelCount field, so deed-spans-multiple-folios is the signal). Top prices verified as real landmark commercial sales (Ponte Gadea, Brickell towers). No assessed value/beds/baths/sqft/year in the public layer.

Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>

Files touched

Diff

commit 7dfbf4ffade119fc33831a8819f7102106c7dd53
Author: Steve Abrams <steve@designerwallcoverings.com>
Date:   Sun Jul 26 09:50:48 2026 -0700

    parcels: add Miami-Dade FL (12086) via keyless ArcGIS PaGis — 937k parcels + 2.06M sales
    
    DTD verdict B (unanimous 5/5): dedicated full-universe adapter over extending the generic sale-cursor one. Streams the Property Appraiser MDC.PaGis layer (memory-safe batch upsert after a first attempt OOM'd holding 943k in RAM). 937,182 parcels: current owner (99.9%), address (95%), zoning (100%), use; up to 3 recorded sales each -> 2,064,976 parcel_event rows w/ price+grantor+grantee+deed+qualified flag, dates current to 2025. Bulk guard: 62,745 multi-folio-deed assemblages detected in-DB -> price nulled + flagged (no ParcelCount field, so deed-spans-multiple-folios is the signal). Top prices verified as real landmark commercial sales (Ponte Gadea, Brickell towers). No assessed value/beds/baths/sqft/year in the public layer.
    
    Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
---
 PARCEL-COVERAGE.md               | 3 ++-
 src/ingest/parcels/miami_dade.ts | 8 ++++----
 2 files changed, 6 insertions(+), 5 deletions(-)

diff --git a/PARCEL-COVERAGE.md b/PARCEL-COVERAGE.md
index 726506e..0ef70ba 100644
--- a/PARCEL-COVERAGE.md
+++ b/PARCEL-COVERAGE.md
@@ -14,6 +14,7 @@ migration 004, adapters in `src/ingest/parcels/`).
 | 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) |
+| 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 |
 
@@ -41,7 +42,7 @@ migration 004, adapters in `src/ingest/parcels/`).
 |---|---|---|
 | 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 | **URL drift** | The documented data-files page 404s now (site reorg). Wake still publishes open RE data files; entry point needs re-discovery before an adapter. |
-| Miami-Dade, FL | **off-Socrata** | `opendata.miamidade.gov` no longer serves the standard Socrata `/api/catalog/v1` or `/resource/` endpoints (302/404) — migrated like several state portals. Property-appraiser **ArcGIS** open-data is the remaining open path; re-probe that surface, not Socrata. |
+| 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
 
diff --git a/src/ingest/parcels/miami_dade.ts b/src/ingest/parcels/miami_dade.ts
index c2a8791..4de2a63 100644
--- a/src/ingest/parcels/miami_dade.ts
+++ b/src/ingest/parcels/miami_dade.ts
@@ -147,12 +147,12 @@ export async function ingestMiami(): Promise<{ upserted: number }> {
     // its price is the bundle total, not per-parcel. Null the price + flag, in one pass.
     const b = await query<{ n: string }>(
       `WITH bulk AS (
-         SELECT extra::jsonb->>'latest_deed' AS deed, COUNT(*)::int AS cnt
-           FROM parcel WHERE county_fips=$1 AND extra::jsonb->>'latest_deed' IS NOT NULL
+         SELECT extra->>'latest_deed' AS deed, COUNT(*)::int AS cnt
+           FROM parcel WHERE county_fips=$1 AND extra->>'latest_deed' IS NOT NULL
           GROUP BY 1 HAVING COUNT(*) > 1)
        UPDATE parcel p SET last_sale_price = NULL,
-         extra = (p.extra::jsonb || jsonb_build_object('bulk_sale', true, 'bulk_deed_folio_count', bulk.cnt))::text
-         FROM bulk WHERE p.county_fips=$1 AND p.extra::jsonb->>'latest_deed' = bulk.deed
+         extra = p.extra || jsonb_build_object('bulk_sale', true, 'bulk_deed_folio_count', bulk.cnt)
+         FROM bulk WHERE p.county_fips=$1 AND p.extra->>'latest_deed' = bulk.deed
        RETURNING 1 AS n`, [FIPS]);
     const bulk = b.rowCount ?? 0;
 

← 9305f09 auto-save: 2026-07-26T09:42:34 (2 files) — src/ingest/parcel  ·  back to Nationalrealestate  ·  miami: contrarian gate fixes — placeholder-deed bulk false-p d409f98 →