# 311 Complaints by District: Pain-Point & Spike Tracker (`clearfeedlabs/district-pain-point-tracker`) Actor

What residents complain about in each council district, ward or supervisor district, and what is spiking. Official 311 open data for NYC, San Francisco, Chicago or any Socrata city. Counts, change vs prior period, city comparison.

- **URL**: https://apify.com/clearfeedlabs/district-pain-point-tracker.md
- **Developed by:** [Clearfeed Labs](https://apify.com/clearfeedlabs) (community)
- **Categories:** Business, Lead generation, News
- **Stats:** 2 total users, 1 monthly users, 100.0% runs succeeded, 0 bookmarks
- **User rating**: No ratings yet

## Pricing

from $3.00 / 1,000 district issue rows

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

### 311 Complaints by District: Pain-Point & Spike Tracker

**District Pain-Point Tracker** answers *"what are people in this district actually upset about, and what's getting worse?"* It reads **official 311 service-request data** from city open-data portals and returns, for every council district / ward / supervisor district, the **top issues**, their **change vs. the previous period**, how each district compares with the **city average**, and a plain signal: `spiking`, `new-or-emerging`, `steady`, `easing`.

Built for **council members and campaign staff, constituent-services teams, local journalists, community boards and advocacy groups, civic-tech and urban researchers, local businesses (pest control, towing, contractors) looking for demand by area**.

- Cities built in: **New York City** (51 council districts), **San Francisco** (11 supervisor districts), **Chicago** (50 wards), plus **any Socrata 311 dataset** (custom mode).
- Filter by district and issue words (noise, rodent, pothole, graffiti, heat...).
- Current window vs. the same-length prior window, share of the district's requests, and ratio vs. the city average.
- **Add-on (off by default)**: week-by-week counts per row.
- Aggregates only: **no names, addresses or descriptions** of individual requests.

No login, no API key, no proxies: documented public Socrata APIs, at most one request per second per the portals' crawl-delay, with a robots.txt check before each run.

#### Why this one

| | District Pain-Point Tracker | Typical 311 scraper |
|---|---|---|
| Output | Ranked issues per district with trend and city comparison | Raw request rows you have to aggregate |
| Spike detection | `spiking` / `new-or-emerging` signals | None |
| Cost for a whole city | ~500 aggregate rows | Hundreds of thousands of raw rows |
| Privacy | Aggregates only | Often exports addresses and free text |
| Other cities | Any Socrata 311 dataset, robots-checked | Usually one city |

#### Pricing (pay per event)

| Event | Price | When |
|---|---|---|
| District issue row | **$0.003** | Each district + issue row returned |
| Weekly trend add-on | +$0.001 per row | Only if `addWeeklyTrend` is on |
| Actor start | $0.00005 | Apify's standard start event |

**Billing examples (no change-only mode; each run bills its rows):** first run, 1 city with 50 districts × top 3 issues = 150 rows = $0.45 (+$0.15 with weekly trend); re-running the next week bills its rows again ($0.45); a filter that matches no district-issue rows = start fee only.

**How that compares:** raw 311 scrapers on the Store cost ~$1–$5 per 1,000 *raw* requests, and a busy city produces 250,000+ requests a month, so summarising a month yourself can cost $250 or more before analysis. Here a **full NYC month (51 districts × top 10 issues) is about $1.50**. Set **Max charge per run** to cap any run.

#### Input examples

What's spiking in NYC this month:

```json
{ "city": "nyc", "sortBy": "spikes", "topIssuesPerDistrict": 10 }
```

Rodent and noise complaints in two Chicago wards, weekly:

```json
{ "city": "chicago", "districts": ["1", "27"], "issueContains": ["rodent", "rat", "noise"], "windowDays": 28, "addWeeklyTrend": true }
```

Custom city:

```json
{ "city": "custom", "customDomain": "data.example.gov", "customDatasetId": "abcd-1234", "customDistrictField": "council_district", "customIssueField": "request_type", "customDateField": "created_date" }
```

#### Output (one row)

`city`, `districtType`, `district`, `rank`, `issue`, `count`, `priorCount`, `changePct`, `signal`, `shareOfDistrictPct`, `vsCityAverage` (1.0 = average district), `districtTotal`, `windowStart`, `windowEnd`, `priorWindowStart`, `source`, plus `weeklyTrend[]` with the add-on.

#### Notes

- Windows end at midnight UTC today; the last few days can still be filling in, and the last week in `weeklyTrend` may be partial.
- 311 counts measure **reports**, not problems: they reflect who reports, how easy reporting is, and campaigns or outreach, as well as real conditions.
- Chicago's portal is slower; runs there can take a minute or two.

#### Data sources and legal notes

- **NYC Open Data** (311 Service Requests, erm2-nwe9), **DataSF** (311 Cases, vw6y-z8j6), **Chicago Data Portal** (311 Service Requests, v6vf-nfxy), and any custom Socrata domain you choose: public data under each city's open-data terms, read through the documented SODA API. robots.txt is checked every run and the run stops, without charge, if the API path is disallowed.
- Not affiliated with or endorsed by any city.

#### Disclaimer

Data is provided **as is** from city systems, which can be delayed, recoded or corrected. This is **not legal, political or professional advice**, and counts shouldn't be presented as verified conditions without checking the linked source. Don't use the output to target or harass individuals.

#### Support

Found a problem or want another city built in? Open an issue on this Actor's **Issues** tab. More Clearfeed Labs data feeds: [clearfeedlabs.com](https://clearfeedlabs.com).

#### Geography, unassigned requests and small counts

- `geographyType` says what a district is: `council-district` (NYC), `supervisor-district` (SF), `ward` (Chicago) or `custom-district-field`. These aren't interchangeable across cities.
- `unassignedRequestsInWindow` counts requests in the window with no usable district (blank, 0 or "unspecified"), across all issue types. They're excluded from every district row.
- `lowCountCaution: true` marks rows with fewer than 10 requests, or a prior count under 5, where `changePct` swings wildly on a few requests. `spiking` already requires at least 10 more requests than the prior period.
- Complaint volume reflects who reports, not necessarily how common a problem is.

### Related Clearfeed Labs Actors

- [Congress Voting Record Tracker: Votes, Bills & Cited Flags](https://apify.com/clearfeedlabs/legislator-record-tracker): U.S. House roll-call voting records
- [Local Business Leads Finder: Emails & Phones, No Google](https://apify.com/clearfeedlabs/local-business-leads): local business leads with phones and websites
- [Political Ad Spend Tracker: Google Election Ads Spend & Surges](https://apify.com/clearfeedlabs/political-ad-spend-tracker): political ad spend and surges
- [All Clearfeed Labs Actors](https://apify.com/clearfeedlabs)

# Actor input Schema

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

Which city's official 311 data to analyse.

## `districts` (type: `array`):

Only these districts/wards, e.g. 33 or 3. Leave empty for all.

## `issueContains` (type: `array`):

Only complaint types containing these words, e.g. noise, rodent, pothole, graffiti.

## `windowDays` (type: `integer`):

Current period length. It's compared with the same-length period just before it.

## `topIssuesPerDistrict` (type: `integer`):

How many issue types to return per district.

## `minCount` (type: `integer`):

Skip issue types with fewer requests in the current window.

## `sortBy` (type: `string`):

Order of rows.

## `maxItems` (type: `integer`):

Each row (district + issue) is charged.

## `addWeeklyTrend` (type: `boolean`):

Week-by-week request counts for each district issue in the current window.

## `customDomain` (type: `string`):

e.g. data.austintexas.gov. The Actor checks the domain's robots.txt first.

## `customDatasetId` (type: `string`):

Socrata 4x4 ID, e.g. xwdj-i9he.

## `customDistrictField` (type: `string`):

API column name for district/ward.

## `customIssueField` (type: `string`):

API column name for request/complaint type.

## `customDateField` (type: `string`):

API column name for the request's created date.

## Actor input object example

```json
{
  "city": "nyc",
  "windowDays": 30,
  "topIssuesPerDistrict": 10,
  "minCount": 5,
  "sortBy": "district",
  "maxItems": 500,
  "addWeeklyTrend": false
}
```

# Actor output Schema

## `results` (type: `string`):

No description

## `summary` (type: `string`):

No description

# 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 = {};

// Run the Actor and wait for it to finish
const run = await client.actor("clearfeedlabs/district-pain-point-tracker").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 = {}

# Run the Actor and wait for it to finish
run = client.actor("clearfeedlabs/district-pain-point-tracker").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 '{}' |
apify call clearfeedlabs/district-pain-point-tracker --silent --output-dataset

```

## MCP server setup

```json
{
    "mcpServers": {
        "apify": {
            "type": "http",
            "url": "https://mcp.apify.com/?tools=fetch-actor-details,clearfeedlabs/district-pain-point-tracker"
        }
    }
}
```

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/HF3AKKkWRFf5Ac2O1/builds/ukRlX5G7xWJJEVMo9/openapi.json
