Accela & EnerGov Building Permit Portal Scraper (Any City)
Pricing
from $3.00 / 1,000 permit record scrapeds
Accela & EnerGov Building Permit Portal Scraper (Any City)
Scrape building permits from US cities and counties on Accela Citizen Access or Tyler EnerGov Citizen Self Service portals: permit type, status, dates, valuation, address, contractor. Normalized JSON, daily new-permit monitor with webhooks. No login, no proxies. $0.003/permit.
Pricing
from $3.00 / 1,000 permit record scrapeds
Rating
0.0
(0)
Developer
Owlabee
Maintained by CommunityActor stats
0
Bookmarked
2
Total users
1
Monthly active users
2 days ago
Last modified
Categories
Share
Scrape building permits from US cities and counties that publish nothing on an open-data portal and run Accela Citizen Access (ACA) or Tyler EnerGov Citizen Self Service (CSS) instead. The Actor talks to the same public search the portal's web page uses (EnerGov's JSON search API, ACA's General Search page), paginates newest-first, and writes every permit in one normalized JSON schema: permit number, type and work class, status, applied / issued / finalized / expiration dates, address, parcel, valuation, contractor, owner and applicant. The schema is the same as our US Building Permits Scraper (26 open-data cities), so records from both Actors are interchangeable in one pipeline.
Built for contractor lead generation (roofing, solar, HVAC, pools, remodels), real-estate and proptech data teams, insurers and lenders. Monitor mode flags only the permits not seen on the previous run, so a daily schedule plus a webhook is a new-permit feed for any of the 31 verified jurisdictions (17 EnerGov, 14 Accela) below. No login, no proxies, no CAPTCHA solving, no browser. Results are available as JSON, CSV, Excel, through the API, webhooks and MCP.
Unofficial: not affiliated with Accela, Inc. or Tyler Technologies, Inc.
How to use
- Pick one or more Jurisdictions (or
all,all-energov,all-accela) and the Issued within (days) window. - Optionally filter by Permit type keywords, Work description keyword or Minimum valuation, turn on Fetch permit details for contractor, owner, valuation and parcel, and set Max permits per jurisdiction together with the run's maximum cost.
- Click Start. For a feed, schedule the run daily with Only new permits since last run on and a Webhook URL; the first run is the baseline.
Input
| Field | Type | Required | Description |
|---|---|---|---|
jurisdictions | string[] | yes | Registry ids (table below), or all, all-energov, all-accela. Each portal queried is one portal-run event. |
issuedWithinDays | integer | no | Window in days (1–365, default 30). EnerGov filters on the issued date; ACA's General Search filters on the record (application) date, so on ACA this means "applied within". |
permitTypes | string[] | no | Case-insensitive words matched against the permit type and work class (roof, electrical, residential…). |
keyword | string | no | Case-insensitive text matched against the description (EnerGov applies it server-side, ACA client-side). |
minEstimatedCost | integer | no | Drop permits whose valuation is below this amount; permits with no valuation are kept. Valuation needs includeDetails. |
maxResultsPerJurisdiction | integer | no | Newest-first cap per jurisdiction (default 500). |
includeDetails | boolean | no | Fetch each permit's detail record/page (valuation, contractor, license, owner, applicant, parcel). One extra request and one permit-detail-fetched event per permit. Default off. |
onlyNewSinceLastRun | boolean | no | Monitor mode: emit only permits not seen before (per jurisdiction, up to 50,000 ids), flagged isNew: true. Details are fetched only for new permits. |
stateStoreName | string | no | Key-value store that holds the seen-sets (default accela-energov-permit-scraper-state). |
includeRaw | boolean | no | Attach the untouched portal row (and detail) as raw. |
accelaAppId | string (secret) | no | Optional free Accela developer app id. When set, Accela jurisdictions are read through the official Construct API's anonymous mode instead of the ACA page (see FAQ). |
webhookUrl | string | no | POST target for the run summary plus up to 500 emitted permits. |
Output example
One dataset item per permit:
{"jurisdiction": "hernando-county-fl","jurisdictionName": "Hernando County, FL","permitNumber": "ELER-000154-2026","permitType": "General Electric - Residential","permitSubtype": "Electrical","workDescription": "Replace 200A service panel and meter can","status": "Issued","appliedDate": "2026-10-14T10:40:15","issuedDate": "2026-10-16T15:12:23","finalizedDate": null,"expirationDate": "2027-04-14T15:12:23","estimatedCost": 3630,"address": "1234 Example Ave, SPRING HILL, FL, 34606","city": "SPRING HILL","state": "FL","zip": "34606","parcelId": "1097388","latitude": null,"longitude": null,"contractorName": "RIVERA'S ELECTRIC INC.","contractorLicense": "ID-000000718","ownerName": null,"applicantName": "RIVERA'S ELECTRIC INC.","sourceApi": "energov","sourceUrl": "https://hernandocountyfl-energovweb.tylerhost.net/apps/selfservice#/permit/8c0f…","sourceRecordId": "8c0f…","fetchedAt": "2026-10-17T10:50:12.345Z","detailFetched": true,"isNew": true}
sourceApi is energov, accela-aca or accela-api. Without includeDetails, estimatedCost, contractorName, contractorLicense, ownerName and applicantName are null and detailFetched is false. On Accela Citizen Access the list page has no issue date, so issuedDate is null and appliedDate carries the record date. Coordinates are only available through the Accela API engine.
A portal that cannot be queried produces one error item instead of failing the run:
{ "jurisdiction": "denver-co", "jurisdictionName": "Denver, CO", "error": "CAPTCHA", "errorMessage": "Portal shows a CAPTCHA on its search page; not supported (no CAPTCHA solving)", "sourceApi": "accela-aca", "sourceUrl": "https://aca-prod.accela.com/DENVER/Cap/CapHome.aspx?module=Development&TabName=Development", "fetchedAt": "2026-10-17T10:50:12.345Z" }
Error codes: HTTP_<status>, RATE_LIMITED, BAD_RESPONSE, PORTAL_ERROR, NOT_ENERGOV, UNSUPPORTED_PORTAL, CAPTCHA, API_FORBIDDEN, FETCH_FAILED. The run's SUMMARY record (default key-value store) lists per-jurisdiction counts, pages, seconds, portal version and charges.
Jurisdictions
All 31 portals were verified live on 2026-10-17 from a datacenter IP with the exact requests the Actor sends (docs/jurisdictions.md in the repository has the evidence and the rejected candidates). Volume is the number of permits the portal returned for the previous 7 days.
| Id | Jurisdiction | Engine | Date filter | 7-day volume | Notes |
|---|---|---|---|---|---|
richmond-va | Richmond, VA | EnerGov | issued | ~270 | All permit modules incl. trades and right-of-way |
overland-park-ks | Overland Park, KS | EnerGov | issued | ~220 | Prefill / daily test |
southlake-tx | Southlake, TX | EnerGov | issued | ~70 | Prefill / daily test |
doral-fl | Doral, FL | EnerGov | issued | ~70 | |
hernando-county-fl | Hernando County, FL | EnerGov | issued | ~370 | |
riverside-county-ca | Riverside County, CA | EnerGov | issued | ~420 | Includes transport and land-use permits |
santa-fe-nm | Santa Fe, NM | EnerGov | issued | ~120 | |
danville-ca | Danville, CA | EnerGov | issued | ~40 | |
carson-ca | Carson, CA | EnerGov | issued | ~40 | |
imperial-beach-ca | Imperial Beach, CA | EnerGov | issued | 8 | |
wilmington-nc | Wilmington, NC | EnerGov | issued | ~40 | |
la-vergne-tn | La Vergne, TN | EnerGov | issued | ~40 | |
grand-traverse-county-mi | Grand Traverse County, MI | EnerGov | issued | ~220 | Incl. well & septic records |
reading-pa | Reading, PA | EnerGov | issued | 3 | Low volume |
shelton-wa | Shelton, WA | EnerGov | issued | 9 | Low volume |
snohomish-wa | Snohomish, WA | EnerGov | issued | 11 | Low volume |
rockland-county-ny | Rockland County, NY | EnerGov | issued | 3 | County plan review and health permits |
sacramento-ca | Sacramento, CA | Accela ACA | applied | 100+ | 10 rows per page |
tampa-fl | Tampa, FL | Accela ACA | applied | 100+ | |
hillsborough-county-fl | Hillsborough County, FL | Accela ACA | applied | 100+ | |
oakland-ca | Oakland, CA | Accela ACA | applied | 200+ | 20 rows per page |
san-mateo-county-ca | San Mateo County, CA | Accela ACA | applied | ~80 | 25 rows per page |
stockton-ca | Stockton, CA | Accela ACA | applied | 100+ | |
monterey-county-ca | Monterey County, CA | Accela ACA | applied | ~100 | 4 MB result pages; slower |
santa-clara-county-ca | Santa Clara County, CA | Accela ACA | applied | ~140 | 50 rows per page |
mesa-az | Mesa, AZ | Accela ACA | applied | 100+ | Module Permits |
omaha-ne | Omaha, NE | Accela ACA | applied | 100+ | Module Permits |
oklahoma-city-ok | Oklahoma City, OK | Accela ACA | applied | 100+ | Module Permits |
fort-worth-tx | Fort Worth, TX | Accela ACA | applied | 100+ | Module Development |
denver-co | Denver, CO | Accela ACA | applied | 100+ | Module Development |
charlotte-nc | Charlotte, NC | Accela ACA | applied | 100+ | City land-development records; building permits are Mecklenburg County's |
ACA's General Search caps its total at "100+" / "200+"; the Actor pages through until the window or maxResultsPerJurisdiction is exhausted. ACA rows that are unsubmitted application drafts (26TMP-…, no record page) are skipped and counted in the summary.
Pricing
Pay per event. You pay only for what the Actor produces; set a maximum cost per run in the run options to cap spend (the Actor stops cleanly when the cap is reached).
| Event | Price | Notes |
|---|---|---|
permit-scraped | $0.003 | Per dataset item: a normalized permit or an error item for a portal that could not be queried |
permit-detail-fetched | $0.005 | Per permit whose detail record/page was fetched and merged (includeDetails); in addition to permit-scraped |
portal-run | $0.01 | Per jurisdiction portal queried per run, including portals that return an error item |
| Actor start | $0.00005 | Apify platform event |
Examples: 1,000 permits from 5 portals without details ≈ $3.05; 1,000 permits with details ≈ $8.05; a daily monitor of 10 portals that finds 40 new permits with details ≈ $0.42 per day. Compute is billed by Apify separately (≈ $0.001 per 100 permits at 512 MB).
Limits and fair use
- Requests to each portal are spaced at least 1 s apart, with exponential backoff on 429/5xx; three portals run in parallel. A 30-day crawl of a large ACA city with details is a few hundred requests and takes a few minutes.
issuedWithinDaysis capped at 365 and ACA agencies commonly cap their own date range at one year.- Only public data is read. No login, no proxies, no CAPTCHA solving, no browser. A portal that shows a CAPTCHA or blocks datacenter IPs returns an
UNSUPPORTED_PORTAL/CAPTCHAerror item and is listed as unsupported indocs/jurisdictions.md. - Portal software changes: EnerGov releases differ per city (2022.3 to 2026.2 are in the registry) and Accela updates ACA several times a year. When a portal changes shape the Actor emits an error item rather than wrong data; failures are watched daily and patched.
- Memory 256–1024 MB; a run with
alland details fits comfortably in 512 MB.
Related Actors
- US Building Permits Scraper — City & County Permit Records: the same schema for 26 open-data cities and counties (Socrata, CKAN, ArcGIS, Carto).
- US Professional License Verifier: verify the contractor licenses that appear in these permits.
- Website Change Monitor: watch a permit-office news page for fee or process changes.
FAQ
Does this need proxies? No. Both portal families answer plain HTTP from datacenter IPs for every jurisdiction in the registry; the Actor never uses residential proxies. If an agency starts blocking, it is marked unsupported rather than worked around.
How is cost controlled? Every item is charged as it is saved. Set the run's maximum cost, maxResultsPerJurisdiction, a short issuedWithinDays window and leave includeDetails off unless you need valuation and contractor fields. Monitor mode pays for details only on new permits.
Why is issuedDate null on Accela portals? ACA's General Search filters and lists by the record (application) date and shows no issue date in the grid or on the detail page, so appliedDate is filled and status (Issued, Finaled, Applied…) tells you where the permit is. EnerGov portals filter on the issue date and fill issuedDate.
What does accelaAppId do? Accela's Construct API has a "no authorization required" mode for citizen apps: with a free developer-portal app id the Actor can read records (with addresses, parcels, professionals and owners in one JSON call) from agencies that allow anonymous access. The engine follows the public v4 reference and was not exercised against a live agency during the build, so treat it as best-effort: agencies that refuse return an API_FORBIDDEN error item, and removing the id switches back to the page engine.
Can you add my city? If it runs EnerGov Citizen Self Service or Accela Citizen Access with a public General Search page, usually yes. Agencies that load their search panel through partial postbacks (San Diego, Detroit, Salt Lake City, Alameda County, Santa Barbara County in our survey) or show reCAPTCHA (Fresno, Detroit) are not supported.
Can an AI agent use this? Yes. Example prompts: "List the roofing and solar permits applied for in Sacramento and Tampa in the last 7 days with contractor names." · "Every morning, find new residential permits in Overland Park and Hernando County, only ones not seen before, and POST them to my CRM webhook." · "Which contractors pulled the most electrical permits in Richmond, VA over the last 30 days?"
Legal
Public records from public portals, read with the same requests the portal's own web page sends, at a polite rate, without login or circumvention. Owner, applicant and contractor names appear as published by the agency. This data is not a consumer report and may not be used for credit, employment, insurance, housing or any other purpose covered by the Fair Credit Reporting Act (FCRA). Verify permits with the issuing agency before relying on them. Not affiliated with Accela, Inc. or Tyler Technologies, Inc.; portal and product names belong to their owners.