# Austin Building Permits Scraper (`crawlerbros/austin-building-permits-scraper`) Actor

Scrape the City of Austin issued construction permits dataset (Building, Electrical, Mechanical, Plumbing, Driveway/Sidewalk). Filter by type, class, status, jurisdiction, district, valuation, or date; lookup by permit number, address, contractor, or TCAD ID. Free Socrata API, no login.

- **URL**: https://apify.com/crawlerbros/austin-building-permits-scraper.md
- **Developed by:** [Crawler Bros](https://apify.com/crawlerbros) (community)
- **Categories:** Automation, Lead generation, Developer tools
- **Stats:** 2 total users, 1 monthly users, 100.0% runs succeeded, 0 bookmarks
- **User rating**: No ratings yet

## Pricing

from $3.00 / 1,000 results

This Actor is paid per event and usage. You are charged both the fixed price for specific events and for Apify platform usage.
Since this Actor supports Apify Store discounts, the price gets lower the higher subscription plan you have.

Learn more: https://docs.apify.com/platform/actors/running/actors-in-store#pay-per-event

## What's an Apify Actor?

Actors are web data automations that power AI and operations. They run on the Apify platform to scrape websites, process data, connect APIs, and automate workflows.
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.
Actors are written with capital "A".

## 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.
The best way to integrate Actors is as follows.

- **AI agents and MCP clients** — the [Apify MCP server](https://docs.apify.com/integrations/mcp.md) at `https://mcp.apify.com` (remote, streamable HTTP, OAuth on first use).
- **Agentic workflows and local Actor development** — [Agent Skills](https://apify.com/.well-known/agent-skills/index.json) with the [Apify CLI](https://docs.apify.com/cli/docs.md): `npm install -g apify-cli`, then `apify login`.
- **JavaScript/TypeScript projects** — the official [JS/TS client](https://docs.apify.com/api/client/js/docs.md): `npm install apify-client`.
- **Python projects** — the official [Python client](https://docs.apify.com/api/client/python/docs.md): `pip install apify-client`.
- **Any other language** — the [REST API](https://docs.apify.com/api/v2.md).

For usage examples, see the [API](#api) section below.

For more details, see Apify documentation as [Markdown index](https://docs.apify.com/llms.txt) and [Markdown full-text](https://docs.apify.com/llms-full.txt).

# README

## Austin Building Permits Scraper

Scrape the official **City of Austin** issued construction permit dataset. Search or filter Austin building permits by permit type, class, work class, status, jurisdiction, council district, zip code, contractor, valuation, square footage, or applied/issued/status date — or look up permits by permit number, property address, contractor name, TCAD property ID, or master permit number. Powered by the public City of Austin Open Data (Socrata) API. No login, no API key, no proxy required.

### What this actor does

- **Six modes:** `search` (filter/browse), `byPermitNumber`, `byAddress`, `byContractor`, `byTcadId`, `byMasterPermitNumber`
- **Rich filters:** permit type/class/work class, status, jurisdiction, council district, zip code, valuation & square-footage ranges, applied/issued/status-date ranges, full-text search, and a geographic radius around a lat/lon point
- **Every issued permit** — Building, Electrical, Mechanical, and Plumbing Permits, plus Driveway/Sidewalk permits, issued by the City of Austin
- **Contractor, applicant, valuation & geo data** on every permit — company/individual names, per-trade valuations, square footage, latitude/longitude, council district
- **Empty fields are omitted** — a permit missing a completion date or a contractor record simply has no such field, never a placeholder

### Output per permit record

- `permitNumber` — City of Austin permit number (e.g. `2026-077081 DS`)
- `permitType`, `permitTypeDesc` — permit type code (`BP`/`EP`/`MP`/`PP`/`DS`) and its description
- `permitClassMapped`, `permitClass` — Residential/Commercial mapping and the detailed permit class code
- `workClass` — type of work performed (New, Remodel, Repair, Demolition, etc.)
- `condominium` — boolean, only present when the dataset records a Yes/No value
- `permitLocation` — the project location/name text recorded on the permit
- `description` — free-text work description
- `tcadId` — Travis Central Appraisal District property identifier
- `legalDescription`
- `appliedDate`, `issueDate`, `dayIssued`, `calendarYearIssued`, `fiscalYearIssued`, `issuedInLast30Days`
- `issueMethod` — how the permit was issued (Permit Center, Online)
- `status`, `statusDate`, `expiresDate`, `completedDate`
- `totalExistingBldgSqft`, `remodelRepairSqft`, `totalNewAddSqft`, `totalLotSqft`
- `totalJobValuation`, `totalValuationRemodel` (USD)
- `buildingValuation`, `buildingValuationRemodel`, `electricalValuation`, `electricalValuationRemodel`, `mechanicalValuation`, `mechanicalValuationRemodel`, `plumbingValuation`, `plumbingValuationRemodel`, `medGasValuation`, `medGasValuationRemodel` (USD, only present when the permit has that trade's valuation)
- `numberOfFloors`, `housingUnits`
- `streetAddress`, `city`, `state`, `zipcode`, `fullAddress`
- `councilDistrict` — Austin City Council district (1-10)
- `jurisdiction` — governing jurisdiction (e.g. `AUSTIN FULL PURPOSE`, `AUSTIN 2 MILE ETJ`)
- `projectId`, `masterPermitNumber`
- `latitude`, `longitude`
- `contractorTrade`, `contractorCompanyName`, `contractorFullName`, `contractorPhone`, `contractorAddress1`, `contractorAddress2`, `contractorCity`, `contractorZip`
- `applicantFullName`, `applicantOrganization`, `applicantPhone`, `applicantAddress1`, `applicantAddress2`, `applicantCity`, `applicantZip`
- `certificateOfOccupancy` — boolean, only present when the dataset records a Yes/No value
- `rowId` — stable Socrata row identifier
- `sourceUrl` — direct link to this permit's page on the City of Austin permit-search portal (falls back to a direct open-data API query for the rare row missing that link)
- `recordType: "buildingPermit"`, `scrapedAt`

### Input

| Field | Type | Default | Description |
|---|---|---|---|
| `mode` | string | `search` | `search` (filter/browse), `byPermitNumber`, `byAddress`, `byContractor`, `byTcadId`, or `byMasterPermitNumber` |
| `searchQuery` | string | – | Full-text search across description/address/contractor text fields (mode=search) |
| `descriptionKeyword` | string | – | Case-insensitive substring match on the work description |
| `permitNumbers` | array | – | Exact permit numbers to fetch (mode=byPermitNumber) |
| `streetAddress` | string | – | Property street address, partial match (mode=byAddress) |
| `contractorName` | string | – | Contractor company or individual name, partial match (mode=byContractor) |
| `tcadIds` | array | – | Exact TCAD property IDs to fetch (mode=byTcadId) |
| `masterPermitNumbers` | array | – | Exact master permit numbers to fetch all sub-permits for (mode=byMasterPermitNumber) |
| `permitType` | string | any | One of 5 permit types (Building, Electrical, Mechanical, Plumbing, Driveway/Sidewalks) |
| `permitClassMapped` | string | any | `Residential` or `Commercial` |
| `permitClass` | string | any | One of 66 detailed permit class codes |
| `workClass` | string | any | One of 32 work-class values (New, Remodel, Demolition, etc.) |
| `status` | string | any | One of 24 current permit statuses |
| `jurisdiction` | string | any | One of 37 governing jurisdictions |
| `issueMethod` | string | any | `Permit Center` or `Online` |
| `councilDistrict` | string | any | Austin City Council district 1-10 |
| `zipcode` | string | any | One of 58 zip codes covered by the dataset |
| `city` | string | any | One of 28 property cities covered by the dataset |
| `condominiumOnly` | boolean | `false` | Only include permits flagged as condominium projects |
| `certificateOfOccupancyOnly` | boolean | `false` | Only include permits that received a certificate of occupancy |
| `issuedInLast30DaysOnly` | boolean | `false` | Only include permits the city flagged as issued in the last 30 days |
| `appliedDateFrom` / `appliedDateTo` | string | – | ISO date range (YYYY-MM-DD) on the applied date |
| `issueDateFrom` / `issueDateTo` | string | – | ISO date range (YYYY-MM-DD) on the issued date |
| `statusDateFrom` / `statusDateTo` | string | – | ISO date range (YYYY-MM-DD) on the status-change date |
| `minTotalJobValuation` / `maxTotalJobValuation` | number | – | Total job valuation bounds (USD, 0-1,000,000,000) |
| `minTotalNewAddSqft` / `maxTotalNewAddSqft` | number | – | New/added square footage bounds (0-10,000,000) |
| `nearLatitude` / `nearLongitude` | number | – | Only include permits within `nearRadiusMeters` of this point (mode=search) |
| `nearRadiusMeters` | number | `2000` | Radius in meters for the geographic filter (1-20000); only applies when both lat/lon are set |
| `sortBy` | string | `issueDateDesc` | Sort order — issued date, applied date, status date, or total job valuation |
| `appToken` | string | – | Optional free Socrata app token for higher rate limits |
| `maxItems` | int | `50` | Hard cap on emitted records (1-10000) |

#### Example: browse the latest issued permits

```json
{
  "mode": "search",
  "sortBy": "issueDateDesc",
  "maxItems": 20
}
```

#### Example: lookup by permit number

```json
{
  "mode": "byPermitNumber",
  "permitNumbers": ["2026-077081 DS"]
}
```

#### Example: all permits at a specific address

```json
{
  "mode": "byAddress",
  "streetAddress": "912 Bastrop Hwy"
}
```

#### Example: all permits by a specific contractor

```json
{
  "mode": "byContractor",
  "contractorName": "Engen Contracting"
}
```

#### Example: all permits on a specific TCAD property

```json
{
  "mode": "byTcadId",
  "tcadIds": ["0307200403"]
}
```

#### Example: all sub-permits under a master project

```json
{
  "mode": "byMasterPermitNumber",
  "masterPermitNumbers": ["12674346"]
}
```

#### Example: high-value new-construction building permits in a council district

```json
{
  "mode": "search",
  "permitType": "BP",
  "councilDistrict": "3",
  "minTotalJobValuation": 500000,
  "maxItems": 100
}
```

#### Example: residential pool permits issued in 2026

```json
{
  "mode": "search",
  "descriptionKeyword": "pool",
  "permitClassMapped": "Residential",
  "issueDateFrom": "2026-01-01",
  "issueDateTo": "2026-12-31",
  "maxItems": 200
}
```

#### Example: permits within 2km of downtown Austin

```json
{
  "mode": "search",
  "nearLatitude": 30.2672,
  "nearLongitude": -97.7431,
  "nearRadiusMeters": 2000,
  "maxItems": 100
}
```

### Use cases

- **Real estate research** — check permit history, open work, and total job valuation for a property before buying or renting
- **Contractor / architect prospecting** — find recent new-construction or remodel permits by council district, permit class, or valuation range
- **Contractor due diligence** — pull a contractor's full permit history by company or individual name
- **Market intelligence** — track construction activity, demolition volume, or square-footage growth trends across Austin and surrounding jurisdictions
- **Journalism & policy research** — investigate construction trends, permit-processing timelines, or ETJ (extraterritorial jurisdiction) development activity
- **Academic research** — bulk-export permit data for urban-planning or housing studies

### FAQ

**What is the data source?**
The City of Austin Development Services Department's "Issued Construction Permits" dataset, published on the City of Austin Open Data portal (Socrata, dataset ID `3syk-w9eu`) and refreshed regularly by the city.

**Is this affiliated with the City of Austin?**
No. This is an independent, third-party actor built on Austin's public open-data API.

**What area does this dataset cover?**
Permits issued within the City of Austin's full-purpose jurisdiction, its extraterritorial jurisdiction (ETJ), and several neighboring municipalities (Lakeway, Bee Cave, West Lake Hills, Rollingwood, Sunset Valley, Pflugerville, and others) that share permitting with the city — see the `jurisdiction` field on each record.

**What does `permitClassMapped` vs `permitClass` mean?**
`permitClassMapped` is a simplified Residential/Commercial rollup. `permitClass` is the detailed permit class code the city assigns (e.g. `R- 101 Single Family Houses`, `C-1000 Commercial Remodel`).

**Why do some valuation fields (e.g. `electricalValuation`) not appear on every record?**
Each permit only carries the trade-specific valuation fields relevant to its scope of work. A pure electrical permit typically has `electricalValuation` but not `buildingValuation`; the actor omits fields the city didn't populate rather than showing `0` or `null`.

**How does the address lookup (`byAddress`) work?**
Supply any part of the property's street address in `streetAddress` — the match is case-insensitive and partial (substring), since the source dataset stores the full address as a single text field rather than separate number/street columns.

**What is a master permit number, and when should I use `byMasterPermitNumber`?**
Large or multi-trade projects (e.g. a big commercial build with separate building, electrical, mechanical, and plumbing permits) are often filed under one shared `masterPermitNumber`. Use `byMasterPermitNumber` to pull every sub-permit tied to that project in one call instead of looking each one up individually. Not every permit has a master permit number — smaller, standalone permits usually don't.

**Why is `sourceUrl` sometimes a City of Austin permit-portal link and not the open-data API?**
Most rows carry a direct link to the permit's page on `abc.austintexas.gov`, the city's own public permit-search system — the actor uses that whenever the dataset provides it, since it's the most useful link for a human reader. On the rare row missing that link, the actor falls back to a direct Socrata API query that returns just that row.

**How fresh is the data?**
The City of Austin Open Data portal refreshes this dataset on a regular schedule (typically daily). The actor always reads the latest published snapshot at run time.

**Are there rate limits?**
The Socrata API allows unauthenticated access with reasonable limits. Supplying a free Socrata app token (optional) raises those limits, but the actor works without one.

# Actor input Schema

## `mode` (type: `string`):

What to fetch.

## `searchQuery` (type: `string`):

Free-text search across permit description, address, contractor, and other text fields (mode=search). Leave blank to browse without a text query.

## `descriptionKeyword` (type: `string`):

Case-insensitive substring match on the permit's work description. Example: `pool`.

## `permitNumbers` (type: `array`):

Exact City of Austin permit numbers to fetch. Example: `2026-077081 DS`.

## `streetAddress` (type: `string`):

Property street address to search for (partial, case-insensitive match). Example: `912 Bastrop Hwy`.

## `tcadIds` (type: `array`):

Exact Travis Central Appraisal District (TCAD) property IDs to fetch permits for. Example: `0307200403`.

## `masterPermitNumbers` (type: `array`):

Exact master permit numbers to fetch all sub-permits for (multiple trade/phase permits filed under one master project). Example: `12674346`.

## `contractorName` (type: `string`):

Contractor company or individual name to search for (partial, case-insensitive match against both company and full name). Example: `Engen Contracting`.

## `permitType` (type: `string`):

Filter to a single permit type.

## `permitClassMapped` (type: `string`):

Filter to Residential or Commercial permits.

## `permitClass` (type: `string`):

Filter to a single detailed permit class code.

## `workClass` (type: `string`):

Filter to a single type of work being performed.

## `status` (type: `string`):

Filter to a single current permit status.

## `jurisdiction` (type: `string`):

Filter to a single governing jurisdiction.

## `issueMethod` (type: `string`):

Filter by how the permit was issued.

## `councilDistrict` (type: `string`):

Filter to a single Austin City Council district (1-10).

## `zipcode` (type: `string`):

Filter to a single property zip code.

## `city` (type: `string`):

Filter to a single property city.

## `condominiumOnly` (type: `boolean`):

Only include permits flagged as condominium projects.

## `certificateOfOccupancyOnly` (type: `boolean`):

Only include permits that received a certificate of occupancy.

## `issuedInLast30DaysOnly` (type: `boolean`):

Only include permits the city flagged as issued within the last 30 days (as of the dataset's own refresh, not the run time).

## `appliedDateFrom` (type: `string`):

Drop permits applied before this date.

## `appliedDateTo` (type: `string`):

Drop permits applied after this date.

## `issueDateFrom` (type: `string`):

Drop permits issued before this date.

## `issueDateTo` (type: `string`):

Drop permits issued after this date.

## `statusDateFrom` (type: `string`):

Drop permits status change before this date.

## `statusDateTo` (type: `string`):

Drop permits status change after this date.

## `minTotalJobValuation` (type: `number`):

Drop permits with a lower total job valuation than this.

## `maxTotalJobValuation` (type: `number`):

Drop permits with a higher total job valuation than this.

## `minTotalNewAddSqft` (type: `number`):

Drop permits with less new/added building square footage than this.

## `maxTotalNewAddSqft` (type: `number`):

Drop permits with more new/added building square footage than this.

## `nearLatitude` (type: `number`):

Only include permits within `nearRadiusMeters` of this latitude/longitude point. Must be combined with Near longitude. Example: `30.2672` (downtown Austin).

## `nearLongitude` (type: `number`):

Longitude for the geographic radius filter. Must be combined with Near latitude. Example: `-97.7431`.

## `nearRadiusMeters` (type: `number`):

Radius in meters around the Near latitude/longitude point. Only applies when both are set.

## `sortBy` (type: `string`):

Sort order for results.

## `appToken` (type: `string`):

Optional free Socrata app token to raise API rate limits. Get one at https://data.austintexas.gov/profile/app\_tokens. Not required — the actor works without it.

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

Hard cap on emitted records.

## Actor input object example

```json
{
  "mode": "search",
  "permitNumbers": [],
  "tcadIds": [],
  "masterPermitNumbers": [],
  "permitType": "",
  "permitClassMapped": "",
  "permitClass": "",
  "workClass": "",
  "status": "",
  "jurisdiction": "",
  "issueMethod": "",
  "councilDistrict": "",
  "zipcode": "",
  "city": "",
  "condominiumOnly": false,
  "certificateOfOccupancyOnly": false,
  "issuedInLast30DaysOnly": false,
  "nearRadiusMeters": 2000,
  "sortBy": "issueDateDesc",
  "maxItems": 50
}
```

# Actor output Schema

## `permits` (type: `string`):

Dataset containing all scraped Austin building permit records.

# 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 = {
    "mode": "search",
    "permitNumbers": [],
    "tcadIds": [],
    "masterPermitNumbers": [],
    "permitType": "",
    "permitClassMapped": "",
    "permitClass": "",
    "workClass": "",
    "status": "",
    "jurisdiction": "",
    "issueMethod": "",
    "councilDistrict": "",
    "zipcode": "",
    "city": "",
    "condominiumOnly": false,
    "certificateOfOccupancyOnly": false,
    "issuedInLast30DaysOnly": false,
    "nearRadiusMeters": 2000,
    "sortBy": "issueDateDesc",
    "maxItems": 50
};

// Run the Actor and wait for it to finish
const run = await client.actor("crawlerbros/austin-building-permits-scraper").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 = {
    "mode": "search",
    "permitNumbers": [],
    "tcadIds": [],
    "masterPermitNumbers": [],
    "permitType": "",
    "permitClassMapped": "",
    "permitClass": "",
    "workClass": "",
    "status": "",
    "jurisdiction": "",
    "issueMethod": "",
    "councilDistrict": "",
    "zipcode": "",
    "city": "",
    "condominiumOnly": False,
    "certificateOfOccupancyOnly": False,
    "issuedInLast30DaysOnly": False,
    "nearRadiusMeters": 2000,
    "sortBy": "issueDateDesc",
    "maxItems": 50,
}

# Run the Actor and wait for it to finish
run = client.actor("crawlerbros/austin-building-permits-scraper").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 '{
  "mode": "search",
  "permitNumbers": [],
  "tcadIds": [],
  "masterPermitNumbers": [],
  "permitType": "",
  "permitClassMapped": "",
  "permitClass": "",
  "workClass": "",
  "status": "",
  "jurisdiction": "",
  "issueMethod": "",
  "councilDistrict": "",
  "zipcode": "",
  "city": "",
  "condominiumOnly": false,
  "certificateOfOccupancyOnly": false,
  "issuedInLast30DaysOnly": false,
  "nearRadiusMeters": 2000,
  "sortBy": "issueDateDesc",
  "maxItems": 50
}' |
apify call crawlerbros/austin-building-permits-scraper --silent --output-dataset

```

## MCP server setup

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

```

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/UcFkbQ47V2dvPLqx5/builds/4A5MBc3zjteykPw95/openapi.json
