Building Permits Scraper (Chicago, Austin, Calgary, Seattle) avatar

Building Permits Scraper (Chicago, Austin, Calgary, Seattle)

Pricing

from $3.20 / 1,000 building permit delivereds

Go to Apify Store
Building Permits Scraper (Chicago, Austin, Calgary, Seattle)

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

Steadfetch

Maintained by Community

Actor stats

0

Bookmarked

2

Total users

1

Monthly active users

3 hours ago

Last modified

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 dateFrom and paginates through SoQL $limit/$offset while respecting each portal's Crawl-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

CityDataset idPublic endpointLicence / terms
Chicago, ILydr8-5enuhttps://data.cityofchicago.org/resource/ydr8-5enu.jsonCity of Chicago Data Terms of Use: derivative applications must include the disclaimer below and attribution to www.cityofchicago.org.
Austin, TX3syk-w9euhttps://data.austintexas.gov/resource/3syk-w9eu.jsonPublic domain with an attribution request and a no-re-identification clause.
Calgary, ABc2es-76edhttps://data.calgary.ca/resource/c2es-76ed.jsonOpen Government Licence - City of Calgary v2.1: commercial use allowed with attribution.
Seattle, WA76t5-zqzrhttps://data.seattle.gov/resource/76t5-zqzr.jsonPublic 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

FieldTypeRequiredDefaultDescription
citiesarrayYes["chicago"] (prefill); all four if omittedchicago, austin, calgary, seattle.
dateFromstringNoemptyISO date (YYYY-MM-DD) lower bound on issue date.
statusstringNoemptyCase-insensitive exact match on the status reported by each city (ACTIVE, Active, Completed, ...).
maxItemsintegerNo1000Maximum permits pushed to the dataset (1-10000).
modestringNofullfull or delta.
strictSchemabooleanNotrueFail 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

FieldTypeDescription
urlstringPublic JSON row permalink used as the source URL.
titlestringPermit number plus property address.
scrapedAtdate-timeISO 8601 UTC timestamp of the run.
citystringchicago, austin, calgary or seattle.
permit_numberstringPermit number as published by the city.
property_addressstring or nullStreet address, without contact data.
descriptionstring or nullPublic work description.
statusstring or nullStatus published by the city. Chicago publishes it only for newer permits.
issue_datestring or nullIssue date (YYYY-MM-DD).
record_urlstringPublic JSON permalink for the permit.
source_datasetstringSocrata 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.