The business directory is why most people arrive at Nextdoor's public data. The city profile is the part they discover afterwards and end up using more, because it answers the question that comes before “who are the providers here” — namely, is this market worth working at all.
What is in a city row
- Population and composition: resident count, average income, average age, homeowner percentage.
- Nextdoor's own scores: safety, friendliness, affordability.
- Category coverage: all 54 business categories Nextdoor tracks, and how populated each is in this city.
- Structure: neighborhood count, reaching 852 in the largest cities.
- Activity: counts of classifieds, local groups and events.
One row per city, in a separate cities dataset, at $0.008 each. It is the cheapest row type the Actor produces relative to how much is in it.
The scores, and what they are not
Safety, friendliness and affordability are Nextdoor's aggregations of what neighbors report. They are not crime statistics, not census measures, and Nextdoor does not publish the methodology behind them.
That makes them useful for one thing and misleading for another. Comparing two cities' scores within the platform tells you something real about how residents perceive them. Quoting a safety score as though it were a crime rate does not, and this site will not do it.
Using category coverage for market sizing
This is the field that earns the dataset its place. Before scraping a single business, the city row tells you how many of the 54 categories are actually populated in that city — which is a direct proxy for how deep the local market is and, more usefully, where the gaps are.
A category that exists in a city of 60,000 with only a handful of providers is either an underserved market or a market that does not work there. Either way, that is a question worth asking before you commit a full sweep to it.
Why it lands in its own dataset
Because a city and a business are not the same record type. Putting both in one table gives you a business table where the demographic columns are blank on every row except a handful, and a city row where 34 business fields are null. Separate datasets keep both tables uniform, which is the difference between data you can load straight into a warehouse and data you have to clean first.
Join them on source_city_slug, which every business row carries.
A cheap two-stage workflow
Stage one: city data only. Set includeCityData: true, maxBusinessesPerCity: 1, and list every candidate city. Twenty cities costs about 16 cents in city rows and gives you the full profile of each.
{
"cities": ["san-clemente--ca", "dana-point--ca", "mission-viejo--ca"],
"categories": ["Dentist"],
"maxBusinessesPerCity": 1,
"includeRecommendations": false,
"includeCityData": true
}Stage two: pick the three or four cities whose income, age and category coverage match your offer, and run the real sweep only on those. The reconnaissance stage costs cents and routinely removes half the candidate list.
Cost
$0.008 per city. Fifty cities is forty cents, which for a market-selection dataset that includes income, age, homeownership and category depth is difficult to beat — and it is a one-off, because demographics do not move week to week. Cache it and set maxCacheAgeDays generously.



