# Code Violation & Distressed Property Leads (`datapenguin/code-violation-leads`) Actor

Recent building and housing code violations from New York City, Chicago, Austin, Cincinnati, Seattle, San Francisco, New Orleans and Norfolk in one format. Filter by ZIP code, keyword and open status, group by property, or get only new violations on a schedule. Official city open data, no API key.

- **URL**: https://apify.com/datapenguin/code-violation-leads.md
- **Developed by:** [Data Penguin](https://apify.com/datapenguin) (community)
- **Categories:** Real estate, Lead generation
- **Stats:** 2 total users, 1 monthly users, 100.0% runs succeeded, 0 bookmarks
- **User rating**: No ratings yet

## Pricing

from $3.00 / 1,000 violation or properties

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

### Recent code violations and distressed property leads from city open data

Code Violation & Distressed Property Leads reads the violation files that New York City, Chicago, Austin, Cincinnati, Seattle, San Francisco, New Orleans and Norfolk, Virginia publish as open data and gives you the newest ones in a single format. Each row has the address, the date, what the inspector found, the status and, where the city publishes it, the severity, the penalty and the balance still owed. You can narrow the list by ZIP code and keyword, keep only open violations, combine everything at one address into a single property row, or ask for only the violations you have not seen before.

There is no account, API key or login to set up. Pick your cities and start the run.

Real estate investors and wholesalers use violation lists to find run-down buildings whose owners may want to sell. Contractors, roofers, exterminators and property managers use them to find buildings that need repairs now, and tenant groups and local reporters use them to keep an eye on problem landlords.

#### How to use it

1. Click **Try for free** and open the **Input** tab.
2. Choose your cities, then add a ZIP code or a keyword such as vacant or roof if you want a narrower list.
3. Click **Start**, then open the **Output** tab.

To get a fresh list every day, turn on **Only violations not seen before** and run it on a schedule. The Actor remembers what it already gave you for that exact set of filters.

#### Example inputs

Open violations in Brooklyn and Queens from the last 30 days that mention vacant buildings:

```json
{
    "sources": ["nyc-housing", "nyc-buildings"],
    "zipCodes": ["112", "113", "114"],
    "keywords": ["vacant"],
    "daysBack": 30,
    "maxItems": 100
}
```

The Chicago and Cincinnati properties with the most open violations in the last 60 days, one row per address:

```json
{
    "sources": ["chicago", "cincinnati"],
    "daysBack": 60,
    "groupByProperty": true,
    "maxItems": 50
}
```

Every new Austin case each day, for a scheduled run:

```json
{
    "sources": ["austin"],
    "daysBack": 7,
    "onlyNew": true,
    "maxItems": 500
}
```

#### What you get

For each violation: city, state, source, violation or case number, date, status, whether it is still open, violation type, the inspector's description, the code section, address, ZIP code, latitude and longitude. Depending on the city you also get the severity class, the penalty and the balance due, the hearing date and status, the apartment, the borough, the tax lot or parcel number, and a link to the city's record.

A shortened example:

```json
{
    "city": "New York City",
    "state": "NY",
    "sourceId": "nyc-buildings",
    "violationId": "39561157L",
    "violationDate": "2026-10-27",
    "status": "ACTIVE",
    "isOpen": true,
    "violationType": "Construction",
    "description": "AT THE TIME OF INSPECTION ON A NON ACTIVE JOB SITE , I OBSERVED A CONSTRUCTION FENCE AROUND PERIMETER OF SITE ...",
    "severity": "Class 2 (major)",
    "penaltyUsd": 1250,
    "balanceDueUsd": 1250,
    "hearingDate": "2027-01-05",
    "address": "80-11 90 AVENUE",
    "zip": "11421",
    "borough": "QUEENS",
    "parcelId": "4089650051"
}
```

With **One row per property** turned on, each row is an address with the number of violations, how many are open, the first and latest dates, the severities seen, the total balance due and a list of up to 20 of its violations.

#### Which city publishes what

| Source | Severity | Penalty and balance | ZIP code | Dataset |
| --- | --- | --- | --- | --- |
| New York City, housing (HPD) | Class A, B or C | No | Yes | Housing Maintenance Code Violations |
| New York City, buildings (DOB ECB) | Class 1, 2 or 3 | Yes | Yes | DOB ECB Violations |
| Chicago | No | No | No | Building Violations |
| Austin | Case priority | No | Yes | Austin Code Complaint Cases |
| Cincinnati | No | No | No | Code Enforcement |
| Seattle | No | No | Yes | Code Complaints and Violations |
| San Francisco | Marks unsafe buildings | No | Yes | DBI Notices of Violation |
| New Orleans | No (case stage and hearing dates instead) | No | Yes | Code Enforcement All Cases |
| Norfolk, VA | No (correction deadline instead) | No | No | Violations |

The DOB ECB file only gives the tax lot of the building, so the address and ZIP code come from the city's MapPLUTO property file. A few lots have no match and are left without an address. Chicago lists one row per violation, so one inspection can give several rows. Cincinnati's file covers trash, tall grass and abandoned vehicles as well as building cases, and Austin's mostly says the type of case (structure condition, property abatement, land use or work without a permit) rather than the details. Seattle's file mixes complaints (weeds, noise, landlord and tenant, vacant buildings) with notices of violation and citations; the type column says which. San Francisco's file has one row per item on a notice of violation, so one notice can give several rows with the same case number. New Orleans lists one row per case, with the stage it has reached (inspection, title research, hearing) and the next or last hearing date. Norfolk lists one row per violation, with the ordinance cited and the date the owner has to correct it by. The city notes that a listing only means a notice was issued, not that the city has judged the condition of the property.

#### Pricing

You pay per use. There is no monthly fee.

| What | Price |
| --- | --- |
| Each row returned (a violation, or a property when grouped) | $0.003 |
| Starting a run | $0.00005 |

Getting 500 violations costs $1.50, which is $3 per 1,000. A search that finds nothing costs only the start fee. Set **Maximum cost per run** in the run options, or use **Max results**, to cap what a single run can spend.

#### Questions

##### Do I need an account or key with the cities?

No. The Actor uses each city's public data portal.

##### Where does the data come from, and how fresh is it?

The NYC Department of Housing Preservation and Development, the NYC Department of Buildings, the City of Chicago, the City of Austin, the City of Cincinnati, the City of Seattle, the San Francisco Department of Building Inspection, the City of New Orleans and the City of Norfolk, through their open-data portals. The files update every day and usually run a day or two behind the city's own records.

##### Does a violation mean the property is distressed or for sale?

No. A violation means an inspector found a problem on that day. Many are fixed quickly, and some are on well-kept buildings. Repeated, serious and unpaid violations at one address are a stronger signal, which is what **One row per property** helps you see.

##### Why did I get fewer results than I asked for?

Usually the filters. A ZIP code or keyword narrows each city, and cities that do not publish ZIP codes are left out when you filter by ZIP. Very short date windows can also come back empty because the files run behind.

##### Something is wrong or missing. Where do I report it?

Open a thread in the **Issues** tab with the input you used and the violation number. I answer within a few days.

#### Good to know

Owner names, inspector names, phone numbers and mailing addresses are not included by default, because they are about private people and are not needed to find the property. The address is the address of the property. For New York City DOB violations you can turn on the respondent name, which is usually the owner or a company. Use it only if you have a lawful reason to.

This is an independent tool. It is not affiliated with, endorsed by or sponsored by any of the cities. Data can be incomplete or out of date, so confirm anything important with the city. This is not legal advice.

Chicago data: this site provides applications using data that has been modified for use from its original source, www.cityofchicago.org, the official website of the City of Chicago. The City of Chicago makes no claims as to the content, accuracy, timeliness, or completeness of any of the data provided at this site. The data provided at this site is subject to change at any time. It is understood that the data provided at this site is being used at one's own risk.

# Changelog

This Actor's version history is a separate document: https://apify.com/datapenguin/code-violation-leads/changelog.md

# Actor input Schema

## `sources` (type: `array`):

Which city files to search. Results are mixed evenly between the ones you pick. Leave empty for all nine.

## `daysBack` (type: `integer`):

Only violations issued or cases opened in this many days. City files run a day or more behind, so a window of 1 day can come back empty.

## `onlyOpen` (type: `boolean`):

Keep only violations the city still lists as open or active. Turn off to include ones that were fixed, dismissed or closed.

## `keywords` (type: `array`):

Match any of these words in the violation type, description or address, for example vacant, roof, unsafe or rodent. Not case sensitive. Leave empty for no keyword filter.

## `zipCodes` (type: `array`):

Start of a ZIP code, for example 112 for much of Brooklyn, 787 for Austin, 981 for Seattle, 941 for San Francisco or 701 for New Orleans. Chicago, Cincinnati and Norfolk do not publish ZIP codes, so they are left out when you use this.

## `groupByProperty` (type: `boolean`):

Combine violations at the same address into one row with a count, the first and latest dates and a list of the violations. Properties with the most violations come first. You are charged per row, so this gives fewer, fuller rows. It reads the whole date window, so long windows take longer.

## `includeRespondentNames` (type: `boolean`):

Add the respondent named on New York City DOB ECB violations, usually the owner or a company. Off by default because it can name private people. Turn it on only if you have a lawful reason to use it.

## `onlyNew` (type: `boolean`):

Skip violations that an earlier run with the same filters already delivered. Use this on a scheduled run to get just the new ones each time. Changing any filter starts a fresh list.

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

The most rows to return. You are charged per row, so this also caps what a run can cost.

## Actor input object example

```json
{
  "sources": [
    "nyc-housing",
    "nyc-buildings",
    "chicago",
    "austin",
    "cincinnati",
    "seattle",
    "san-francisco",
    "new-orleans",
    "norfolk"
  ],
  "daysBack": 14,
  "onlyOpen": true,
  "groupByProperty": false,
  "includeRespondentNames": false,
  "onlyNew": false,
  "maxItems": 25
}
```

# Actor output Schema

## `overview` (type: `string`):

No description

## `properties` (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 = {
    "daysBack": 14,
    "maxItems": 25
};

// Run the Actor and wait for it to finish
const run = await client.actor("datapenguin/code-violation-leads").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 = {
    "daysBack": 14,
    "maxItems": 25,
}

# Run the Actor and wait for it to finish
run = client.actor("datapenguin/code-violation-leads").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 '{
  "daysBack": 14,
  "maxItems": 25
}' |
apify call datapenguin/code-violation-leads --silent --output-dataset

```

## MCP server setup

```json
{
    "mcpServers": {
        "apify": {
            "type": "http",
            "url": "https://mcp.apify.com/?tools=fetch-actor-details,datapenguin/code-violation-leads"
        }
    }
}
```

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/KuXRDVF5QrkjqJ1W8/builds/kf9qodQ2PhHjR4vmn/openapi.json
