City Building Permits Scraper - Solar, EV, Roofing, ADU avatar

City Building Permits Scraper - Solar, EV, Roofing, ADU

Pricing

from $2.10 / 1,000 permits

Go to Apify Store
City Building Permits Scraper - Solar, EV, Roofing, ADU

City Building Permits Scraper - Solar, EV, Roofing, ADU

Scrape newly issued solar PV, EV charger, heat pump/HVAC, roofing, and ADU permits from Austin, Chicago, Los Angeles, Seattle, and San Francisco open-data portals. Coverage varies by city: Los Angeles covers roofing, ADU, and HVAC only.

Pricing

from $2.10 / 1,000 permits

Rating

0.0

(0)

Developer

Groundplane Labs

Groundplane Labs

Maintained by Community

Actor stats

0

Bookmarked

2

Total users

1

Monthly active users

5 days ago

Last modified

Categories

Security

Limited permissions

Share

Scrape newly issued building and electrical permits for solar PV systems, EV chargers (EVSE), heat pumps / HVAC, roofing / re-roofing, and accessory dwelling units (ADUs) from five municipal open-data portals (Austin, Chicago, Los Angeles, Seattle, and San Francisco), normalized into one unified schema. Coverage is not uniform across cities: Los Angeles covers ROOFING, ADU, and HVAC only, because its source dataset publishes no electrical permits (see the coverage table below). Seattle solar, EV charger, and HVAC permits come from its separate Electrical Permits dataset.

Disclaimer: This Actor is an independent tool and is not affiliated with or endorsed by the City of Austin, the City of Chicago, the City of Los Angeles, the City of Seattle, or the City and County of San Francisco.


What it does

  • Queries 5 Municipal Socrata Open-Data Portals Live: Uses server-side SoQL $where filtering combined with word-boundary classification rules to pull newly issued clean-energy and construction permits across:
    • Austin, TX (data.austintexas.gov/resource/3syk-w9eu.json)
    • Chicago, IL (data.cityofchicago.org/resource/ydr8-5enu.json)
    • Los Angeles, CA (data.lacity.org/resource/pi9x-tg5x.json): building permits only, so ROOFING, ADU, and HVAC categories only
    • Seattle, WA (data.seattle.gov/resource/c4tj-daue.json Electrical Permits for SOLAR, EV_CHARGER, and HVAC; data.seattle.gov/resource/76t5-zqzr.json Building Permits for ROOFING and ADU)
    • San Francisco, CA (data.sf.gov/resource/i98e-djp9.json)
  • Unified Multi-City Schema: Normalizes city-specific column names, dates, valuations, geocoded coordinates, and contractor details into a single flat schema (city, permitNumber, category, permitType, workDescription, status, appliedDate, issuedDate, valuationUsd, address, zip, latitude, longitude, contractorName, contractorLicense, contractorPhone, sourceUrl).
  • Fault-Tolerant Across Cities: If one municipal portal is temporarily undergoing maintenance, the Actor logs a warning and continues collecting permits from the remaining selected cities.
  • Privacy Controls Built In: Homeowner / property owner person names are excluded by default (includeOwnerNames: false), while commercial contractor business names, licenses/certifications, and business phone numbers are always included when published.
  • Newest-First Ordering: Results are deduplicated by city + permitNumber and sorted by issuedDate descending before applying maxItems.

Coverage by city and category

Permits issued in the last 30 days (2026-10-02 to 2026-11-01), counted live via SoQL on 2026-11-01 with this Actor's classifier and deduplication applied. Counts shift daily as cities publish new permits.

CitySOLAREV_CHARGERHVACROOFINGADU
Austin5757154274
Chicago153314215811
Los AngelesNot publishedNot published231,286468
Seattle31952811718
San Francisco14332916
  • Los Angeles: the source dataset (pi9x-tg5x) publishes building permits only. It contains no electrical permit types and its solar flag has never been set, so SOLAR and EV_CHARGER return nothing for Los Angeles. (A keyword search of its building permit text finds about 5 incidental solar mentions in the window; those are not solar permits.) Requesting Los Angeles with SOLAR or EV_CHARGER is flagged in the run status: if those are the only requested pairs, the run ends PARTIAL: with the reason stated; if mixed with covered pairs, the status carries a note naming the uncovered pairs.
  • Seattle: SOLAR, EV_CHARGER, and HVAC are read from Electrical Permits (c4tj-daue), where Seattle permits that work. ROOFING and ADU are read from Building Permits (76t5-zqzr). Before this split, Seattle returned 1 solar/EV row in the same 30-day window; the Electrical Permits source returns 126 (31 solar, 95 EV charger), against 135 raw keyword candidates in a direct SoQL count on c4tj-daue.

Who it's for

  • Solar, Battery Storage & EVSE Equipment Distributors: Track active solar and EV charger installers (contractorName, contractorLicense, contractorPhone) and volume by metro area.
  • HVAC, Roofing & Electrical Subcontractors: Monitor newly issued permits and commercial remodel activity across major metro markets.
  • Clean-Energy & Urban Housing Researchers: Analyze rooftop solar adoption, EV charging infrastructure deployment, electrification (heat pumps), and ADU construction trends at the street and ZIP code level.
  • Property & Insurance Analysts: Verify recent roofing, electrical, and solar PV improvements on commercial and residential properties.

Input

All parameters have working defaults/prefills that return results in under 2 minutes.

FieldTypeDefault / PrefillDescription
citiesarray<string>["AUSTIN", "CHICAGO", "SEATTLE"]Municipal portals to query: AUSTIN, CHICAGO, LOS_ANGELES, SEATTLE, SAN_FRANCISCO.
categoriesarray<string>["SOLAR", "EV_CHARGER"]Permit categories to match: SOLAR, EV_CHARGER, HVAC, ROOFING, ADU.
issuedDateFromstring"" (today − 30 days)Earliest permit issue date in YYYY-MM-DD format. When blank, defaults to 30 days ago.
minValuationUsdinteger0Minimum reported project valuation in USD (0 includes all permits, including those without a reported valuation).
includeOwnerNamesbooleanfalseInclude property owner / homeowner names (ownerName) when published by the city portal. Defaults to false for privacy compliance.
socrataAppTokenstring (secret)""Optional Socrata X-App-Token for higher rate limits on large historical queries.
maxItemsinteger200Maximum number of permit records to return.

Example input JSON

{
"cities": ["AUSTIN", "CHICAGO", "SEATTLE"],
"categories": ["SOLAR", "EV_CHARGER"],
"issuedDateFrom": "",
"minValuationUsd": 0,
"includeOwnerNames": false,
"socrataAppToken": "",
"maxItems": 200
}

Example run options (with default $50 max charge protection)

When invoking via the Apify API or CLI, set a default maximum charge of $50 ("maxTotalChargeUsd": 50):

{
"maxTotalChargeUsd": 50
}

The Actor checks calculate_max_event_charge_count_within_limit("apify-default-dataset-item") before every dataset push and stops cleanly when your spending limit is reached.


Output

Results are saved to the default dataset, deduplicated by city + permitNumber, and sorted by issuedDate descending.

Output fields

FieldTypeDescription
citystringCity identifier (AUSTIN, CHICAGO, LOS_ANGELES, SEATTLE, SAN_FRANCISCO).
permitNumberstringOfficial municipal building or electrical permit number.
categorystringMatched permit category (SOLAR, EV_CHARGER, HVAC, ROOFING, ADU).
permitTypestring | nullCity permit type / work class description.
workDescriptionstring | nullOfficial scope of work / permit description text.
statusstring | nullCurrent permit status (e.g. Active, ACTIVE, Issued, issued).
appliedDatestring | nullApplication / filing date in YYYY-MM-DD format.
issuedDatestring | nullPermit issue date in YYYY-MM-DD format.
valuationUsdnumber | nullReported project cost / job valuation in USD.
addressstring | nullStreet address of the permitted project.
zipstring | nullPostal ZIP code (XXXXX).
latitudenumber | nullWGS84 latitude, rounded to 3 decimal places.
longitudenumber | nullWGS84 longitude, rounded to 3 decimal places.
contractorNamestring | nullContractor company / business name (published by Austin, Chicago, and Seattle).
contractorLicensestring | nullContractor license or certification identifier, only when a city publishes it as a structured field. Currently null for all five cities: Austin publishes only a trade classification and Chicago only unattributed certificate numbers inside free text, and neither is emitted as a license.
contractorPhonestring | nullContractor phone number as published by Austin (one per permit; Austin labels it the contractor phone, and it may be an individual contractor's line).
sourceUrlstringDirect URL to the city permit record or Socrata endpoint entry.
ownerNamestring | nullProperty owner / applicant name, included only when includeOwnerNames is true. Populated only for Chicago (OWNER party) and Austin (applicant name); always null for Los Angeles, Seattle, and San Francisco, whose portals do not publish it in these tables.

Sample output row (synthetic example)

{
"city": "AUSTIN",
"permitNumber": "2026-149800 EP",
"category": "SOLAR",
"permitType": "Electrical Permit",
"workDescription": "Installation of 8.4 kW roof mounted solar PV system with 13.5 kWh battery energy storage.",
"status": "Active",
"appliedDate": "2026-10-25",
"issuedDate": "2026-10-30",
"valuationUsd": 28500.0,
"address": "4810 BURNET RD",
"zip": "78756",
"latitude": 30.319,
"longitude": -97.739,
"contractorName": "SUNBELT CLEAN ENERGY SOLUTIONS LLC",
"contractorLicense": null,
"contractorPhone": "512-555-0148",
"sourceUrl": "https://abc.austintexas.gov/web/permit/public-search-other?t_detail=1&t_selected_folderrsn=13999999"
}

How pricing works

Pay per result: $3.00 per 1,000 results ($0.003 per row). You only pay for rows returned.


Data source and terms


Compliance

This Actor retrieves public building permit records published by municipal open-data portals. Homeowner / property owner names are turned off by default (includeOwnerNames: false).

If you enable includeOwnerNames or use contractor/property data for outreach:

  • Regulatory Compliance: Buyers are solely responsible for complying with the Telephone Consumer Protection Act (TCPA), the National Do-Not-Call (DNC) Registry, the CAN-SPAM Act, the EU GDPR where it applies, and all applicable state and local privacy and telemarketing laws before calling any party.
  • No Consumer / Individual Targeting: This Actor is intended for B2B commercial research, contractor intelligence, and market analysis, and must not be used for unlawful consumer or individual homeowner solicitation.

Privacy and residual risk

  • Residual risk: property addresses and coordinates. Most solar, EV charger, and heat pump permits are issued for private residences, and every row carries the permitted property's street address (address) by default. That is inherent to the source data and to the permit record itself; it cannot be removed without removing the record's usefulness for permit verification. As a mitigation, latitude and longitude are rounded to 3 decimal places (about 100 m) in the output, so coordinates locate a property only approximately. The street address itself is not rounded or masked. Treat downloaded datasets as location data about private homes and handle them accordingly.
  • Contractor fields can name individuals. contractorName is a business field, but sole operators appear under personal names: Chicago contractor slots sometimes hold a person's name rather than a company, and the Austin contractorPhone is one phone per permit as labeled by the city, which may be an individual contractor's line. Treat both as personal data where they name or reach an individual.

Limits and FAQ

  • Which cities publish contractor names and phone numbers?
    • Austin publishes contractorName and a contractor phone (one per permit, as labeled by the city; it may be an individual contractor's line). Austin does not publish a contractor license number: its contractor_trade field is a trade classification, so contractorLicense is null for Austin.
    • Chicago publishes contractorName (across up to 15 party slots on each permit). Chicago publishes no structured license field; certificate numbers appear only inside free-text work descriptions, unattributed to any named party, so they are not emitted: contractorLicense is null for Chicago.
    • Seattle publishes contractorName (contractorcompanyname).
    • Los Angeles and San Francisco do not include contractor detail columns in their primary Socrata permit table (pi9x-tg5x and i98e-djp9), so contractorName is null for those two cities.
  • San Francisco address variants: one permit can appear in the source with several street-address spellings (for example 228, 230, and 230 A 04th Ave). The dedupe key (city plus permitNumber) keeps one variant, so the surviving address spelling can differ between runs.
  • Why is zip null for Chicago permits? The Chicago dataset publishes no property ZIP column. Its per-party ZIP fields are mailing ZIPs (often in another city or state), so they are never emitted as the property ZIP: zip is null for Chicago by disclosure.
  • What happens if one city's Socrata portal times out? Each city is queried independently with up to 6 tries and jittered exponential backoff (2 to 32 seconds, capped at 120 seconds, honoring the portal's Retry-After header). If one city portal fails, the Actor logs a warning, continues returning permits from the remaining selected cities, and ends with a PARTIAL: status naming the failed city and the per-city row counts.
  • Why did my run end PARTIAL: because a source is stale? Each run checks every requested source's Socrata rowsUpdatedAt metadata. If a source has not updated in more than 21 days, the run ends PARTIAL: naming the city, the dataset, and its last update date, because its counts may be silently incomplete. Los Angeles normally lags about a week, which is inside the threshold.
  • Why does Los Angeles return no solar or EV charger permits? The Los Angeles source dataset publishes building permits only: it has no electrical permit types and its solar flag has never been set. Los Angeles covers ROOFING, ADU, and HVAC. Requesting SOLAR or EV_CHARGER for Los Angeles is flagged in the run status rather than silently returning nothing.

Troubleshooting

  • Run ends PARTIAL:: the status message names the reason (a failed city portal, a stale source with its last update date, a requested city and category pair the source does not publish, skipped invalid rows, or a scan cap) and the per-city row counts. One city failing never fails the whole run.
  • Zero matches: a healthy run with no matching permits ends Complete: 0 rows matched your filters. Widen issuedDateFrom, add cities or categories, or lower minValuationUsd.
  • Caps: reaching maxItems is reported in the status. Reaching your max charge stops the run early as a PARTIAL: with the reason stated.
  • Canary input (returns rows in under 30 seconds):
    {
    "cities": ["CHICAGO"],
    "categories": ["SOLAR"],
    "issuedDateFrom": "",
    "minValuationUsd": 0,
    "includeOwnerNames": false,
    "socrataAppToken": "",
    "maxItems": 5
    }

Found a problem or need a field? Open an issue on the Issues tab; we respond quickly.


Changelog

v0.1.3 (2026-11-01)

  • Seattle solar, EV charger, and HVAC permits now come from the Seattle Electrical Permits dataset (c4tj-daue); Building Permits (76t5-zqzr) still supplies Seattle roofing and ADU. Seattle solar/EV yield for the last 30 days went from 1 row to 126.
  • Los Angeles coverage corrected: Los Angeles covers ROOFING, ADU, and HVAC only, because its source publishes no electrical permits. An explicit per-city category capability map now flags any requested pair a source cannot supply in the run status (a run requesting only unsuppliable pairs ends PARTIAL: with the reason).
  • Listing honesty: title no longer claims uniform 5-city coverage, a per-city by category coverage table with measured 30-day counts was added, and the README intro states the per-city coverage plainly.
  • Per-city freshness gate: a source whose Socrata rowsUpdatedAt is more than 21 days old ends the run PARTIAL: naming the city and its last update date.
  • Retry policy: up to 6 tries with jittered backoff (2 to 32 seconds, capped at 120 seconds) and Retry-After honored as seconds or an HTTP-date.
  • Privacy: latitude and longitude are rounded to 3 decimal places, and the residual risk of property street addresses and coordinates is documented in the Compliance section.
  • Added exampleRunInput, the per-1,000 pricing figure, and the current Los Angeles dataset name in the source links.

v0.1.2 (2026-10-31)

  • Red Team correction round: contractorLicense is now null for every city. Austin's value was the source trade classification (not a license) and Chicago's was an unattributed certificate number mined from free text that could belong to a different party than the named contractor; neither is emitted as a license. The field now carries a value only if a city publishes a license as a structured field.
  • Disclosures added: per-city ownerName availability (Chicago and Austin only), the Austin contractor phone residual note (one phone per permit, may be an individual contractor's line), GDPR in the Compliance section, and the San Francisco address-variant dedupe note. TEST_NOTES marked as a historical v0.1 record.

v0.1.1 (2026-10-31)

  • Status contract fixed: runs now end Complete: or PARTIAL: with per-city counts; zero matches on a healthy source is a Complete: success, not a failure.
  • Chicago zip is now null: the dataset has no property ZIP column, and per-party mailing ZIPs were previously emitted as the property ZIP.
  • Added per-row validation and a per-city core-column sentinel (schema drift now fails that city loudly as a PARTIAL: source reason).
  • Store categories set to BUSINESS only; default run options now carry the $50 max charge.

v0.1 (2026-10-31)

  • Initial release supporting Austin, Chicago, Los Angeles, Seattle, and San Francisco Socrata permit portals across SOLAR, EV_CHARGER, HVAC, ROOFING, and ADU categories.