# Nextdoor Scraper (`alizarin_refrigerator-owner/nextdoor-scraper`) Actor

Scrape local business recommendations, neighborhood posts, and community data from Nextdoor. Get authentic local insights and recommendations that aren't available on other platforms.

- **URL**: https://apify.com/alizarin_refrigerator-owner/nextdoor-scraper.md
- **Developed by:** [The Howlers](https://apify.com/alizarin_refrigerator-owner) (community)
- **Categories:** Developer tools, Social media, Lead generation
- **Stats:** 232 total users, 12 monthly users, 91.7% runs succeeded, 10 bookmarks
- **User rating**: 1.00 out of 5 stars

## Pricing

from $0.01 / 1,000 results

This Actor is paid per event. You are not charged for the Apify platform usage, but only a fixed price for specific events.

Learn more: https://docs.apify.com/actors/running/actors-in-store.md#pay-per-event

## What's an Apify Actor?

An Actor is a serverless cloud program that runs on the Apify platform. It has two run modes.
In Batch mode, an Actor accepts a well-defined JSON input, performs an action which can take anything from a few seconds to a few hours,
and optionally produces a well-defined JSON output, datasets with results, or files in key-value store.
In Standby mode, an Actor provides a web server which can be used as a website, API, or an MCP server.

Apify vocabulary and the platform model are defined once, in the agent quickstart at https://apify.com/agents.md.

## How to integrate an Actor?

If asked about integration, you help developers integrate Actors into their projects.
You adapt to their stack and deliver integrations that are safe, well-documented, and production-ready.

Do not guess an integration path. Every one of them is in the agent quickstart at https://apify.com/agents.md: the Apify MCP server, Agent Skills with the Apify CLI, the JavaScript and Python clients, the REST API, and the account-free path for an agent with no human to sign in. It also carries the rule on stating cost before the first paid run.

For examples already wired to this Actor's own input schema, see the [API](#api) section below.

Each client library has reference documentation the quickstart does not restate: [JavaScript/TypeScript](https://docs.apify.com/api/client/js/docs.md) (`npm install apify-client`) and [Python](https://docs.apify.com/api/client/python/docs.md) (`pip install apify-client`).

# README

## Nextdoor Business Profile Scraper

Scrape Nextdoor business profiles, recommendations, reviews, and neighborhood posts. Extract business name, address, phone, recommendation count, reviews, and category.

### Read this first: how Nextdoor scraping actually works

Nextdoor now shows a login wall on most public pages. That means the only reliable way to get real data is to give the actor your own Nextdoor session cookies. The actor has three modes, in order of how well they work:

1. **Session cookies (Mode 3): RECOMMENDED.** You paste your Nextdoor login cookies. This unlocks recommendations, posts, business listings, and events. This is the mode that works.
2. **Public /pages/ URLs (Mode 1): best-effort, not recommended.** Scrapes public business pages with no login. It is easily blocked and often returns nothing, because Nextdoor login-walls public pages.
3. **Google discovery (Mode 2): best-effort, not recommended.** Searches Google to find Nextdoor pages, then scrapes them. Same limitation as Mode 1.

If you just want it to work, use Mode 3. Modes 1 and 2 are kept for the occasional page that is still public, but do not rely on them.

There is also a **Demo Mode** that returns fake sample data (for example "Mike's Plumbing") so you can see the output shape without any credentials. Demo Mode is OFF by default. It never returns real Nextdoor data.

***

### Quick start (Mode 3, recommended)

#### Step 1: Export your Nextdoor cookies

1. Install the free **Cookie-Editor** browser extension (Chrome, Edge, or Firefox).
2. Open **nextdoor.com** in that browser and make sure you are **logged in**.
3. Click the Cookie-Editor icon while you are on the Nextdoor tab.
4. Click **Export** (bottom of the Cookie-Editor panel), then choose **JSON**. This copies a JSON array of cookies to your clipboard.

#### Step 2: Run the actor

Paste that JSON array into `sessionCookies` and set the neighborhoods you want:

```json
{
  "sessionCookies": "[{\"name\":\"...\",\"value\":\"...\",\"domain\":\".nextdoor.com\"}]",
  "neighborhoods": ["miami-beach-fl"],
  "scrapeType": "recommendations",
  "maxResults": 100,
  "proxyConfiguration": { "useApifyProxy": true, "apifyProxyGroups": ["RESIDENTIAL"] }
}
```

That is the whole setup. `scrapeType` can be `recommendations`, `posts`, `businesses`, or `events`.

**Where do I find the neighborhood slug?** Open any neighborhood on Nextdoor and look at the URL: `nextdoor.com/neighborhood/SLUG/`. The `SLUG` part (for example `miami-beach-fl`) is what you put in `neighborhoods`.

**Cookies expire.** When they do, you will get a clear "login wall" message. Just re-export from Cookie-Editor (Step 1) and run again. To avoid re-pasting, see "Auto-refresh" below.

#### Try Demo Mode first (optional, free, no cookies)

Want to see the output format before setting up cookies? Turn Demo Mode on:

```json
{ "demoMode": true, "maxResults": 5 }
```

This returns fake sample businesses so you can wire up your workflow. Remember to turn it off and add cookies to get real data.

***

### Modes 1 and 2 (no auth, best-effort only)

These do not require cookies but are easily blocked. Use them only if Mode 3 is not an option and accept that they often return nothing.

**Mode 1, direct public URLs:**

```json
{ "businessPageUrls": ["https://nextdoor.com/pages/motz-plumbing-north-miami-fl/"] }
```

**Mode 2, Google discovery:**

```json
{ "searchTerms": ["plumber", "electrician"], "city": "Miami, FL" }
```

***

### Auto-refresh (optional, hands-off sessions)

If you run this on a schedule, you can let it re-login automatically when the session expires, using the companion **Cookie Manager** actor. Capture your cookies once with Cookie Manager (it stores them under a key), then:

```json
{
  "cookieStorageKey": "nextdoor-yourname",
  "neighborhoods": ["miami-beach-fl"],
  "scrapeType": "posts",
  "autoRefreshCookies": true,
  "refreshEmail": "you@example.com",
  "refreshPassword": "your-nextdoor-password",
  "proxyConfiguration": { "useApifyProxy": true, "apifyProxyGroups": ["RESIDENTIAL"] }
}
```

When a run hits a login wall, the actor calls Cookie Manager in refresh mode, logs back in, rewrites the shared cookies, and continues. `refreshPassword` is stored encrypted.

***

### Continuous monitoring (new-leads-only)

For live home-services lead monitoring, run on a schedule in `posts` mode with `onlyNewSince` enabled:

```json
{
  "cookieStorageKey": "nextdoor-yourname",
  "neighborhoods": ["your-neighborhood-1", "your-neighborhood-2"],
  "scrapeType": "posts",
  "searchQuery": "plumber",
  "onlyNewSince": true,
  "maxNeighborhoodsPerRun": 5,
  "autoRefreshCookies": true,
  "refreshEmail": "you@example.com",
  "refreshPassword": "your-nextdoor-password",
  "proxyConfiguration": { "useApifyProxy": true, "apifyProxyGroups": ["RESIDENTIAL"] },
  "webhookUrl": "https://hooks.your-crm.com/nextdoor-leads"
}
```

How it works:

- **Only new posts.** The actor remembers each post's stable ID and the newest post timestamp per neighborhood in a named Key-Value Store (`seenStateKvStoreName`). The first run seeds the baseline and emits everything. Every run after that emits only posts that appeared since the last run, so scheduled runs surface fresh leads instead of re-sending the whole feed.
- **Rich post fields.** Each emitted post includes `postId`, `postUrl`, `title`, `content`, `author`, `neighborhood`, `date`, `upvotes`, `commentCount`, and `businessMentions`, ready to route into a CRM or webhook.
- **Human-like pacing.** Requests are serialized with a jittered delay, and `maxNeighborhoodsPerRun` caps each run's footprint.
- **Session self-healing.** With `autoRefreshCookies` on, an expired session is re-logged-in via the Cookie Manager actor and the run continues.
- **Residential IPs.** Authenticated mode defaults to a RESIDENTIAL proxy group when Apify proxy is enabled without an explicit group. Datacenter IPs get login-walled quickly on neighborhood feeds.

***

### Input parameters

| Parameter | Type | Default | Description |
|-----------|------|---------|-------------|
| `sessionCookies` | string | - | RECOMMENDED. JSON array of Nextdoor cookies exported from the Cookie-Editor extension. Unlocks recommendations, posts, businesses, and events. Pair with `neighborhoods`. |
| `neighborhoods` | array | - | Neighborhood slugs to scrape in authenticated mode. Required with `sessionCookies`. Find the slug in `nextdoor.com/neighborhood/SLUG/`. |
| `scrapeType` | string | `recommendations` | Authenticated content type: `recommendations`, `posts`, `businesses`, or `events`. |
| `cookieStorageKey` | string | - | Optional. Load cookies automatically from the Cookie Manager actor's Key-Value Store instead of pasting them. |
| `cookieKvStoreName` | string | `cookie-sessions` | KV Store name Cookie Manager saves to. Only change if you customized it. |
| `autoRefreshCookies` | boolean | `false` | On login wall, call Cookie Manager to re-login and continue. Requires `cookieStorageKey`, `refreshEmail`, `refreshPassword`. |
| `cookieManagerActorId` | string | `cookie-manager` | Actor to call for refresh. Use a username-scoped ID if renamed. |
| `refreshEmail` | string | - | Nextdoor email, used only for auto-refresh. |
| `refreshPassword` | string | - | Nextdoor password (stored encrypted), used only for auto-refresh. |
| `businessPageUrls` | array | - | Mode 1, best-effort. Direct `/pages/` URLs to scrape with no login. Often blocked. |
| `searchTerms` | array | - | Mode 2, best-effort. Business types to find via Google. Requires `city`. Often blocked. |
| `city` | string | - | City and state for Google discovery (for example `Miami, FL`). Required with `searchTerms`. |
| `searchQuery` | string | - | Filter results by keyword. Applied to all modes. |
| `category` | string | `all` | Filter by business category (authenticated mode). |
| `maxResults` | integer | `100` | Maximum items to return. |
| `onlyNewSince` | boolean | `false` | Continuous-monitoring dedup. Emits only posts new since the previous run. First run seeds the baseline. |
| `seenStateKvStoreName` | string | `nextdoor-monitor-state` | KV Store holding the per-neighborhood high-water mark for `onlyNewSince`. Keep stable across runs. |
| `maxNeighborhoodsPerRun` | integer | `0` | Cap neighborhoods per run (0 = no cap). |
| `includeComments` | boolean | `false` | Extract comments and replies on posts (slower). |
| `minRecommendations` | integer | `0` | Only include businesses with at least this many recommendations. |
| `proxyConfiguration` | object | - | Proxy settings. RESIDENTIAL is recommended and defaults on for authenticated scraping. |
| `demoMode` | boolean | `false` | Returns fake sample data for testing your integration. Not real Nextdoor data. Leave off and use cookies for real results. |
| `webhookUrl` | string | - | POST results here when scraping completes (Zapier, Make, n8n, custom). |

***

### Pricing

Pay-per-event billing:

| Event | Description | Price |
|-------|-------------|-------|
| Business Scraped | Each Nextdoor business profile scraped | $0.06 |

Demo Mode is free. Runs that return zero real results are not charged.

***

### Troubleshooting

#### "Nextdoor blocked authenticated scraping with a login wall"

Your session cookies are expired, or they were captured while you were logged out of Nextdoor. Fix: log into nextdoor.com in your browser, re-export cookies with the Cookie-Editor extension (choose JSON), and paste them into `sessionCookies`. To recover automatically on expiry, set `autoRefreshCookies` with `refreshEmail` and `refreshPassword`.

#### "Cookies were rejected before we could log in"

The value in `sessionCookies` was not a valid JSON array. It must be the full array from Cookie-Editor. In Cookie-Editor, click Export, choose JSON, and paste the entire thing (it starts with `[` and ends with `]`). Do not paste a single cookie or a screenshot.

#### "0 results" on a no-auth run

You used Mode 1 (`businessPageUrls`) or Mode 2 (`searchTerms`) with no cookies. Nextdoor login-walls most public pages, so these modes often return nothing. Switch to Mode 3: add `sessionCookies` and `neighborhoods`.

#### "Google discovery found no Nextdoor pages"

Mode 2 is best-effort and frequently returns nothing. Use Mode 3 (session cookies) for reliable results, or provide direct `/pages/` URLs in `businessPageUrls`.

#### "No NEW posts since the last run"

This is not an error. With `onlyNewSince` on, the session is healthy and nothing new was posted in the monitored neighborhoods since the previous run.

#### I do not have a Nextdoor account

Modes 1 and 2 do not need one, but they are unreliable. For dependable data you need an account so you can export session cookies. A free Nextdoor account is enough.

#### How do I test without cookies?

Set `demoMode` to true. It returns realistic fake sample data so you can verify the output format, then turn it off and add cookies for real data.

***

**Built by John Rippy | [Actor Arsenal](https://actorarsenal.com)**

# Actor input Schema

## `sessionCookies` (type: `string`):

Your Nextdoor session cookies as a JSON array. This is the path that reliably returns real data. How to get it: (1) install the free Cookie-Editor browser extension, (2) log into nextdoor.com in that browser, (3) open Cookie-Editor on the Nextdoor tab, click Export, choose 'JSON', (4) paste the whole array here. Pair with the neighborhoods field below. Unlocks recommendations, posts, businesses, and events. Cookies expire, so re-export if you see a login-wall error. Also accepted: the Cookie header string (name=value; name2=value2) or a cookies.txt file.

## `neighborhoods` (type: `array`):

Neighborhood slugs to scrape in authenticated mode. Required with sessionCookies. Example: 'miami-beach-fl'. Find the slug in any Nextdoor URL: nextdoor.com/neighborhood/SLUG/

## `scrapeType` (type: `string`):

What to scrape in authenticated mode. Only used with sessionCookies.

## `cookieStorageKey` (type: `string`):

Key-Value Store key from the Cookie Manager actor (e.g. 'nextdoor-john'). When set, cookies load automatically from the shared KV store, so you do not have to paste sessionCookies by hand. Run the Cookie Manager actor first to capture and store your cookies.

## `cookieKvStoreName` (type: `string`):

Name of the Key-Value Store where Cookie Manager saves sessions. Default: 'cookie-sessions'. Only change this if you set a custom store name in Cookie Manager.

## `autoRefreshCookies` (type: `boolean`):

When the Nextdoor session hits a login wall, automatically call the Cookie Manager actor in refresh mode to log back in and continue. Requires cookieStorageKey plus refreshEmail and refreshPassword below.

## `cookieManagerActorId` (type: `string`):

Actor to call for session refresh. Default: 'cookie-manager'. Use your own username-scoped ID if you renamed it (e.g. 'yourname/cookie-manager').

## `refreshEmail` (type: `string`):

Nextdoor account email, used only when auto-refreshing an expired session via the Cookie Manager actor.

## `refreshPassword` (type: `string`):

Nextdoor account password, used only when auto-refreshing an expired session via the Cookie Manager actor. Stored encrypted.

## `businessPageUrls` (type: `array`):

Direct Nextdoor /pages/ URLs to scrape without logging in. Best-effort only: Nextdoor now login-walls most public pages, so this often returns nothing. Use Mode 3 (session cookies) for reliable results. Example: https://nextdoor.com/pages/motz-plumbing-north-miami-fl/

## `searchTerms` (type: `array`):

Business types to look up via Google (e.g. 'plumber', 'electrician'). Requires the city field. Discovers /pages/ URLs, then scrapes them. Best-effort only and often returns nothing. Use Mode 3 (session cookies) for reliable results.

## `city` (type: `string`):

City and state for Google discovery (e.g. 'Miami, FL', 'Austin, TX'). Required when using searchTerms.

## `searchQuery` (type: `string`):

Filter results by keyword (e.g. 'plumber', 'pizza'). Applied to all modes.

## `category` (type: `string`):

Filter by business category (authenticated mode).

## `maxResults` (type: `integer`):

Maximum number of items to return (default: 100).

## `onlyNewSince` (type: `boolean`):

For continuous monitoring (authenticated posts/events mode). Remembers post IDs and the newest timestamp per neighborhood between runs, so each scheduled run emits only posts that appeared since the previous run. The first run emits everything and seeds the baseline.

## `seenStateKvStoreName` (type: `string`):

Named Key-Value Store that holds the per-neighborhood high-water mark used by 'Only new posts since last run'. Default: 'nextdoor-monitor-state'. Keep this stable across scheduled runs so dedup persists.

## `maxNeighborhoodsPerRun` (type: `integer`):

Cap how many neighborhoods are scanned in a single run (0 = no cap). Keeps each scheduled run light when monitoring many neighborhoods.

## `includeComments` (type: `boolean`):

Extract comments and replies on posts (authenticated mode, slower).

## `minRecommendations` (type: `integer`):

Only include businesses with at least this many recommendations.

## `proxyConfiguration` (type: `object`):

Proxy settings. RESIDENTIAL is recommended for Nextdoor and is the default for authenticated scraping.

## `demoMode` (type: `boolean`):

Off by default. When ON, the actor returns fake sample businesses (e.g. 'Mike's Plumbing') so you can test your integration wiring without real credentials. It does NOT return real Nextdoor data. Leave this OFF and provide session cookies (Mode 3) to scrape real data.

## `webhookUrl` (type: `string`):

URL to POST results to when scraping completes (Zapier, Make, n8n, or a custom endpoint).

## Actor input object example

```json
{
  "neighborhoods": [
    "miami-beach-fl"
  ],
  "scrapeType": "recommendations",
  "cookieKvStoreName": "cookie-sessions",
  "autoRefreshCookies": false,
  "cookieManagerActorId": "cookie-manager",
  "category": "all",
  "maxResults": 100,
  "onlyNewSince": false,
  "seenStateKvStoreName": "nextdoor-monitor-state",
  "maxNeighborhoodsPerRun": 0,
  "includeComments": false,
  "minRecommendations": 0,
  "proxyConfiguration": {
    "useApifyProxy": true,
    "apifyProxyGroups": [
      "RESIDENTIAL"
    ]
  },
  "demoMode": false
}
```

# API

You can run this Actor programmatically using our API. Below are code examples in JavaScript, Python, and CLI, as well as the OpenAPI specification and MCP server setup.

## JavaScript example

```javascript
import { ApifyClient } from 'apify-client';

// Initialize the ApifyClient with your Apify API token
// Replace the '<YOUR_API_TOKEN>' with your token
const client = new ApifyClient({
    token: '<YOUR_API_TOKEN>',
});

// Prepare Actor input
const input = {
    "neighborhoods": [
        "miami-beach-fl"
    ],
    "proxyConfiguration": {
        "useApifyProxy": true,
        "apifyProxyGroups": [
            "RESIDENTIAL"
        ]
    },
    "demoMode": false
};

// Run the Actor and wait for it to finish
const run = await client.actor("alizarin_refrigerator-owner/nextdoor-scraper").call(input);

// Fetch and print Actor results from the run's dataset (if any)
console.log('Results from dataset');
console.log(`💾 Check your data here: https://console.apify.com/storage/datasets/${run.defaultDatasetId}`);
const { items } = await client.dataset(run.defaultDatasetId).listItems();
items.forEach((item) => {
    console.dir(item);
});

// 📚 Want to learn more 📖? Go to → https://docs.apify.com/api/client/js/docs

```

## Python example

```python
from apify_client import ApifyClient

# Initialize the ApifyClient with your Apify API token
# Replace '<YOUR_API_TOKEN>' with your token.
client = ApifyClient("<YOUR_API_TOKEN>")

# Prepare the Actor input
run_input = {
    "neighborhoods": ["miami-beach-fl"],
    "proxyConfiguration": {
        "useApifyProxy": True,
        "apifyProxyGroups": ["RESIDENTIAL"],
    },
    "demoMode": False,
}

# Run the Actor and wait for it to finish
run = client.actor("alizarin_refrigerator-owner/nextdoor-scraper").call(run_input=run_input)

# Fetch and print Actor results from the run's dataset (if there are any)
print(f"💾 Check your data here: https://console.apify.com/storage/datasets/{run.default_dataset_id}")
for item in client.dataset(run.default_dataset_id).iterate_items():
    print(item)

# 📚 Want to learn more 📖? Go to → https://docs.apify.com/api/client/python/docs/quick-start

```

## CLI example

```bash
echo '{
  "neighborhoods": [
    "miami-beach-fl"
  ],
  "proxyConfiguration": {
    "useApifyProxy": true,
    "apifyProxyGroups": [
      "RESIDENTIAL"
    ]
  },
  "demoMode": false
}' |
apify call alizarin_refrigerator-owner/nextdoor-scraper --silent --output-dataset

```

## MCP server setup

```json
{
    "mcpServers": {
        "apify": {
            "type": "http",
            "url": "https://mcp.apify.com/?tools=fetch-actor-details,alizarin_refrigerator-owner/nextdoor-scraper"
        }
    }
}
```

The hosted server signs you in with OAuth on first connect, so no API token belongs in this config. Clients without OAuth support can send an `Authorization: Bearer <APIFY_API_TOKEN>` header instead, using a token from API & Integrations in Apify Console (https://console.apify.com/settings/integrations).

## OpenAPI specification

Download the OpenAPI definition: https://api.apify.com/v2/actors/QDCRHEWLxbrvStt8z/builds/k4yejEFE2vrptt6py/openapi.json
