NYC DOB Permits & Violations Scraper avatar

NYC DOB Permits & Violations Scraper

Pricing

from $3.00 / 1,000 results

Go to Apify Store
NYC DOB Permits & Violations Scraper

NYC DOB Permits & Violations Scraper

Scrape NYC Department of Buildings (DOB) construction permits and code violations from the public NYC Open Data API. Filter by borough, address, BIN, block/lot, job/permit type, permit status, violation category, and date range.

Pricing

from $3.00 / 1,000 results

Rating

0.0

(0)

Developer

Crawler Bros

Crawler Bros

Maintained by Community

Actor stats

0

Bookmarked

2

Total users

1

Monthly active users

8 days ago

Last modified

Share

Scrape NYC Department of Buildings (DOB) construction permit and code violation records straight from the public NYC Open Data API. Search or filter by borough, address, Building Identification Number (BIN), tax block/lot, job/permit type, permit status, violation category, device number, and date range — or look up exact records by job number or violation number. HTTP-only via the public data.cityofnewyork.us Socrata API. No login, no cookies, no proxy required.

What this actor does

  • Four modes: permits, permitsByJob, violations, violationsByNumber
  • Two datasets: DOB Permit Issuance (~4 million permits) and DOB Violations (~2.5 million violations)
  • Rich filters: borough, address (house number + street), BIN, block/lot, ZIP code, job type, permit type, permit subtype, work type, permit status, filing status, permittee license type, owner business type, residential-only, self-certified-only, non-profit-owner-only, violation category, violation type code, device number, ECB number, date range (by filing/issuance/expiration/job-start date for permits, or by issue/disposition date for violations), and free-text keyword search
  • Derived fields: canonical address, a computed bbl (Borough-Block-Lot) for violations, latitude/longitude for permits, zoning special districts for permits
  • Empty fields are omitted — a record never contains null, "", or empty arrays

Output: per permit (mode = permits / permitsByJob)

  • recordType: "permit", scrapedAt
  • borough, houseNumber, streetName, address, bin, block, lot, bbl
  • zipCode, communityBoard, councilDistrict, censusTract, ntaName, specialDistrict1, specialDistrict2
  • jobNumber, jobDocNumber, jobType, permitType, permitSubtype, permitSequence
  • permitStatus, filingStatus, workType, buildingType
  • residential, selfCertified, ownerNonProfit — booleans
  • siteFill, oilGas
  • filingDate, issuanceDate, expirationDate, jobStartDate, dobRunDateYYYY-MM-DD
  • permitteeName, permitteeBusinessName, permitteePhone, permitteeLicenseType, permitteeLicenseNumber, hicLicense
  • actAsSuperintendent, superintendentName, superintendentBusinessName
  • siteSafetyManagerName, siteSafetyManagerBusinessName
  • ownerBusinessType, ownerBusinessName, ownerName, ownerAddress, ownerCity, ownerState, ownerZipCode
  • latitude, longitude
  • permitSiNo, sourceUrl

Output: per violation (mode = violations / violationsByNumber)

  • recordType: "violation", scrapedAt
  • isn — internal DOB BIS violation ID
  • borough, bin, block, lot, bbl (derived — see FAQ)
  • houseNumber, street, address
  • issueDate, dispositionDateYYYY-MM-DD
  • dispositionComments
  • violationTypeCode, violationType, violationNumber, violationCategory, number
  • deviceNumber, ecbNumber (cross-reference to the DOB ECB Violations dataset — present on ~8% of records), description
  • sourceUrl

Input

FieldTypeDefaultDescription
modestringpermitspermits / permitsByJob / violations / violationsByNumber
boroughstringNYC borough (mode=permits / mode=violations)
houseNumberstringStreet/house number, combine with streetName
streetNamestringStreet name (case-insensitive)
binstringBuilding Identification Number
blockstringTax block number, combine with lot
lotstringTax lot number, combine with block
zipCodestring5-digit ZIP (mode=permits)
jobTypestringDOB job type (mode=permits): A1/A2/A3/DM/NB/SG
permitTypestringDOB permit type (mode=permits): AL/DM/EQ/EW/FO/NB/PL/SG
permitSubtypestringDOB permit subtype (mode=permits), e.g. BL/FN/SH/SP
workTypestringDOB work type (mode=permits), e.g. BL/PL/MH/SP
permitteeLicenseTypestringPermittee's professional license type (mode=permits), e.g. GC/MP/RA/PE
ownerBusinessTypestringProperty owner's business type (mode=permits), e.g. CORPORATION/INDIVIDUAL/NYCHA
permitStatusstringIn Process / Issued / Re-Issued / Revoked (mode=permits)
filingStatusstringInitial / Renewal (mode=permits)
residentialOnlybooleanfalseOnly residential permits (mode=permits)
selfCertifiedOnlybooleanfalseOnly self-certified filings — no DOB plan review (mode=permits)
nonProfitOwnerOnlybooleanfalseOnly permits where the owner is flagged non-profit (mode=permits)
dateFieldstringfilingDateWhich permit date column to filter/sort by (mode=permits)
dateFromstringYYYY-MM-DD, inclusive lower bound
dateTostringYYYY-MM-DD, inclusive upper bound
keywordstringFree-text search
jobNumbersarrayDOB job numbers to fetch (mode=permitsByJob)
violationCategorystringViolation category (mode=violations)
violationTypeCodestringViolation type code, e.g. elevator/boiler/facade (mode=violations)
deviceNumberstringElevator/boiler device number (mode=violations)
ecbNumberstringAssociated ECB violation number (mode=violations)
violationDateFieldstringissueDateWhich violation date column dateFrom/dateTo/sorting apply to: issue date or disposition date (mode=violations)
violationNumbersarrayExact violation numbers to fetch (mode=violationsByNumber)
sortAscendingbooleanfalseSort oldest-first instead of newest-first
appTokenstringOptional free Socrata app token for higher rate limits
maxItemsint20Hard cap on emitted records (1–10000)

Example: permits issued in Manhattan for new buildings

{
"mode": "permits",
"borough": "MANHATTAN",
"jobType": "NB",
"permitStatus": "ISSUED",
"maxItems": 100
}

Example: permit history for a specific job number

{
"mode": "permitsByJob",
"jobNumbers": ["340733647"]
}

Example: active elevator violations in Queens, last 12 months

{
"mode": "violations",
"borough": "QUEENS",
"violationCategory": "V-DOB VIOLATION - ACTIVE",
"violationTypeCode": "E",
"dateFrom": "2025-07-01",
"dateTo": "2026-07-01",
"maxItems": 200
}

Example: self-certified corporate-owned permits in Brooklyn

{
"mode": "permits",
"borough": "BROOKLYN",
"ownerBusinessType": "CORPORATION",
"selfCertifiedOnly": true,
"maxItems": 100
}

Example: violations at a specific address

{
"mode": "violations",
"houseNumber": "222",
"streetName": "4TH AVE",
"borough": "MANHATTAN"
}

Use cases

  • Real estate due diligence — pull a property's full permit and violation history before acquisition
  • Contractor / permittee research — track a licensed contractor's active and historical permits
  • Compliance monitoring — watch for new violations by borough, category, or device type (elevators, boilers)
  • Urban development analysis — study construction activity trends by borough, job type, or time period
  • PropTech / data products — enrich property records with NYC DOB permit and violation history

FAQ

What is the data source? The NYC Department of Buildings' public datasets on NYC Open Data, served via the Socrata Open Data API (SODA): DOB Permit Issuance and DOB Violations.

How fresh is the data? Both datasets are updated regularly by NYC DOB (the Permit Issuance dataset carries a dobRunDate field showing the last refresh date per record). This actor always queries the live dataset — there is no caching or staleness beyond NYC's own publishing schedule.

Is this affiliated with NYC or the Department of Buildings? No. This is an independent, third-party actor that queries NYC's public open-data API. It is not affiliated with or endorsed by the City of New York.

Why does borough sometimes not appear on a violation record? The Violations dataset stores borough as a legacy internal code. The vast majority of rows use an unambiguous code (1–5, or M/Q/S), which is mapped to a readable borough name. A small number of legacy rows use an ambiguous code that cannot be reliably distinguished between Bronx and Brooklyn, or use garbage/blank values — those records simply omit the borough field rather than guess.

Why is bbl present on some violation records but not others? DOB Violations doesn't include a Borough-Block-Lot (BBL) column directly, so this actor computes it from the row's borough, block, and lot when all three are present and valid (matching the same 10-digit BBL format the Permit Issuance dataset provides natively). Rows with a missing, ambiguous, or placeholder block/lot don't get a computed BBL.

Do I need a Socrata app token? No — the actor works fully without one. An optional free app token (get one at data.cityofnewyork.us/profile/app_tokens) raises the API's rate limit ceiling for very large runs, but isn't required for normal use.

What date format should I use for dateFrom/dateTo? Always YYYY-MM-DD (e.g. 2025-01-31) regardless of which dataset/mode you're querying — the actor handles the underlying format differences between the two source datasets internally.

Can I look up a specific permit or violation by ID? Yes — use mode=permitsByJob with jobNumbers, or mode=violationsByNumber with violationNumbers.

Does this cover ECB (Environmental Control Board) violations too? The DOB Violations dataset used here covers DOB-issued civil penalties. NYC also publishes a separate "DOB ECB Violations" dataset for summonses adjudicated by OATH/ECB, which is out of scope for this actor.