Philadelphia L&I - Code Violations, Inspections & Complaints
Pricing
from $0.03 / 1,000 philadelphia l&i code case records
Philadelphia L&I - Code Violations, Inspections & Complaints
Philadelphia L&I enforcement records (public open data, 5.2M rows, three linked tables): violation notices, inspector visit outcomes and resident complaints, with violation code and title, case status, dates, address, owner, parcel and geocode.
Pricing
from $0.03 / 1,000 philadelphia l&i code case records
Rating
0.0
(0)
Developer
Wenhao Yang
Maintained by CommunityActor stats
0
Bookmarked
2
Total users
1
Monthly active users
a day ago
Last modified
Categories
Share
The enforcement record of the Philadelphia Department of Licenses & Inspections: 5,200,849 rows across three linked tables from the City's current L&I system, spanning 2007 to today.
L&I is the City's building-code and property-maintenance enforcement arm. A case moves through three stages, and this actor carries all three rather than making you buy them separately or guess which one answers your question:
| Record set | Rows | What it is |
|---|---|---|
violations | 2,019,604 | The notices themselves - what was cited, under which code, and what happened |
investigations | 2,117,950 | Inspector visits and their outcomes - passed, failed, closed |
complaints | 1,063,295 | What a resident reported, and what came of it |
All three are keyed on the case number, so a violation and its inspections share an identifier.
Low cost
From $0.00005 per record, down to $0.00003 at Gold Pay-per-event: you are charged per record delivered, and nothing for the query.
What you get
| Field | Meaning |
|---|---|
caseNumber | The L&I case. Links a violation to its inspections |
violationCode / violationCodeTitle | What was cited - the code and its plain-English title (99.9% populated) |
violationStatus / caseStatus | Where it stands. Violations: COMPLIED 1,571,553 / CLOSEDCASE 124,309 / CLOSED 102,698 / OPEN 93,150 plus 10 more |
caseType | NOTICE OF VIOLATION 621,558 / SITE VIOLATION NOTICE 21,279 / WARNING 1,492 and 3 more |
violationDate / caseCreatedDate / violationResolutionDate / mostRecentInvestigation | The dates, from 2007-01-01 forward |
investigationType / investigationStatus / investigationCompleted | The inspector's visit - HCEU INSP 677,596 / PRECOURT 142,381 / CSUINITIAL 131,904 and 66 more types; outcomes FAILED 1,273,492 / PASSED 565,376 / CLOSED 261,849 |
complaintCode / complaintCodeName / complaintDate / complaintStatus | The complaint - MAINTENANCE RESIDENTIAL 169,545 / COMMUNITY LIFE IMPROVEMENT PROGRAM 84,181 / PROPERTY MAINTENANCE COMPLAINT EXTERIOR 79,769 and 134 more |
ticket311 | The linked Philly311 ticket, where one exists |
underAppeal / publicNotice / caseResponsibility / unitResponsible | Case handling |
address / zip / censusTract / councilDistrict | The property |
opaOwner / opaAccountNumber / parcelId | Owner of record, OPA account and parcel |
latitude / longitude / jobId | Coordinates and the L&I system's job id |
Modes
rows(default) - records of the chosencorpusmatching your filters.aggregate- one count row per group, with the dimensions that record set actually has.
Example inputs
Every inspection under one case - caseNumber is the number that links a violation to the inspections it produced.
{ "corpus": "investigations", "caseNumber": "CF-2026-073037" }
Notices where the case is still in violation - caseStatus is available on the violations and complaints record sets.
{ "corpus": "violations", "caseStatus": "IN VIOLATION", "maxResults": 25 }
Complaints filed in one ZIP - corpus picks the record set; each one carries its own filters.
{ "corpus": "complaints", "zip": "19139", "maxResults": 25 }
What neighbours complain about - one count per complaint code on the complaints record set.
{ "corpus": "complaints", "mode": "aggregate", "groupBy": "complaintCode" }
Fail the inspection, then check the notice - status filters the investigations record set; the case number then resolves against corpus=violations.
{ "corpus": "investigations", "status": "FAILED" }
How cases end in one district - councilDistrict is available on the violations record set; district 5 holds 96,107 violation rows.
{ "corpus": "violations", "councilDistrict": 5, "mode": "aggregate", "groupBy": "caseStatus" }
Filters and groupings are per record set
The three tables have genuinely different columns, and this actor does not paper over that. A filter that does not exist on the record set you chose is rejected with an error rather than quietly ignored - so you never receive unfiltered rows believing you had filtered them.
The clearest case: councilDistrict is populated on the violations (640,943 rows) and complaints (415,435) tables, and the investigations table has the column but every single one of its 2,117,950 rows is empty. Filtering on it there would return zero rows and read as "no cases in that district", which is the wrong conclusion. It is refused on that record set instead.
Complaints do not always become cases
caseNumber is populated on only 27.3% of complaints, and complaintStatus on 39.2%. Most complaints are resolved without ever opening an L&I case, so the case number is a partial link across the three tables, not a guarantee. Joining the complaints table to the violations table on case number is correct where a case number exists and meaningless where it does not.
The old L&I tables are still online - do not use them
Two similarly-named services from L&I's previous system, LI_VIOLATIONS (1,451,562 rows) and LI_PERMITS (1,051,902 rows), remain published. Both are frozen in March 2020: LI_VIOLATIONS holds nothing after 2020-03-12, and 2020 carries only 18,090 rows against 108,346 in 2017, 117,090 in 2018 and 121,805 in 2019. They are retired legacy that the City has not taken down.
This actor reads the live tables. If you have seen those older services and wondered why they stopped, that is why.
Example output
One complaint - corpus=complaints, zip=19139 returns records like this one:
{"platform": "philly-li-violations","source": "philadelphia-licenses-inspections","mode": "rows","groupKey": "","groupCount": "","groupBy": "","corpus": "complaints","address": "38 S 54TH ST","addressObjectId": "15486788","caseCompletedDate": "","caseCreatedDate": "","caseNumber": "","casePriority": "","caseResponsibility": "","caseStatus": "","caseType": "","censusTract": "008500","complaintCode": "WNP","complaintCodeName": "WORK UNDERWAY WITHOUT PERMITS","complaintDate": "2026-09-22","complaintNumber": "CM-2026-129370","complaintResolutionDate": "","complaintStatus": "IN REVIEW","councilDistrict": "3","initialInvestigationDate": "","investigationCompleted": "","investigationProcessId": "","investigationStatus": "","investigationType": "","jobId": "","latitude": "2675079.99501881","longitude": "238159.5386170289","mostRecentInvestigation": "","opaAccountNumber": "603147400","opaOwner": "SAAT CAPITAL INVESTMENTS LLC","parcelId": "200870","publicNotice": "","systemOfRecord": "ECLIPSE","ticket311": "","underAppeal": "","unit": "","unitResponsible": "CONSTRUCTION COMPLAINT INVESTIGATOR","unitType": "","violationCode": "","violationCodeTitle": "","violationDate": "","violationNumber": "","violationResolutionCode": "","violationResolutionDate": "","violationStatus": "","zip": "19139-3311","sourceUpdatedAt": "2026-09-23"}
corpus=complaints, mode=aggregate, groupBy=complaintCode - one row per group:
MR 169,545VL 100,484CP 84,181PME 79,769BC 59,622
Source
Counts below are a live snapshot - the layers are edited continuously, so exact figures move between reads. The order of magnitude and the ratios are stable.
City of Philadelphia, Department of Licenses & Inspections, published on the City's ArcGIS open-data service as VIOLATIONS, CASE_INVESTIGATIONS and COMPLAINTS - public open data, no login and no key.
Output
Every record carries the same key set regardless of mode or record set - the fields above plus corpus, and the aggregate columns (groupKey, groupCount, groupBy), which are "" outside aggregate mode. Fields that belong to another record set are "" rather than absent, so the schema is stable across all three. Every record carries sourceUpdatedAt, the date the City last edited that layer.
Related actors
- Philadelphia Building Permits - the permits these violations are raised against.
- Philly311 Service Requests - the resident reports that feed the complaints table.