ActorStack.dev
Lead generationSocial mediav0.1.24updated 18 August 2026

Nextdoor Business & Reviews Scraper

No login. No session cookies. No browser.

Discovers Nextdoor businesses by city and category, then extracts 34 fields per business, the neighbor recommendations written about it and the demographics of the city it sits in. It reads only what Nextdoor's servers hand to a signed-out visitor, so there is no cookie to refresh and nothing that expires between runs.

oswaldocarabano/nextdoor-scraper

input.json
{
  "cities": ["san-clemente--ca"],
  "categories": ["Dentist", "Plumber"],
  "maxBusinessesPerCity": 50,
  "includeRecommendations": true,
  "includeCityData": true
}
Version
v0.1.24
Memory
512 MB
Browser
none
Proxy
US residential IPs, preconfigured

Short answer

The Nextdoor Business & Reviews Scraper extracts public Nextdoor data without an account: business listings with contact details (phone filled on 93.9% of 741 measured businesses), neighbor recommendations classified into real reviews vs service requests at 95.6% accuracy, and city-level demographics. Pricing is pay-per-result at $0.008 per business and $0.002 per recommendation, and error rows are never charged.

Key points

  • Runs signed-out: no account, no session cookies, nothing that expires between runs.
  • 34 fields per business, with fill rates counted over 741 distinct businesses across 5 cities and 12 categories — not estimated.
  • Every recommendation is classified as `recommendation`, `service_request`, `thanks` or `unknown`, at 95.6% accuracy on a hand-labelled set. Measured across 891 recommendations, 50% were service requests and only 19% actual reviews.
  • Nextdoor's category directory is regional, not municipal. `onlyRequestedCity` filters during discovery, so a dropped business is never charged.
  • Throughput measured on the platform at ~3,300 businesses/hour end-to-end at the default concurrency of 5.
  • Neighbor posts and author neighborhoods are off by default, because a partial name next to a precise neighborhood can identify a real person.
On this page11 sections

What it does

Discovers Nextdoor businesses by city and category, then extracts 34 fields per business, the neighbor recommendations written about it and the demographics of the city it sits in. It reads only what Nextdoor's servers hand to a signed-out visitor, so there is no cookie to refresh and nothing that expires between runs.

output — one row
{
  "_type": "business",
  "name": "Example Plumbing",
  "slug": "example-plumbing-san-clemente-ca",
  "categories": ["Plumber", "Water Heater Installation"],
  "phone_number": "+19495550123",
  "email": "hello@exampleplumbing.com",
  "website_url": "https://exampleplumbing.com",
  "address_full": "123 Avenida Del Mar, San Clemente, CA 92672",
  "address_postal_code": "92672",
  "hide_address": false,
  "recommendations_count": 12,
  "neighbors_talking_count": 34,
  "recommendations_summary": "Neighbors mention fast response and fair pricing.",
  "is_verified": true,
  "source_city_slug": "san-clemente--ca",
  "source_category": "Plumber",
  "scraped_at": "2026-08-17T12:00:00.000Z",
  "from_cache": false,
  "data_age_hours": 0,
  "_warnings": [],
  "recommendations": [
    {
      "kind": "recommendation",
      "kind_confidence": 0.92,
      "kind_signals": ["praise", "past_service"],
      "text": "They fixed our water heater the same day we called. Fair price too.",
      "author_display_name": "Sarah M.",
      "author_city": "San Clemente"
    }
  ]
}

Why this one

It does not ask you for your cookies

Most Nextdoor scrapers require you to paste session cookies from a logged-in browser. That works the day you set it up and breaks silently when the cookies expire. This Actor reads only the signed-out surface, so a run in six months behaves like a run today. The trade-off is stated openly: it cannot reach anything behind the login.

A classifier for a feed that lies about itself

Nextdoor's recommendation feed mixes praise, requests for a provider and bare thank-yous, and all three look alike. Scrape it raw and half of your "reviews" are neighbors asking whether anyone knows a good plumber — worthless as review data and actively misleading as sentiment input. Every row carries `kind`, `kind_confidence` and `kind_signals`, so you can raise the bar yourself instead of trusting a black box.

Fill rates that were corrected downward

An earlier version of the README quoted higher numbers measured on 30 businesses. At n=741 several came out lower — opening hours most of all, 57.4% rather than 77%. The published table is the corrected one. Anything not on it is not promised.

Cache metadata on every row

Rows can be served from a shared cache, which is why runs are fast and cheap. That is never hidden: `from_cache`, `fetched_at` and `data_age_hours` travel with every row, and `maxCacheAgeDays: 0` forces a fresh read.

Use cases

  • Build local business directories with verified contact details for a city or trade area.
  • Generate B2B lead lists for home services, dental, legal and other local categories.
  • Analyse neighbor sentiment about local providers using only the rows that are actually reviews.
  • Research a local market: income, average age, homeowner percentage and category coverage per city.
  • Monitor what businesses publish about themselves through the posts dataset.
  • Map a trade area rather than a municipality, using Nextdoor's distance-ordered directory on purpose.

Input

Every field has a default, and the defaults are deliberately small so a first run is cheap enough to inspect before you commit to a sweep. This table mirrors the Actor's own input schema field for field.

FieldDefaultWhat it does
citiesstring[]["san-clemente--ca"]CitiesNextdoor city slugs in the format `city-name--state`, lowercase, two-letter state.
categoriesstring[]["Dentist"]Business categoriesLeave empty to sweep every category a city exposes — Nextdoor publishes 54 per city. The per-city limit is split evenly between the categories you list, and whatever a small category cannot fill is handed to the others.
onlyRequestedCitybooleanfalseOnly businesses in the requested cityNextdoor's directory is regional, not municipal. With this on, filtering happens during discovery, so a dropped business is never charged and the Actor stops paging once the city is exhausted.
directBusinessUrlsstring[][]Business URLsScrape these business pages directly, in addition to whatever discovery finds.
maxBusinessesPerCityinteger50Max businesses per cityA per-city cap, shared evenly between categories. The default keeps a first run fast and cheap; raise it for a full sweep.
includeRecommendationsbooleantrueInclude neighbor recommendationsIndividual posts neighbors wrote about the business, with the author left exactly as Nextdoor anonymizes them, each classified by kind.
maxRecommendationsPerBusinessinteger100Max recommendations per businessMeasured over 741 businesses: 2.5 each on average, 33 the most seen on one, and 57.6% have none at all. Raising this rarely changes the result.
includeCityDatabooleantrueInclude city dataOne row per city in a separate `cities` dataset: population, average income and age, homeowner percentage, safety and friendliness scores, all 54 categories and up to 852 neighborhoods.
includeBusinessActivitybooleanfalseInclude business postsCorporate content the businesses published themselves. No neighbor personal data.
includeCityPostsbooleanfalseInclude public neighbor postspersonal dataContains personal data: a partial author name and free text, sometimes about local safety incidents. Off by default.
includeAuthorNeighborhoodbooleanfalseInclude the author's neighborhoodpersonal dataA partial name next to a precise neighborhood can identify a real person in a small community. Only applies if neighbor posts are enabled.
expandNearbyCitiesbooleanfalseExpand to nearby citiesDiscover neighbouring cities through Nextdoor's own cross-links, up to the hard cap below.
maxExpandedCitiesinteger3Cap on expanded citiesA hard cap, and not optional: Nextdoor's city graph connects the whole of the United States, so without a limit one run could keep going indefinitely.
maxConcurrencyinteger5Max concurrencyMeasured clean up to 5. At 10, Nextdoor returns HTTP 429 with a cooldown of about four minutes, which costs more time than the extra speed saves.
maxCacheAgeDaysinteger7Maximum acceptable data ageSet 0 to force a fresh fetch of everything. Every row reports which it was.
proxyConfigurationobject{ "useApifyProxy": false }ProxyOptional. The Actor already routes through US residential IPs, so nothing needs configuring here.

Output and fill rates

A field being in the schema is not the same as it having a value. The percentages below were counted on real runs; the sample sizes are in Measurements. Anything not listed here is not promised.

FieldFilledMeaning
namestringalwaysBusiness name as published.
slugstringalwaysNextdoor's own business slug.
categoriesstring[]84.2%Nextdoor business categories.
phone_numberstring93.9%E.164 phone number.
emailstring62.6%Published business email.
website_urlstring77.2%Business website.
address_fullstringalwaysStreet address, city, state and ZIP.
address_postal_codestringalwaysDerived by this Actor: Nextdoor exposes no ZIP field anywhere in its schema.
hide_addressbooleanalwaysTrue when the business set its address to private.
hours_open_statusstring57.4%Opening hours as Nextdoor reports them.
descriptionstring46.6%Business self-description.
recommendations_summarystring47.4%Nextdoor's own summary of what neighbors say.
gallery_urlsstring[]44.5%Image gallery.
recommendations_countintegeralwaysHow many recommendations exist. 0 for 57.6% of businesses.
neighbors_talking_countintegeralwaysNextdoor's engagement counter.
is_verifiedbooleanalwaysNextdoor verification status.
source_city_slugstringalwaysThe city slug this row was discovered under.
source_categorystringalwaysThe category this row was discovered under.
from_cachebooleanalwaysWhether this row came from the shared cache.
fetched_atdatetimealwaysWhen the data was actually read from Nextdoor.
data_age_hoursnumberalwaysHow old the data in this row is.
recommendationsobject[]alwaysNested rows, each with `kind`, `kind_confidence` and `kind_signals`.

Every key is always present. A field that exists but is empty comes back as explicit null, so a parser never has to guess.

Datasets

Different record types go to different datasets, so the main table never carries columns that are blank on most rows.

  • defaultOne row per business, with its recommendations nested inside.billed
  • citiesOne row per city: demographics, scores, category coverage, neighborhoods.billed
  • postsBusiness posts, and neighbor posts only if you opt in.billed
  • errorsAnything that failed, with the reason, for traceability.never billed

Pricing

Pay per delivered result. Charges are applied as each row is produced rather than in a lump at the end, so an aborted run bills only for what it actually gave you.

EventPriceNotes
actor-startActor start$0.00001Effectively free. A run that finds nothing costs you nothing.
businessBusiness$0.008One business with 34 fields. Error rows are never charged.
cityCity$0.008One city: demographics, scores, categories and neighborhoods.
recommendationRecommendation$0.002One neighbor recommendation, classified by kind.
postPost$0.001One public post.

Measurements

Each figure is shown with the method that produced it. A benchmark without a method is a marketing claim wearing a number's clothes.

Throughput

~3,300 businesses/hour

End-to-end on the Apify platform at the default concurrency of 5: 120 businesses plus 393 recommendations plus city data in 130 seconds, discovery included. The extraction stage alone runs at ~4,900/hour.

Classifier accuracy

95.6%

Hand-labelled validation set of neighbor recommendations.

Recommendation mix

50% service requests, 19% real reviews

891 recommendations across two real runs.

Recommendation coverage

42.4% of businesses have at least one

741 distinct businesses across 5 cities and 12 categories. Average 2.5 per business including zeros.

Directory locality

96-100% in-city for results 1-75, 0% past 76

Measured on san-clemente--ca asking for 200 dentists, counting per block of 25. San Clemente holds roughly 72 dentists; everything past that is the surrounding trade area.

Rate-limit ceiling

Concurrency 5 clean, 10 triggers a ~4 minute cooldown

Measured against Nextdoor's HTTP 429 response on the platform.

What it will not do

Stated plainly so you can judge fit before spending anything.

  • No logged-in content: no private groups, no member feeds, no direct messages.
  • No free-text business search. Nextdoor requires a login for that, so discovery runs through the public category directory: you find businesses by city and category, not by arbitrary keyword.
  • No star ratings, because Nextdoor recommendations do not have them.
  • No de-anonymized authors. Author names pass through exactly as Nextdoor publishes them and are never cross-referenced or resolved to real people.
  • No addresses for businesses that set theirs to private: every address field returns `null` with a warning, even though coordinates are visible in the page source.
  • United States only in this version.

Privacy

  • Business contact details are published by the businesses themselves, for the purpose of being contacted.
  • `includeCityPosts` is off by default: neighbor posts carry partial real names alongside a specific neighborhood and sometimes describe local safety incidents.
  • `includeAuthorNeighborhood` is a separate opt-in on top of that, because a partial name plus a precise neighborhood can identify a real person in a small community.
  • Removal requests: email privacy@actorstack.dev and the business or resident is added to an exclusion list for future runs.

See also the data removal process.

Frequently asked questions

Do I need a Nextdoor account or session cookies?
No. The Actor reads only what Nextdoor's servers serve to a signed-out visitor. There is no account, no session and no cookie jar, so there is nothing to go stale between runs. The trade-off is that it cannot reach anything behind Nextdoor's login.
Are Nextdoor recommendations the same as reviews?
No, and treating them as such is the most common mistake. Nextdoor calls them recommendations: they are free-text posts from neighbors with no star rating, and the author is anonymized to a first name and last initial. Measured across 891 of them, 50% were neighbors asking for a provider rather than reviewing one, which is why every row carries a `kind` field.
How much does a run cost?
Pay per result: $0.008 per business, $0.008 per city, $0.002 per recommendation, $0.001 per post, and $0.00001 to start. A default first run — 50 businesses in one city with recommendations and city data — costs under $0.50. Error rows are never charged.
Why does my run return businesses from other cities?
Because Nextdoor's category directory is ordered by distance and keeps going into neighbouring towns once the requested city runs out. Set `onlyRequestedCity: true` to filter during discovery, which also stops the Actor from paging into the wider region.
Can I search Nextdoor businesses by keyword?
No. Nextdoor requires a login for free-text business search, so discovery runs through the public category directory instead: you select a city and one or more of the 54 categories it exposes. You can also pass known business URLs directly through `directBusinessUrls`.
Which countries are supported?
The United States only in this version.
How fresh is the data?
Rows may come from a shared cache, and every row says so: `from_cache`, `fetched_at` and `data_age_hours` travel with the data. Set `maxCacheAgeDays: 0` to force a fresh fetch of everything.

Guides for this Actor