Building Permits Scraper (Chicago, Austin, Calgary, Seattle)
Pricing
from $3.20 / 1,000 building permit delivereds
Building Permits Scraper (Chicago, Austin, Calgary, Seattle)
Unified public building-permit records from Chicago, Austin, Calgary and Seattle: permit number, property address, description, status and issue date in one JSON schema, with date filters and delta mode.
Pricing
from $3.20 / 1,000 building permit delivereds
Rating
0.0
(0)
Developer
Steadfetch
Maintained by CommunityActor stats
0
Bookmarked
2
Total users
1
Monthly active users
3 hours ago
Last modified
Categories
Share
Public building-permit records from Chicago, Austin, Calgary and Seattle in one normalized schema. One row per permit with permit number, property address, work description, status and issue date, with common date filters, pagination handled and an optional delta mode for daily monitoring.
What it does
- Queries the four official city open-data JSON endpoints (Socrata) in a single run and returns one unified schema regardless of city.
- Merges Chicago (
ydr8-5enu), Austin (3syk-w9eu), Calgary (c2es-76ed) and Seattle (76t5-zqzr) into the same fields, so downstream code does not need four parsers. - Applies
dateFromand paginates through SoQL$limit/$offsetwhile respecting each portal'sCrawl-delay: 1(at least 1 second between requests). - Optional delta mode (
mode: "delta"): keeps the newest issue date per city in the Actor key-value store and returns only permits issued after that date. A quiet day delivers no rows and bills 0 results. - Ships no-code access through Apify plus stable JSON that AI and automation clients can consume directly.
Sources and compliance
| City | Dataset id | Public endpoint | Licence / terms |
|---|---|---|---|
| Chicago, IL | ydr8-5enu | https://data.cityofchicago.org/resource/ydr8-5enu.json | City of Chicago Data Terms of Use: derivative applications must include the disclaimer below and attribution to www.cityofchicago.org. |
| Austin, TX | 3syk-w9eu | https://data.austintexas.gov/resource/3syk-w9eu.json | Public domain with an attribution request and a no-re-identification clause. |
| Calgary, AB | c2es-76ed | https://data.calgary.ca/resource/c2es-76ed.json | Open Government Licence - City of Calgary v2.1: commercial use allowed with attribution. |
| Seattle, WA | 76t5-zqzr | https://data.seattle.gov/resource/76t5-zqzr.json | Public Domain, City of Seattle (attribution given below). The portal has no separate terms page. |
All four portals allow /resource/* in robots.txt and declare Crawl-delay: 1. This Actor only calls those JSON endpoints, with a descriptive User-Agent that identifies Steadfetch, no login, no token, no CAPTCHA bypass, no browser and no proxies. The HTML front ends (including abc.austintexas.gov) are never requested.
No personal data. Applicant, owner and contractor contact fields present in the raw datasets (contact_*, applicantname, contractorname) are never read or emitted. Only public permit facts are returned, and Austin's no-re-identification clause is respected.
Chicago disclaimer (required by the City of Chicago Data Terms of Use)
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.
Attribution
- Contains information from the City of Chicago Open Data Portal (dataset
ydr8-5enu),www.cityofchicago.org. - Data provided by the City of Austin Open Data Portal (dataset
3syk-w9eu). - Contains information licensed under the Open Government Licence - City of Calgary (dataset
c2es-76ed). - Data provided by the City of Seattle Open Data Portal (dataset
76t5-zqzr), public domain.
Input
| Field | Type | Required | Default | Description |
|---|---|---|---|---|
cities | array | Yes | ["chicago"] (prefill); all four if omitted | chicago, austin, calgary, seattle. |
dateFrom | string | No | empty | ISO date (YYYY-MM-DD) lower bound on issue date. |
status | string | No | empty | Case-insensitive exact match on the status reported by each city (ACTIVE, Active, Completed, ...). |
maxItems | integer | No | 1000 | Maximum permits pushed to the dataset (1-10000). |
mode | string | No | full | full or delta. |
strictSchema | boolean | No | true | Fail the run when a row does not match the output schema. Keep enabled. |
Example input
Matches the declared exampleRunInput:
{"cities": ["chicago"],"maxItems": 25,"mode": "full"}
Delta mode
{"cities": ["chicago", "austin", "calgary", "seattle"],"mode": "delta","maxItems": 1000}
The first delta run returns the selected range and saves the newest issue_date per city under building-permits-extractor-state. Later runs request issue_date > lastIssueDate for each city, so unchanged days deliver 0 rows and cost only the run start. Dates are day-granular, matching the source datasets.
Output
Example output
{"url": "https://data.cityofchicago.org/resource/ydr8-5enu.json?$where=id%3D'N2998605'","title": "B200517005 - 3740 N SAYRE AVE","scrapedAt": "2026-10-24T19:57:00.000Z","city": "chicago","permit_number": "B200517005","property_address": "3740 N SAYRE AVE","description": "INSTALL SOLAR PANELS ON ROOF OF ACCESSORY BUILDING. ROOF TYPE: STEEP (>5:12).","status": "ACTIVE","issue_date": "2026-10-23","record_url": "https://data.cityofchicago.org/resource/ydr8-5enu.json?$where=id%3D'N2998605'","source_dataset": "ydr8-5enu"}
Output fields
| Field | Type | Description |
|---|---|---|
url | string | Public JSON row permalink used as the source URL. |
title | string | Permit number plus property address. |
scrapedAt | date-time | ISO 8601 UTC timestamp of the run. |
city | string | chicago, austin, calgary or seattle. |
permit_number | string | Permit number as published by the city. |
property_address | string or null | Street address, without contact data. |
description | string or null | Public work description. |
status | string or null | Status published by the city. Chicago publishes it only for newer permits. |
issue_date | string or null | Issue date (YYYY-MM-DD). |
record_url | string | Public JSON permalink for the permit. |
source_dataset | string | Socrata dataset id. |
New fields are additive and required fields never change, so downstream code can rely on the documented contract.
Pricing
Pay-per-event with the two synthetic platform events:
apify-actor-start: 0.00005 USD per run (Apify-recommended default, includes the first 5 seconds of compute).apify-default-dataset-item: 0.004 USD per row = 4.00 USD per 1,000 results.
There is no custom per-item event, so users are never billed twice for the same permit. Rows rejected by the schema are never pushed and never charged.
Measured cost is about 0.001 USD per 1,000 permits (JSON endpoints, no browser, no proxies, one request per 1,000 rows plus the 1 s crawl delay). The price keeps a wide margin above cost and is aligned with the closest Store competitors (leader about 11 users in 30 days at a comparable price).
Works on the Apify free plan: with the 5 USD monthly credit, about 1,249 permits can be delivered per month (N = floor((5.00 - 0.00005) / 0.004)).
Usage with the API
curl -X POST "https://api.apify.com/v2/acts/steadfetch~building-permits-extractor/runs?token=<YOUR_API_TOKEN>" \-H 'Content-Type: application/json' \-d '{"cities":["chicago","austin"],"dateFrom":"2026-10-01","maxItems":100}'
Then read the default dataset of the run.
FAQ
Do I need an API key for the city portals? No. All four are anonymous public Socrata endpoints. The Actor sends only a descriptive User-Agent and respects each portal's crawl delay.
Are the four cities really the same schema? Yes. city, permit_number, property_address, description, status, issue_date, record_url and source_dataset are normalized. Fields that a city does not publish are null, never invented.
Why is status null for some Chicago rows? Chicago publishes permit_status only for newer permits; older rows have no status. The Actor reports null instead of guessing.
Can I filter by status across cities? Yes, but status vocabularies differ by city (ACTIVE in Chicago, Active in Austin, Completed in Calgary, Issued in Seattle). status is a case-insensitive exact match against the city's own value.
What does delta mode bill? Only delivered permits. The first run delivers the selected range; later runs deliver only permits with an issue date newer than the last delivered date, so a quiet day bills 0 results.
Does the Actor use a browser? No. The sources are JSON APIs, so HTTP is roughly 10x cheaper than a browser.
Is the output schema stable? Yes. New fields are added additively and required fields never change.
Maintenance
The Actor is tested daily through the Steadfetch catalogue QA and the monorepo CI (npm test and npm run publish:check on every push). Repairs take priority over new features. Schema changes are announced through repository releases.
Support
Report bugs or request features through the Apify Store page (Issues tab) of this Actor, or through the Steadfetch actors repository issues. Include the run ID and the input used.