# US Building Permits (`subrosa/us-building-permits`) Actor

Returns building permits issued in the last seven days (by default) in ten US cities, from each city's open data API: site address, work type, cost, contractor company, no owner or applicant names.

- **URL**: https://apify.com/subrosa/us-building-permits.md
- **Developed by:** [Sub Rosa](https://apify.com/subrosa) (community)
- **Stats:** 2 total users, 1 monthly users, 100.0% runs succeeded, 0 bookmarks
- **User rating**: No ratings yet

## Pricing

from $7.00 / 1,000 results

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

## US Building Permits

Returns building permits issued in the last seven days (by default) in ten US cities: New York, Los Angeles, San Francisco, Austin, Chicago, Seattle, Cincinnati, New Orleans, Mesa and Buffalo. Each item carries the permit number as the city issues it, the permit or work type, the description of the work as filed, the street address and ZIP of the site, the issue, application and expiry dates, the status, the declared cost of the work, the business name of the contractor company where the city publishes one, and the site's coordinates. The data comes from each city's open data API (Socrata, now Tyler Data & Insights), fetched without an account or token, as it stands at the moment of the run. The sources are JSON endpoints, so the Actor is built on Crawlee's `HttpCrawler` rather than a Cheerio or browser crawler. A default run returns 300 items across the ten cities in about ten seconds and eleven API requests. The `result` price is $0.0025 per item, with a $0.02 charge per run.

No owner, applicant, permittee, agent or contact identities are collected. Every one of these datasets publishes person-level columns (owners' names and home addresses, applicants' and contractors' personal names, phone numbers, email addresses, licence numbers, inspectors' names); this Actor never selects those columns from the API, so they never reach the extractor. The one business-name column a city may carry passes an organization test before it is returned, and a value shaped like a person's name is dropped. The work description, free text typed by whoever filed the permit, passes through the house contact filter, which drops any sentence carrying a name after a role word, an honorific, a phone-shaped number, an email address, a licence number or a health detail; it is a filter, not a guarantee. The site address stays: a permit is a public record about a place, and the address is the record. See Limits and honesty and Legal below.

### Who uses it

- A building-products or home-services company finding new work as it is permitted: pulls every city each morning, filters `permitType` and `workDescription` for roofing, solar, HVAC or pool work, keeps `address`, `zip`, `issuedAt` and `estimatedCost`, and routes each site to a local team without ever handling a homeowner's name.
- A construction analyst or lender tracking activity by market: pulls all ten cities with `sinceDays` 30, sums `estimatedCost` by `city` and `permitType` week by week, and compares the mix of new construction, alteration and trade permits across markets using one field vocabulary rather than ten portals.
- A researcher or journalist studying contractors and code enforcement: uses `contractorBusinessName` to count which companies pull the most permits in Austin, Seattle, Cincinnati, Mesa and New York, joins `permitNumber` to the city's own record via `url` for the full file, and uses `latitude` and `longitude` to map where work concentrates.

### Sample output

One real item from a real run, as JSON:

```json
{
    "id": "nyc/102649232",
    "url": "https://data.cityofnewyork.us/resource/rbx6-tga4.json?tracking_number=102649232",
    "sourceUrl": "https://data.cityofnewyork.us/resource/rbx6-tga4.json?%24select=tracking_number%2Cwork_permit%2Cjob_filing_number%2Cwork_type%2Cjob_description%2Chouse_no%2Cstreet_name%2Cborough%2Czip_code%2Cissued_date%2Capproved_date%2Cexpired_date%2Cpermit_status%2Cestimated_job_costs%2Capplicant_business_name%2Clatitude%2Clongitude&%24where=issued_date+%3E%3D+%272026-09-19T00%3A00%3A00%27&%24order=issued_date+DESC%2C+tracking_number%2C+work_permit&%24limit=30&%24offset=0",
    "scrapedAt": "2026-09-26T12:49:55.324Z",
    "city": "New York",
    "state": "NY",
    "permitNumber": "M01143900-S1-PL",
    "permitType": "Plumbing",
    "workDescription": "Modification to plumbing system in existing duplex apartment #7-8A, as per plans filed herewith. No change in use, egress, or occupancy.",
    "address": "941 PARK AVENUE",
    "zip": "10028",
    "issuedAt": "2026-09-24T04:00:00.000Z",
    "appliedAt": "2025-03-04T05:00:00.000Z",
    "expiresAt": "2027-03-02T05:00:00.000Z",
    "status": "Permit Issued",
    "estimatedCost": 76000,
    "costCurrency": "USD",
    "contractorBusinessName": "GOLDS PLUMBING CORP",
    "latitude": 40.777095,
    "longitude": -73.959438
}
```

Ten items, one from each city, are in `sample.json`.

### Data dictionary

Every field is present on every item. Fields a city does not publish are `null`, never missing and never an empty string.

| Field                    | Type           | Meaning                                                                                                                                                                                                                                                                                                                                                                              | Example                                                                              |
| ------------------------ | -------------- | ------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------ | ------------------------------------------------------------------------------------ |
| `id`                     | string         | City key and the source's own row identifier, joined with a slash. Unique within a run. The row identifier is the city's row id where it has one (New York's tracking number, San Francisco's record id, Chicago's id, Mesa's row id) and the permit number otherwise                                                                                                                | `"chicago/3433743"`                                                                  |
| `url`                    | string         | Canonical page for the record: the city's own permit record page when the dataset links to one (Austin, Seattle, Cincinnati), otherwise the record's address in the source API, a JSON URL that returns exactly this row                                                                                                                                                             | `"https://services.seattle.gov/portal/customize/LinkToRecord.aspx?altId=7152387-CN"` |
| `sourceUrl`              | string         | The API page the record came from: the city's resource URL with the column selection, date window, ordering and paging that produced it                                                                                                                                                                                                                                              | `"https://data.seattle.gov/resource/76t5-zqzr.json?%24select=permitnum..."`          |
| `scrapedAt`              | string         | Extraction time, ISO 8601, UTC                                                                                                                                                                                                                                                                                                                                                       | `"2026-09-26T11:54:43.511Z"`                                                         |
| `city`                   | string         | City the permit was issued in                                                                                                                                                                                                                                                                                                                                                        | `"Austin"`                                                                           |
| `state`                  | string         | Two-letter state code                                                                                                                                                                                                                                                                                                                                                                | `"TX"`                                                                               |
| `permitNumber`           | string         | The permit number exactly as the city issues it, declared in the dataset schema as an identifier field (`x-house-identifier`), so the house phone check leaves its digit runs alone. Not unique in San Francisco and Cincinnati, which publish one row per revision or trade under the same number; `id` tells those apart                                                           | `"2023-149589 PP"`                                                                   |
| `permitType`             | string or null | Permit type or work type as the city labels it. Vocabulary differs by city: New York's work type, Los Angeles's permit type, San Francisco's permit type definition, Austin's permit type description, Chicago's permit type, Seattle's permit type (or class when the type is blank), Cincinnati's mapped type, New Orleans's type, Mesa's type of work, Buffalo's application type | `"Bldg-Alter/Repair"`                                                                |
| `workDescription`        | string or null | Description of the work as filed, with HTML removed and passed through the house contact filter (see Limits and honesty). Null when the city publishes none or when nothing safe remains                                                                                                                                                                                             | `"Construct addition and alterations to existing one-family dwelling per plan."`     |
| `address`                | string or null | Street address of the site, as the city publishes it: street number, direction and name, with a unit only where the city includes it in the address column                                                                                                                                                                                                                           | `"12527 DAYTON AVE N"`                                                               |
| `zip`                    | string or null | Five-digit ZIP of the site (ZIP+4 kept when given). Null for Chicago, New Orleans and Mesa, whose datasets carry no ZIP column                                                                                                                                                                                                                                                       | `"98133"`                                                                            |
| `issuedAt`               | string or null | Issue date, ISO 8601, UTC. Cities publish a local calendar date with no time zone; it is placed in the city's own zone and converted, so a Chicago permit dated 2026-09-24 reads `2026-09-24T05:00:00.000Z` and a Seattle one `2026-09-24T07:00:00.000Z`. Convert back to the city's zone to recover the date; do not truncate                                                       | `"2026-09-24T05:00:00.000Z"`                                                         |
| `appliedAt`              | string or null | Application, filing or submission date, converted the same way. For New York it is the approval date, the earliest date DOB NOW publishes per permit. Null for Buffalo and where a city left it blank                                                                                                                                                                                | `"2026-07-31T07:00:00.000Z"`                                                         |
| `expiresAt`              | string or null | Expiry date, converted the same way. Null for Los Angeles, San Francisco, Chicago, New Orleans and Mesa, which publish none                                                                                                                                                                                                                                                          | `"2028-03-24T07:00:00.000Z"`                                                         |
| `status`                 | string or null | Status as the city labels it. Null for Buffalo, which publishes none                                                                                                                                                                                                                                                                                                                 | `"Issued"`                                                                           |
| `estimatedCost`          | number or null | Declared or estimated cost of the work in US dollars, as the applicant filed it. Zero and token values such as 1 occur where nothing was declared. For Austin the first populated valuation column is used (total job, remodel total, building, then the trade columns), and most trade permits carry none                                                                           | `170000`                                                                             |
| `costCurrency`           | string or null | `"USD"` when `estimatedCost` is set, otherwise null                                                                                                                                                                                                                                                                                                                                  | `"USD"`                                                                              |
| `contractorBusinessName` | string or null | Business name of the contractor company, only when the value names an organization. Null for Los Angeles, San Francisco, Chicago, New Orleans and Buffalo, whose datasets carry no company column, and null wherever the value is shaped like a person's name or is a placeholder such as OWNER                                                                                      | `"Advantage Plumbing Contractors LLC"`                                               |
| `latitude`               | number or null | Latitude of the site as the city geocoded it, WGS84                                                                                                                                                                                                                                                                                                                                  | `30.2823`                                                                            |
| `longitude`              | number or null | Longitude of the site as the city geocoded it, WGS84                                                                                                                                                                                                                                                                                                                                 | `-97.7574`                                                                           |

### Input

| Field                | Type             | Default                | Meaning                                                                                                                                                                                                                                                                                                                               |
| -------------------- | ---------------- | ---------------------- | ------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- |
| `cities`             | array of strings | all ten                | City keys: `nyc`, `los-angeles`, `san-francisco`, `austin`, `chicago`, `seattle`, `cincinnati`, `new-orleans`, `mesa`, `buffalo`. `maxItems` is shared evenly across the cities you choose; a city with fewer permits in the window than its share ends early and the others fill the remainder. Unknown keys are logged and ignored. |
| `sinceDays`          | integer          | 7                      | Return permits whose issue date is within this many whole days before today (UTC midnight). Los Angeles refreshes weekly, so a short window can hold nothing there; the log says so.                                                                                                                                                  |
| `maxItems`           | integer          | 300                    | Stop after this many items across all chosen cities. Each API page carries up to 1,000 permits, so a run of 3,000 items costs about a dozen requests. The busiest cities (New York, Austin, Chicago) hold thousands of permits a week; a run larger than the window holds returns what the window holds.                              |
| `proxyConfiguration` | object           | Apify datacenter proxy | Standard Apify proxy settings. Datacenter proxies are sufficient; the sources answer plain requests.                                                                                                                                                                                                                                  |

### Pricing

Pay per event, two events. `actor-start`: $0.02, once per run, covers the fixed overhead of starting. `result`: $0.0025 per item, that is $2.50 per 1,000 items. Items are pushed and charged in the same step, so a run never delivers more items than it charges for, and a run stops cleanly when your maximum charge is reached. A default run of 300 items costs $0.77.

Measured platform cost: the default run makes eleven API requests, transfers about 170 KB, and the crawler runs for about seven seconds inside a run of about ten seconds (measured 2026-09-26 with the one-second same-domain delay in place). Scaled to 1,000 items that is roughly fourteen requests (ten first pages plus top-ups), about 600 KB, and a run of ten to fifteen seconds, since each page can carry 1,000 rows. At Apify's list prices ($0.40 per compute unit at 1 GB of memory, $0.20 per GB of transfer, $0.005 per 1,000 dataset writes) that is about $0.008 per 1,000 items, most of it the dataset writes. The $2.50 price is therefore roughly 300 times the platform cost, above the house floor of three times.

Free allowance: Apify's free plan carries $5 of usage a month. At these prices that covers six default runs of 300 items ($0.77 each, $4.62 in all), or about 1,990 items in one run, before a paid plan is needed.

### Limits and honesty

- Ten cities, one dataset each, chosen because each publishes an open JSON API with a permissive licence and current rows. The datasets differ in what they hold, and the nulls follow the source: Chicago, New Orleans and Mesa publish no ZIP; Buffalo publishes no application date and no status; Los Angeles, San Francisco, Chicago, New Orleans and Mesa publish no expiry; five cities publish no contractor company column at all. A field that is null for a city is null because the city does not publish it, not because it was withheld.
- The window is on the issue date only. Permits applied for but not yet issued are not returned; neither are permits issued earlier and amended in the window.
- Los Angeles refreshes its dataset weekly and Cincinnati, Mesa and Buffalo daily, so the newest permits in those cities can lag the run by up to a week. New York, San Francisco, Austin, Chicago, Seattle and New Orleans were current to the previous day when checked.
- `permitType` keeps each city's own vocabulary. Ten cities use ten schemes (New York work types, Chicago's upper-case permit categories, Buffalo's short codes such as `REP-PLANS`); the Actor does not fold them into one taxonomy.
- `estimatedCost` is what the applicant declared. Many cities accept 0 or 1 as a placeholder, Austin leaves most trade permits blank, and no city verifies the figure.
- Sources publish exact duplicate rows (New York) and one row per revision or trade under one permit number (San Francisco, Cincinnati). Within a run every `id` is delivered once; a permit number can therefore appear on more than one item in those two cities, and a New York permit whose rows are identical appears once.
- `contractorBusinessName` is the result of an organization test on the city's company column, because Seattle, Mesa and Cincinnati put individuals' names in that column now and then. A value with a company marker (LLC, Inc, Corp, a trade word such as Roofing or Electric, an ampersand, a digit, more than four words) is kept; two to four plain words with no such marker are treated as a person and dropped; a person's name written after the company ("Acme Electric Inc. / J. Doe") is cut off; a trade name after DBA is kept in place of what precedes it. A company name with no recognizable marker is dropped too, so the field errs toward null.
- `workDescription` is free text typed by whoever filed the permit, and in a default run it has carried an applicant's name in parentheses after "applicant/agent", a reviewer's name after "per", a roofing contractor's licence number, and a note that a tenant at the address is disabled. Every description therefore passes through the house contact filter, `stripContactProse` in the shared `src/scrub.js`, which works at the sentence level: any sentence carrying an email address, a phone-shaped number, an honorific (Mr, Dr), a role word followed by a capitalised name (applicant, agent, owner, tenant, per, by, c/o), a licence number, or a health word (disabled, medical, hospice) is dropped, and a capitalised name in parentheses is removed wherever it stands. On top of that, this Actor removes two shapes the house rules do not key on, both seen in a default run: a registered professional named with a registration number ("Registered Structural professional engineer: A. Name #30895, expires 12/31/26", Mesa), and a family's surname naming a private event at the site ("Name WEDDING TENT AT ... ACADEMY ON SEPT 26", Chicago). It also drops the period after an honorific ("Mr. Name" becomes "Mr Name") so the house rule, whose sentence splitter would otherwise break at "Mr.", sees the name and drops the sentence, and it keeps the source's line breaks up to the filter so that a contact line in a multi-line description (New Orleans' re-roofing notes end with the city's inspections mailbox) takes only its own line with it. This is a filter, not a guarantee: a name that follows none of these shapes can pass, and innocent text can go with the guilty (a sentence mentioning a medical office, a parenthesised phrase of two capitalised words such as "(COMPLEX DEMOLITION)", a sentence with "per LA City Standard Plan"). Phone detection is by shape, never by digit count, so reference numbers inside descriptions ("revision to app#202609248597", "REF: PMT23-02563") survive. A description from which nothing safe remains is null.
- `permitType`, `status` and `address` are labels the city assigns, not free text; they are cleaned of HTML and set to null in the rare case one carries an email address or a phone-shaped number.
- Not collected, on purpose (never selected from the API): owners' names and mailing addresses, applicants' names, contractors' personal names, phone numbers, email addresses and licence numbers, filing representatives, site safety managers, superintendents, inspectors, the staff who created or closed a record, fees paid, parcel and lot numbers, census and council geography, and any column that is not in the city's `select` list in `src/cities.json`.
- Requests go out at most 30 requests a minute and two at a time, with at least two seconds between requests to the same portal (`sameDomainDelaySecs: 2`, twice the `Crawl-delay: 1` every portal's robots.txt states) and three retries with backoff. Socrata throttles anonymous clients by IP and answers a throttled request with 429; if 429s appear in the log, lower the rate and re-run, and the house lowers the default when a source asks.
- A city can change a dataset's columns or retire it (Dallas, Honolulu, Kansas City and Providence were dropped in intake for stale datasets, and Nashville moved off Socrata). When a city's response no longer carries the expected identifier column the request fails loudly, the daily test fails, the house status page shows this Actor as under maintenance, a fix ships, and the changelog records it.
- Running locally without an Apify login: set `proxyConfiguration` to `{ "useApifyProxy": false }` in the input, otherwise the SDK tries the Apify proxy without credentials.

### Legal

Robots. All ten portals run the same platform and publish the same robots.txt apart from the Sitemap line (data.cityofnewyork.us, data.lacity.org, data.sf.gov, data.austintexas.gov, data.cityofchicago.org, data.seattle.gov, data.cincinnati-oh.gov, data.nola.gov, data.mesaaz.gov, data.buffalony.gov, each at `/robots.txt`, all checked on 2026-09-26 under the declared identity). The file has one group, `User-agent: *`, with `Crawl-delay: 1`, and disallows catalogue browsing with filter parameters (`/browse?*&q=` and the like), `/api/odata/`, `/OData.svc/`, `/api/collocate*`, `/login`, `/reset_password/`, `/tiles/`, `/browse/embed`, widget previews, and `*/alt` and `*/edit` pages. The only path this Actor fetches, `/resource/<dataset>.json`, is not among them. The crawler reads each host's robots.txt at the start of every run under the house identity and skips anything that has since become disallowed. The stated `Crawl-delay: 1` is honoured with margin: the crawler's same-domain delay is set to two seconds (`sameDomainDelaySecs: 2`), so no two requests to the same portal are ever less than two seconds apart, by construction rather than by the rate limit alone.

Platform terms. The portals' footers link to the platform vendor's terms (https://www.tylertech.com/terms), which say a user of Tyler's services will not "use any computer code, data mining software, 'robot,' 'bot,' 'spider,' 'scraper' or other automatic device, or program, algorithm or methodology having similar processes or functionality, or any manual process, to monitor or copy any of the Web pages, data or content found or accessed through the Services", and which open by saying they apply "except where terms specific to a particular Service may apply instead" and that "to the extent that the provisions of any additional terms conflict with these Terms of Use, the provisions of the additional terms will govern." The service-specific terms for this API are the Socrata Open Data API developer documentation (https://dev.socrata.com/docs/app-tokens.html), which says: "While it is possible to perform simple unauthenticated queries against the Socrata Open Data API without making use of an application token, you'll receive much higher throttling limits if you include an application token in your requests. If you elect not to use an application token, you'll be subjected to a much lower throttling limit for all requests originating from your IP address." and "If you are throttled for any reason, you will receive a status code 429 response." The data itself belongs to each city, under the licence each city states below. The house holds no account on any of these portals, has never registered one, uses no application token, and never logs in, so it has not entered the vendor's terms as a user. The statement each site addresses to automated visitors is its robots.txt, and that is the consent the house honours exactly. This Actor fetches only the public JSON resource endpoints robots.txt permits, at 30 requests a minute and two at a time, under the declared identity `SubRosaBot/1.0` (`SubRosaBot/1.0 (+https://subrosa.dev/bots)` in full), with header generation off, no session pool and no cookies kept. If any city or the platform asks the house to stop, in any form, that city is removed or the Actor is unpublished the same day and the changelog says why.

New York. Dataset: DOB NOW: Build - Approved Permits, https://data.cityofnewyork.us/d/rbx6-tga4, published by the Department of Buildings. The dataset lists no licence. NYC Open Data's FAQ (https://www.nyc.gov/opendata/get-started/FAQs) answers "Are there restrictions on how I can use Open Data?" with "Open Data belongs to all New Yorkers. There are no restrictions on the use of Open Data." The NYC.gov Terms of Use (https://www.nyc.gov/main/terms-of-use) prohibit, among other things, any use that would "disrupt NYC.gov or its servers or networks in any way"; the rate above is set with that in mind. Columns the dataset shows and this Actor never selects: `applicant_first_name`, `applicant_middle_name`, `applicant_last_name`, `applicant_license`, `applicant_business_address`, `filing_representative_first_name`, `filing_representative_middle_initial`, `filing_representative_last_name`, `filing_representative_business_name`, `permittee_s_license_type`, `owner_name`, `owner_business_name`, `owner_street_address`, `owner_city`, `owner_state`, `owner_zip_code`, and the apartment and floor columns. The one name column selected, `applicant_business_name`, is the permittee company's name and passes the organization test.

Los Angeles. Dataset: Building and Safety - Building Permits Issued from 2020 to Present, https://data.lacity.org/d/pi9x-tg5x, published by the Department of Building and Safety. The dataset lists no licence. The portal's Terms of Use (https://data.lacity.org/terms-of-use, revised 23 May 2014) say "Public data sets made available on the Site are provided for informational purposes, and provided for the convenience of the reader", and under User Conduct that a user may not "Post or share any personally identifiable or private information of any third party or collect or store personally identifiable or private information of any third party without written City authorization" and may not "Interfere with or disrupt the Site, servers or networks connected to the Socrata Service". This dataset carries no person columns; nothing is dropped and `contractorBusinessName` is null.

San Francisco. Dataset: Building Permits, https://data.sf.gov/d/i98e-djp9, published by the Department of Building Inspection under the Open Data Commons Public Domain Dedication and License (http://opendatacommons.org/licenses/pddl/1.0/), as its metadata states. The DataSF Terms of Use (https://www.sf.gov/reports/april-2017/datasf-terms-use) say at IX: "Except where otherwise stated in the file containing such Data or on the page from which such Data is accessed, including its metadata, Data is made available under the Public Domain Dedication and License v1.0", and at VI: "You will not take any measures to re-identify the Data or to contact individuals whose information is represented by the Data." This dataset carries no person columns; the city's Building Permits Contacts dataset, which does, is never read.

Austin. Dataset: Issued Construction Permits, https://data.austintexas.gov/d/3syk-w9eu, published by the Development Services Department under "Public Domain U.S. Government" (https://www.usa.gov/government-works). The City of Austin Open Data Terms of Use (https://data.austintexas.gov/stories/s/ranj-cccq) say "Data available through the City of Austin Open Data Portal are offered free and without restriction" and "Unless otherwise noted in metadata, datasets available on the City of Austin Open Data Portal are in the public domain", ask that "proper credit be given ... Please provide attribution to both the City of Austin and the City Department that is the source of the cited data" (given here and in every item's `city` and `sourceUrl`), and carry the same re-identification clause as San Francisco. Columns never selected: `contractor_full_name`, `contractor_phone`, `contractor_address1`, `contractor_address2`, `contractor_city`, `contractor_zip`, `applicant_full_name`, `applicant_org`, `applicant_phone`, `applicant_address1`, `applicant_address2`, `applicant_city`, `applicantzip`. The one name column selected, `contractor_company_name`, passes the organization test.

Chicago. Dataset: Building Permits, https://data.cityofchicago.org/d/ydr8-5enu, published by the Department of Buildings; the dataset's licence field says "See Terms of Use" and links to the City's Data Terms of Use at https://www.chicago.gov/city/en/narr/foia/data\_disclaimer.html. That page answers the declared identity `SubRosaBot/1.0` with 403 (checked 2026-09-26), so the house has not read it there and does not pretend to be a browser to do so; the City publishes the same Terms of Use, verbatim, on its own TIF portal at https://webapps1.chicago.gov/ChicagoTif/disclaimer.html, which answers the declared identity with 200, and the text below is quoted from that copy (read 2026-09-26). Those terms say: "The City may require a user of this data to terminate any and all display, distribution or other use of any or all of the data provided at this website for any reason including, without limitation, violation of these Terms of Use or other terms as defined by City agencies or departments contributing data to this website." They also require any secondary or derivative application to carry this disclaimer, which this Actor carries here: "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." Columns never selected: `contact_1_type` through `contact_15_zipcode`, the names, cities, states and ZIPs of up to fifteen contacts per permit (owners, contractors, architects and expediters mixed), and the fee columns. `contractorBusinessName` is null for Chicago because the only contractor names are in those contact columns.

Seattle. Dataset: Building Permits, https://data.seattle.gov/d/76t5-zqzr, published by the Department of Construction and Inspections under "Public Domain". The Seattle Open Data Terms of Use (https://data.seattle.gov/stories/s/Data-Policy/6ukr-wvup/) say: "To the extent the data consists of a list of individuals or can be readily sorted, filtered, or configured as a list of individuals, it is not to be used for a commercial purpose", and "Unless otherwise indicated, data on this site does not require specific attribution." This dataset is a list of permits, not of individuals, and its one name column, `contractorcompanyname`, sometimes holds an individual's name; the organization test drops those, so the output cannot be configured as a list of individuals. No other person columns exist in the dataset.

Cincinnati. Dataset: Cincinnati Building Permits, https://data.cincinnati-oh.gov/d/uhjb-xac9, published by the City of Cincinnati under "Public Domain", as the dataset's licence field states with the City named as attribution. The portal's footer links only to the platform terms quoted above, and the dataset's description says "For directions on downloading and using open data please visit our How-to Guide". The one name column selected, `companyname`, passes the organization test; the city's Building Permits Contacts dataset is never read. The dataset publishes each record's link as `http://cagis.hamilton-co.org/...`, and that server redirects to https, so `url` carries the https form.

New Orleans. Dataset: Permits, https://data.nola.gov/d/rcm3-fn58, published by the Department of Safety and Permits under Creative Commons CC0 1.0 (http://creativecommons.org/publicdomain/zero/1.0/legalcode). The city's DataDriven programme (https://datadriven.nola.gov/open-data/) requires every data provider "to assigning your data with a Creative Commons cc0 Public Domain license". Columns never selected: `owner`, `applicant`, and `contractors`, which holds licensed individuals' names rather than companies, so `contractorBusinessName` is null for New Orleans.

Mesa. Dataset: Building Permits, https://data.mesaaz.gov/d/dzpk-hxfb, published by the Development Services Department; the licence field says "See Terms of Use" and the City of Mesa Open Data Terms of Use (https://data.mesaaz.gov/stories/s/Terms-of-Use-page/2dcd-j2nx/) say at 3.e: "Datasets are made available to the public on an open license basis. An open license on a dataset signifies there are no restrictions on copying, publishing, distributing, modifying or using the data for a commercial or non-commercial use", and at 3.f: "The Licensed User agrees to list the City as the source for the Data or Derivative Work on all products (including maps, reports, displays, applications) where the Data or Derivative Work is used by the Licensed User." The City of Mesa is the source of every Mesa item, and each carries `city` and `sourceUrl`. Columns never selected: `applicant`, `contractor_phone`, `contractor_email`, `contractor_address`, `contractor_city`, `contractor_state`, `contractor_zip`, `contractor_license`, `created_by`, `assigned_user`, `closed_by_user`, and the fee, balance and infraction columns. The one name column selected, `contractor_name`, passes the organization test.

Buffalo. Dataset: Permits, https://data.buffalony.gov/d/9p2d-f3yt, published by the Department of Permit and Inspection Services under "Public Domain U.S. Government" (https://www.usa.gov/government-works). The City of Buffalo Open Data Policy (https://data.buffalony.gov/stories/s/City-of-Buffalo-Open-Data-Policy/xhgt-q9im/) commits the City to "Proactively release all open data through a central location, making it freely available and fully accessible to the broadest range of users in readily accessible formats without any licensing fees or restrictions on use or reuse". Columns never selected: `applicant`, `licno`, `lictype`, `inspector`, and the fee and plan columns. `contractorBusinessName` is null for Buffalo.

Declined in intake. Baton Rouge (data.brla.gov) publishes a current permits dataset tagged Public Domain, but the portal's Terms of Service limit use to "informational, non-commercial and personal use only" and exclude "any resale or commercial use" and "use of any data mining, robots or similar data gathering or extraction methods"; it is not included. San Jose's portal disallows `/api/` in robots.txt; it is not included.

Personal data. The house ruling on government records of work at a property applies: the address is the record and stays; every person named on a permit (owner, applicant, permittee, contractor as an individual, agent, contact, inspector) goes at the schema level, by never being selected from the API, and organizations stay. The only names returned are business names of contractor companies that pass the organization test. The work description passes through the house contact filter described under Limits and honesty; that is a filter, not a guarantee, and a buyer who finds a person in a description should open an issue so a rule can be added.

You. A buyer who holds an account on any of these portals is bound by the terms they accepted there, and is responsible for whether and how they use this data. You are responsible for your downstream use of the output and for the law that applies to you.

### Changelog

- 2026-09-26: review fixes before publish. `workDescription` now passes through the house contact filter (`stripContactProse`) plus rules for a registered professional named with a registration number, a surname naming a private event, and honorifics written with a period, after a default run carried an applicant's name, a reviewer's name, a licence number and a health detail; `permitId` renamed `permitNumber` and declared an identifier in the dataset schema; `sameDomainDelaySecs: 2` set from the portals' `Crawl-delay: 1` with margin; Cincinnati record links upgraded to https; Chicago terms quoted from the City's mirror because chicago.gov refuses the declared bot; test fixtures use invented names only.
- 2026-09-26: first release. Ten cities from their Socrata open data APIs; per-city column selection with no person columns; organization test on contractor names; site addresses kept per the house ruling of 2026-09-26.

### Support

Open an issue on the Actor's Issues tab. Replies within one day.

# Changelog

This Actor's version history is a separate document: https://apify.com/subrosa/us-building-permits/changelog.md

# Actor input Schema

## `cities` (type: `array`):

Which cities to return permits for. maxItems is shared evenly across the chosen cities; a city with fewer permits in the window than its share ends early and the others fill the remainder.

## `sinceDays` (type: `integer`):

Return permits whose issue date falls within this many days before today (UTC). Whole days; the window starts at midnight. Cities that refresh weekly (Los Angeles) can show nothing in a short window.

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

Stop after this many items across all chosen cities. The default is sized so the default run finishes in well under five minutes; each API page carries up to 1,000 permits, so larger runs cost few extra requests.

## `proxyConfiguration` (type: `object`):

Apify proxy settings. Datacenter proxies are enough for these sources; residential proxies are not needed and cost more.

## Actor input object example

```json
{
  "cities": [
    "nyc",
    "los-angeles",
    "san-francisco",
    "austin",
    "chicago",
    "seattle",
    "cincinnati",
    "new-orleans",
    "mesa",
    "buffalo"
  ],
  "sinceDays": 7,
  "maxItems": 300,
  "proxyConfiguration": {
    "useApifyProxy": true,
    "apifyProxyGroups": []
  }
}
```

# Actor output Schema

## `results` (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 = {
    "cities": [
        "nyc",
        "los-angeles",
        "san-francisco",
        "austin",
        "chicago",
        "seattle",
        "cincinnati",
        "new-orleans",
        "mesa",
        "buffalo"
    ],
    "sinceDays": 7,
    "maxItems": 300,
    "proxyConfiguration": {
        "useApifyProxy": true,
        "apifyProxyGroups": []
    }
};

// Run the Actor and wait for it to finish
const run = await client.actor("subrosa/us-building-permits").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 = {
    "cities": [
        "nyc",
        "los-angeles",
        "san-francisco",
        "austin",
        "chicago",
        "seattle",
        "cincinnati",
        "new-orleans",
        "mesa",
        "buffalo",
    ],
    "sinceDays": 7,
    "maxItems": 300,
    "proxyConfiguration": {
        "useApifyProxy": True,
        "apifyProxyGroups": [],
    },
}

# Run the Actor and wait for it to finish
run = client.actor("subrosa/us-building-permits").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 '{
  "cities": [
    "nyc",
    "los-angeles",
    "san-francisco",
    "austin",
    "chicago",
    "seattle",
    "cincinnati",
    "new-orleans",
    "mesa",
    "buffalo"
  ],
  "sinceDays": 7,
  "maxItems": 300,
  "proxyConfiguration": {
    "useApifyProxy": true,
    "apifyProxyGroups": []
  }
}' |
apify call subrosa/us-building-permits --silent --output-dataset

```

## MCP server setup

```json
{
    "mcpServers": {
        "apify": {
            "type": "http",
            "url": "https://mcp.apify.com/?tools=fetch-actor-details,subrosa/us-building-permits"
        }
    }
}
```

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/O4bbgAUDV0Rz26OJH/builds/WormObY7bdoVKsbo2/openapi.json
