If you scrape Nextdoor's recommendation feed and count the rows as reviews, your numbers will be roughly five times too high and your sentiment will point the wrong way. This is not a subtle bias — it is a measured 50/19 split — and it comes from the feed mixing three different kinds of post that are almost impossible to tell apart with a keyword filter.
Three different posts that look identical
Nextdoor calls the feed recommendations. What actually appears in it:
kind | What it is |
|---|---|
recommendation | Actual praise or criticism of a business. |
service_request | Somebody looking for a provider, not reviewing one. |
thanks | An acknowledgement with no substance about the business. |
unknown | Below the confidence threshold — flagged rather than guessed. |
The reason a keyword filter does not separate them is that they share vocabulary. “Great plumber, fixed it same day” and “Looking for a great plumber, anyone?” overlap almost completely on tokens, and both are positive in tone. What differs is the grammatical stance — whether the writer is reporting a completed service or requesting one — and that is a classification problem, not a matching problem.
What that does to a sentiment model
Two ways, and the second is the one that survives review unnoticed.
Volume inflation. A business with three real reviews and twelve service requests naming it looks like a business with fifteen reviews. Any “most reviewed provider” ranking built on raw counts is really a ranking of how often a category's name gets typed into a request.
Sentiment inversion. Service requests are usually written by somebody whose current provider just failed them — “need a new dentist, mine cancelled again”. A model reads that as negative and attributes it to whichever business is mentioned, which may be the one the writer is about to hire. The polarity is not just noisy, it is pointed at the wrong entity.
The measured mix
Across 891 recommendations from two real runs:
- 50% came back
service_request. - 19% were actual recommendations.
- The remainder were thanks, or below the confidence threshold and flagged as unknown.
Half the feed is people asking for a provider. That single number is the reason the classifier exists rather than a post-processing filter.
How the classification works
Each row carries three fields instead of one label: kind, kind_confidence and kind_signals. The signals are the features that drove the decision — the presence of a completed-service reference, praise vocabulary, an interrogative stance — so you can see why a row was labelled the way it was.
Accuracy is 95.6% on a hand-labelled validation set. That figure is this project's own measurement rather than an independent audit, which is exactly why the confidence score ships with every row: you can raise the threshold, or discard unknown entirely, and arrive at a stricter dataset without asking anybody to trust a number.
{
"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",
"sentiment_hint": "positive",
"char_count": 66
}Coverage: most businesses have none
Measured over the same 741 businesses:
- 42.4% have at least one recommendation.
- 2.5 is the average per business, counting the zeros.
- 33 was the most seen on a single business.
So more than half of any local category has nothing written about it at all. Those businesses are still returned, with recommendations_count: 0, which keeps your row count predictable — but it means any analysis restricted to businesses with reviews is working with two fifths of the market and should say so.
Using recommendations responsibly
Three rules that follow directly from the numbers:
- Filter to
kind === "recommendation"before computing anything, and report how many rows that removed. - Keep the service requests. They are poor review data and excellent demand data: a category with many requests and few providers is a market signal.
- Never present an average as a rating. There is no numeric scale underneath it — a mean of free-text sentiment scores is your model's output, not Nextdoor's.
If you need star ratings, this is the wrong dataset
Nextdoor recommendations have no numeric rating, and the author is anonymized to a first name and last initial by Nextdoor itself. If your product needs a 1–5 score per business, this source cannot supply one and any tool that appears to is generating it.
What you get instead is what people actually wrote, which for local-market research is usually the more useful half. The Actor documentation lists every field on the recommendation row, and the business field reference covers what sits alongside them.



