Ben Moss's homepage

NYC Property Values: Block by Block

→ Open the interactive map

Walking around a Brooklyn neighborhood a while back, I kept noticing how much you can read a block just from street level: how well the stoops are kept up, whether people have flower boxes, what cars are parked out front. I got curious whether any of that was actually measurable. NYC’s Department of Finance publishes assessed values for every one of the city’s ~850,000 tax lots through the MapPLUTO dataset on NYC Open Data. It’s not quite the same as sale prices, but it’s a reasonable proxy and the data is public and granular. I wanted to see what it looked like on a map.

Each block is colored by its total assessed value on a logarithmic scale (blue = low, red = high). A few things that stood out:

How it works

The map uses Leaflet.js with CartoDB dark tiles and has three zoom tiers:

ZoomWhat you seeData source
< 11“Zoom in” prompt
11–16Clustered circles → individual blocksPre-built static JSON
≥ 17Individual tax lotsLive Socrata API

Block view (zoom 11–16) is built on a pre-aggregated snapshot of all 28,664 NYC blocks (~5 MB JSON, generated from the full 853k-lot dataset). The file loads once on page load and stays in memory, so panning and zooming are instant with no round-trips to the API.

At city scale (zooms 11–13), 28k individual block markers would be visually overwhelming, so I use supercluster.js to merge nearby blocks into labeled cluster circles. The cluster radius is 60px, and supercluster stops clustering at zoom 14, where individual block dots appear. Each cluster circle shows the number of blocks it contains and is colored by the aggregate assessed value of those blocks, on the same scale as individual blocks.

Lot view (zoom ≥ 17) queries the Socrata API live with a bounding-box WHERE filter. At that zoom level the viewport covers only a few blocks, so the query is fast and the individual lot granularity is actually useful.

Color scale: Assessed values citywide span nearly ten orders of magnitude (from a few thousand dollars to $8.7B for a single block). Anchoring the color scale to the absolute extremes would compress 95% of blocks into the yellow middle. Instead, I anchored it at the 5th–95th percentile of all block values ($700K–$75M for total; $44K–$10M for average per lot), so the bulk of the city’s variation spreads across the full RdYlBu palette. Blocks outside that range clamp to solid blue or red.

Building the block snapshot

The pre-aggregated block data comes from scripts/nyc_heatmap_data.py, which fetches the full MapPLUTO dataset from the Socrata API in batches and groups lots by borough+block:

# All five boroughs
python scripts/nyc_heatmap_data.py

# Manhattan only
python scripts/nyc_heatmap_data.py --boro 1

# Specific borough to a custom path
python scripts/nyc_heatmap_data.py --boro 3 --output /tmp/brooklyn.json

Each block in the output carries its centroid lat/lng, total assessed value, lot count, sample address, and borough code. The map ships with a snapshot committed to the repo; re-run the script to refresh it against the latest PLUTO release.