# Building Permit Properties and Details Scraper (`realestateapi/building-permit-properties-and-details-scraper`) Actor

Normalize public Socrata building permits into structured permit, work, fee, property-location, and contact records, with transparent lead scoring. Supports Chicago by default and follows no redirects.

- **URL**: https://apify.com/realestateapi/building-permit-properties-and-details-scraper.md
- **Developed by:** [Real Estate API](https://apify.com/realestateapi) (community)
- **Stats:** 2 total users, 1 monthly users, 100.0% runs succeeded, 0 bookmarks
- **User rating**: No ratings yet

## Pricing

from $3.99 / 1,000 results

This Actor is paid per event and usage. You are charged both the fixed price for specific events and for Apify platform usage.

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

### What does Building Permit Properties and Details Scraper do?

This Actor reads public building-permit rows from HTTPS Socrata resource endpoints and normalizes permit, work, fee, property-location, and contact fields when the source provides them. It defaults to the City of Chicago's [Building Permits dataset](https://data.cityofchicago.org/Buildings/Building-Permits/ydr8-5enu), whose portal documents 116 columns. It does not invent missing contact details or property attributes.

### Why use this Actor?

Use the structured records to review public permit activity, project descriptions, reported costs, fees, and geographic fields. Output preserves flat fields for existing integrations and adds nested permit, property, work, fee, and contact objects. Each record includes its dataset provenance and a lead score based only on available values. This is a bounded, single-request data reader: it does not crawl detail pages or contact permit applicants.

### What data can it extract?

| Group | Fields when present |
| --- | --- |
| Permit | Source row ID, permit number, type, status, milestone, review type, application and issue dates, processing time |
| Work | Work type, description, permit conditions |
| Property | Street components, city/state context, ZIP, PIN, community area, census tract, ward, coordinates |
| Fees | Reported project cost, paid/unpaid/waived fees, fee subtotals and total |
| Contacts | Up to 15 source contact slots with role and public name/location fields; phone/email only if the selected source supplies them |
| Provenance and score | Dataset URL, source host, score, and HOT/WARM/COLD temperature |

Fields stay absent when a source row does not provide them. The Chicago dataset's location is associated with Chicago, Illinois; its permit rows do not have separate city/state columns. Its published columns provide contact role/name/city/state/ZIP, not phone or email.

### How to scrape Chicago building permits

1. Open the Actor's **Input** tab and keep the default Chicago endpoint, or enter another public Socrata resource endpoint.
2. Add a keyword such as `ROOF` if you want to search the dataset's searchable fields.
3. Set the maximum number of records and request timeout, then start the Actor.
4. Review the **Dataset** output. Download it as JSON, CSV, Excel, or another available format.

### How much does a run cost?

Apify charges depend on your platform plan and the resources used by the run. This Actor makes one bounded dataset request, so the selected item limit and response size affect runtime and memory. Review the run's usage in Apify Console; this Actor does not promise a fixed price.

### Input

See the input tab for the complete configuration. Example:

```json
{
  "datasetUrl": "https://data.cityofchicago.org/resource/ydr8-5enu.json",
  "search": "ROOF",
  "maxItems": 100,
  "requestTimeoutSeconds": 45
}
```

`datasetUrl` must be an HTTPS `/resource/<dataset-id>.json` endpoint on a `data.*` or `*.socrata.com` host. `search` is optional and limited to 200 characters. `maxItems` defaults to 100 and is bounded from 1 to 1,000. `requestTimeoutSeconds` defaults to 45 and is bounded from 5 to 120. Optional `city` and `state` filters are applied only when the selected source has corresponding permit-level fields. They cannot filter Chicago rows because those columns are absent. Redirects are not followed. Failed runs do not create dataset records.

### Output

You can download the dataset in various formats such as JSON, HTML, CSV, or Excel.

Example based on a row visible in the City of Chicago dataset:

```json
{
  "recordType": "permit_lead",
  "recordId": "permit:100123862",
  "sourceRecordId": "1697816",
  "permitId": "100123862",
  "permitType": "PERMIT - EASY PERMIT PROCESS",
  "applicationDate": "2006-07-12T00:00:00.000Z",
  "issueDate": "2006-07-12T00:00:00.000Z",
  "address": "3749 W WRIGHTWOOD AVE",
  "city": "Chicago",
  "state": "IL",
  "description": "ROOF REPAIRS",
  "permit": {
    "number": "100123862",
    "type": "PERMIT - EASY PERMIT PROCESS",
    "applicationDate": "2006-07-12T00:00:00.000Z",
    "issueDate": "2006-07-12T00:00:00.000Z"
  },
  "property": {
    "address": {
      "streetNumber": "3749",
      "streetDirection": "W",
      "streetName": "WRIGHTWOOD AVE",
      "city": "Chicago",
      "state": "IL"
    }
  },
  "work": {
    "description": "ROOF REPAIRS"
  },
  "leadScore": 15,
  "leadTemperature": "COLD"
}
```

The dataset contains permit records only. A source or processing failure with no permit records reports `FAILED` / `FAILED`; an empty but valid response reports `SUCCEEDED` / `COMPLETED`; and records saved before a later storage failure keep the run `SUCCEEDED` / `PARTIAL`. The `OUTPUT` key-value record reports standardized status and last-run counts. The five local dataset rows are historical records accumulated across runs; the saved summary's `itemsStored: 2` describes its prior run, not the cumulative local dataset size.

### Tips and advanced options

- Start with a small `maxItems` value to inspect the source's fields and response size.
- A source's own city/state fields are needed for the optional city/state filters to narrow rows.
- Keep search terms and item limits small enough for a single bounded response.
- This Actor does not use proxy rotation. It does not follow redirects, log in, or bypass site access controls.
- Check the selected portal's current license, agency terms, rate limits, and privacy rules before running it.

### FAQ, support, and responsible use

**Why are some fields missing?** Sources expose different columns, and older permit rows can be sparse. The Actor omits absent values rather than guessing.

**Why did a run fail?** The endpoint may be unavailable, return invalid JSON, redirect, or contain no permit rows the Actor can identify. Check the run log and `OUTPUT` summary. Failure details are not written as dataset records.

**Is this Actor affiliated with the City of Chicago or Socrata?** No. Users must follow the selected source's terms, robots guidance, rate limits, and applicable law. The City of Chicago Data Terms of Use require secondary applications to include this notice:

> 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.

Permit contacts can contain personal information. Use such data only for a lawful, legitimate purpose and follow applicable privacy rules. For bugs or feature requests, use the Actor's Issues tab and include a run ID and a short description.

# Actor input Schema

## `datasetUrl` (type: `string`):

HTTPS Socrata /resource/<dataset-id>.json endpoint on a data.\* or \*.socrata.com host. Defaults to Chicago permits. Redirects are not followed.

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

Optional city filter for sources that expose a permit-level city field. The Chicago dataset has no such column, so this does not filter its rows; its Chicago location comes from the selected dataset.

## `state` (type: `string`):

Optional state filter for sources that expose a permit-level state field. The Chicago dataset has no such column; its IL location comes from the selected dataset.

## `search` (type: `string`):

Optional Socrata full-text query across the source dataset's searchable fields.

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

Maximum number of permit lead records to emit.

## `requestTimeoutSeconds` (type: `integer`):

Maximum time to wait for the public dataset request.

## Actor input object example

```json
{
  "datasetUrl": "https://data.cityofchicago.org/resource/ydr8-5enu.json",
  "maxItems": 100,
  "requestTimeoutSeconds": 45
}
```

# Actor output Schema

## `dataset` (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("realestateapi/building-permit-properties-and-details-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 = {}

# Run the Actor and wait for it to finish
run = client.actor("realestateapi/building-permit-properties-and-details-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 '{}' |
apify call realestateapi/building-permit-properties-and-details-scraper --silent --output-dataset

```

## MCP server setup

```json
{
    "mcpServers": {
        "apify": {
            "type": "http",
            "url": "https://mcp.apify.com/?tools=fetch-actor-details,realestateapi/building-permit-properties-and-details-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/EiBfvciVHUNuxP8De/builds/TdS81uSq2QNDcBvCx/openapi.json
