Accessory dwelling units (ADUs, also called granny flats, backyard cottages or DADUs) are one of the biggest residential construction trends in the US. Each one is a $100k to $300k project that needs a permit, and those permits are public. If you sell windows, cabinets, solar, HVAC, flooring, insurance, construction loans or property management, a new ADU permit is a strong lead.

This post shows how to find every ADU permit issued in the last 90 days across several counties and cities with one Python script against official open-data APIs.

Run on Oct 22, 2026, the script found 156 ADU permits in 90 days:

  • San Diego County, CA: 87 permits, average declared value $223,539
  • Pierce County, WA: 35 permits (Pierce doesn't fill in a value for most of them)
  • Mesa, AZ: 21 permits, average $194,926
  • Corona, CA: 12 permits, average $208,027
  • Marin County, CA: 1 permit, $100,000

The data sources

Area Dataset Text searched
San Diego County, CA data.sandiegocounty.gov red2-qccu work description and scope code
Corona, CA corstat.coronaca.gov 2agx-camz description and permit subtype
Marin County, CA data.marincounty.gov mkbn-caye description and construction type
Pierce County, WA open.piercecountywa.gov nhnt-v7ka work description and work type
Mesa, AZ citydata.mesaaz.gov dzpk-hxfb description and type of work

All five are Socrata portals, so one function handles them all. Each source just needs its own date, text and value column names.

The script

import requests from datetime import date, timedelta since = (date.today() - timedelta(days=90)).isoformat() TERMS = ["ADU", "ACCESSORY DWELLING", "GRANNY", "JADU", "BACKYARD COTTAGE", "DADU"] SOURCES = [ # label, domain, dataset, date field, description fields, value field  ("San Diego County, CA", "data.sandiegocounty.gov", "red2-qccu", "issued_date", ["use", "primary_scope_code"], "valuation"), ("Corona, CA", "corstat.coronaca.gov", "2agx-camz", "issued", ["description", "permitsubtype"], "jobvalue"), ("Marin County, CA", "data.marincounty.gov", "mkbn-caye", "issued_date", ["description", "construction"], "construction_value"), ("Pierce County, WA", "open.piercecountywa.gov", "nhnt-v7ka", "issueddate", ["workdescription", "worktype"], "projectvalue"), ("Mesa, AZ", "citydata.mesaaz.gov", "dzpk-hxfb", "issued_date", ["description_of_work", "type_of_work"], "total_valuation"), ] def adus(label, domain, ds, dfield, fields, vfield): like = " OR ".join(f"upper({f}) like '%{t}%'" for f in fields for t in TERMS) rows = requests.get(f"https://{domain}/resource/{ds}.json", params={ "$where": f"{dfield} >= '{since}' AND ({like})", "$limit": 5000}, timeout=120).json() # "ADU" also matches words like "GRADUATE"/"ADULT": keep rows where it is a whole word  import re rx = re.compile(r"\b(J?ADU|DADU|ACCESSORY DWELLING|GRANNY|BACKYARD COTTAGE)\b", re.I) return [r for r in rows if any(rx.search(str(r.get(f, ""))) for f in fields)] total = 0 for s in SOURCES: rows = adus(*s) vals = [float(r[s[5]]) for r in rows if r.get(s[5]) not in (None, "")] avg = sum(vals) / len(vals) if vals else 0 total += len(rows) print(f"{s[0]}: {len(rows)} ADU permits in 90 days, average declared value ${avg:,.0f}") print("total:", total) 

Three things that will trip you up

  1. "ADU" hides inside other words. A plain like '%ADU%' also matches GRADUATE, ADULT and ADULTS. The script lets the server do a broad match, then keeps only whole-word hits in Python with a regex.
  2. Every place names it differently. California permits say ADU or JADU (junior ADU), Washington uses DADU (detached ADU) and "backyard cottage", and older records say "granny unit". Add local terms to TERMS.
  3. Valuation is often blank or zero. Pierce County leaves the value empty on most ADU permits, so the average comes out as $0. Treat value as a bonus field and don't filter on it.

Turning it into a lead list

  • Sort by issue date: the weeks right after issue are when owners pick finishes, windows and HVAC.
  • Group by ZIP code to plan mailers or canvassing routes.
  • If you're a lender or insurer, ADU permits with a high declared value are the best fit.
  • Keep it to the property address and permit. You don't need the owner's name to market to a property.

Optional: I run this as a hosted, scheduled search across 47 cities and counties in 20 states: ADU Permits: Accessory Dwelling Unit Leads (ready-made search) (paid per result). Disclosure: it's my tool. The script above does the same job for free.