One unified Philadelphia property record. Type any address or OPA number — get business licenses, open violations, violation history, and 311 complaints, all pulled live from the city’s own data.
The trick: every data point is pulled from Eclipse (the authoritative L&I backend behind li.phila.gov) and Carto (the historical open-data mirror at phl.carto.com). When they disagree, 4PHILLY flags it. Eclipse always wins.
Note
4PHILLY runs entirely in your browser. No server. No analytics. No account. Your lookups don’t leave your device except to hit the city’s public APIs.
Drop any of these into the lookup bar at the top of the app:
| Input | What it pulls |
|---|---|
315 N 12th St |
address-based lookup |
1900 Market St |
high-rise example |
The Sterling |
partial-name match |
| OPA account number | OPA-anchored (most reliable) |
Tip
OPA account numbers beat address strings every time. The city normalizes addresses differently across systems — Eclipse, Carto, and OPA itself can disagree on the same building. The OPA number doesn’t drift.
| What it does | |
|---|---|
| Live data | Eclipse ArcGIS feature services + Carto SQL API, pulled at lookup time |
| Drift detection | Side-by-side compare; divergent rows highlighted red |
| Status decoding | OPEN, IN COMPLIANCE, COMPLIED, CASE CLOSED — only COMPLIED is real compliance1 |
| OPA-anchored | Identity bound to OPA account, not fuzzy address matching |
| PWA | Installable on iOS and Android; works on desktop; offline shell |
| No backend | Static site. Auditable. Forkable. Nothing between you and the city’s APIs. |
%%{init: {'theme':'base','themeVariables':{'primaryColor':'#ffb000','primaryTextColor':'#000','primaryBorderColor':'#ffb000','lineColor':'#ffb000','secondaryColor':'#1a1a1a','tertiaryColor':'#000'}}}%%
flowchart LR
A[Address or OPA #] --> B{OPA resolve}
B --> C[Eclipse ArcGIS<br/>authoritative]
B --> D[Carto SQL<br/>historical mirror]
C --> E[Drift comparator]
D --> E
E --> F[Unified record<br/>+ red flags on divergence]
Eclipse is what L&I inspectors actually use. Carto is what gets published to OpenDataPhilly. They drift. License expirations, violation status changes, and new complaints appear in Eclipse before — sometimes long before — Carto catches up.
4PHILLY shows you both.
The app surfaces five views per property:
- Inspect — business & trade licenses, open violations, violation history, 311 complaints (last 24 months)
- Drift — Eclipse vs. Carto side-by-side, divergent rows highlighted
- Brief — coverage gaps summary
- Records — permits and building certifications
- Limits — what the data can’t tell you, with citations
Warning
Public data has limits. Some are city policy, some are technical, some are because the data simply doesn’t exist in machine-readable form. Verify any claim before relying on it.
| Gap | Why |
|---|---|
| Inspector identity | Not published in public feeds |
| Inspector notes | Internal correspondence only |
| 311 complainant identity | Protected by policy |
| Re-inspection occurrence | Status updates don’t require a physical visit to record |
| Pre-archive violations | Carto archive coverage varies; Eclipse retention varies |
| Sealed cases | Excluded from public feeds entirely |
See the Limits tab inside the app for the full list with source citations.
iOS (Safari)
- Open https://thumpersecure.github.io/4philly/ in Safari
- Tap the Share button
- Tap Add to Home Screen
- Confirm — 4PHILLY now lives on your home screen like a native app
Android (Chrome)
- Open the site in Chrome
- Tap the three-dot menu
- Tap Install app (or Add to Home screen)
- Confirm
Desktop (Chrome / Edge / Brave)
- Open the site
- Click the install icon at the right edge of the address bar
- Or: menu → Install 4PHILLY
Click to expand
4philly/
├── index.html # entry point
├── manifest.webmanifest # PWA manifest
├── sw.js # service worker
├── og-image.png # social card
├── assets/
│ ├── css/ # black + amber theme
│ ├── js/
│ │ ├── eclipse.js # ArcGIS feature service client
│ │ ├── carto.js # Carto SQL client
│ │ ├── drift.js # comparison engine
│ │ ├── render.js # tab views
│ │ └── opa.js # OPA resolver
│ └── icons/ # PWA icons (multiple sizes)
└── README.md # you are here
No frameworks. No build step. Vanilla JS, fetch, and the two city APIs.
- Pages deploy is automated with
.github/workflows/deploy-pages.yml. - On
mainpushes, the workflow publishes from the repository root (.). - For branch layouts that publish from
/docs, run the workflow manually and choosepublish_source=docs. - Repo path references are normalized to lowercase
/4philly/so case-sensitive paths resolve consistently.
- Eclipse ArcGIS —
services.arcgis.com/fLeGjb7u4uXqeF9q— authoritative for current state - Carto SQL API —
phl.carto.com— historical mirror, can lag Eclipse - OPA assessment layer — anchor for property identity
A short field guide to the L&I status codes you’ll see:
OPEN- Violation has been issued. No resolution yet.
IN COMPLIANCE- Owner has claimed compliance. Not verified by inspection.
COMPLIED- Inspector verified the condition was resolved. This is the only status that means what it sounds like.
CASE CLOSED- Case is administratively closed. Could mean resolved, could mean dropped, could mean reassigned. Look at the surrounding history.
- Eclipse + Carto unified lookup
- Drift detection
- PWA install
- 311 complaints (24-month window)
- OPA-anchored identity
- Permit timeline view
- Multi-property watchlist
- CSV / JSON export
- Diff alerts (subscribe to a property)
- Print-ready brief (one-page PDF per property)
Found drift the comparator missed? A status code that should decode differently? An edge case where Eclipse and Carto give the same answer but neither is correct?
Open an issue with the OPA number and what you saw. PRs welcome.
MIT — see LICENSE.
Built by @thumpersecure.
Civic data is public. This tool makes it legible.
4PHILLY is an independent civic tool. Not affiliated with the City of Philadelphia, L&I, or OPA.
Footnotes
-
CASE CLOSEDin particular is ambiguous — a case can close without compliance being achieved. TheCOMPLIEDstatus is the only one that means the underlying condition was resolved on inspection. ↩