← back to Lawyer Directory Builder

docs/blocked_sources.md

64 lines

# Blocked sources — require Playwright / browser session

Two sources we wanted but cannot reach with plain HTTP under our compliance policy
(no captcha bypass, respect site terms).

## CA Secretary of State bizfile API

- Endpoint: `POST https://bizfileonline.sos.ca.gov/api/Records/businesssearch`
- Probe result: **403 Forbidden** with empty body on plain POST.
- Reason: their SPA injects a Google reCAPTCHA v3 token in the `x-recaptcha` header
  for every API call. Without a real browser executing their reCAPTCHA challenge,
  the gateway rejects the request.
- Path forward: a Playwright session that (a) loads the search page so reCAPTCHA
  initializes, (b) submits the form, (c) extracts the token from the live request,
  (d) replays via fetch. This is **inside compliance** because we are not bypassing
  reCAPTCHA — we are letting it run normally and just persisting the result.

## CA State Bar — Attorney Licensee Search

- Form page: `https://apps.calbar.ca.gov/attorney/LicenseeSearch/AdvancedSearch`
- Detail page: `https://apps.calbar.ca.gov/attorney/Licensee/Detail/{barNumber}`
- Probe result: every URL returns the **same 624 KB SPA shell** with an empty
  `#moduleAttorneySearchList` div.  Server-side rendering doesn't expose result data;
  the page loads a Telerik Kendo grid that fetches results client-side via an
  endpoint we couldn't locate from the static HTML/JS.
- Path forward: same Playwright pattern as bizfile — load `Detail/{n}` for each
  Bar # of interest, wait for the data-bound elements, scrape the rendered DOM.

## Why not now

Both imply adding Playwright + headless Chromium + DOM extractors + per-page rate
limits much stricter than for plain HTTP. That's a project unto itself; tonight's
run sticks with the sources that work cleanly via curl-grade requests:

- OpenStreetMap Overpass (already wired)
- Wikidata SPARQL (already wired)

When ready to do Playwright pass, see `src/ingest/calbar_playwright.ts` (TODO).

## Adjacent-city open-data portals

LA County firm coverage would benefit from the same kind of "Active Business Licenses"
dataset for cities outside LA City proper:

- Beverly Hills (~35K pop) — `beverlyhills-cityofbh.opendata.arcgis.com`
- Santa Monica (~92K) — `data-smgov.opendata.arcgis.com`
- Pasadena (~140K) — `data-cityofpasadena.opendata.arcgis.com`
- Long Beach (~462K) — `data-longbeach.opendata.arcgis.com`

All four serve their portal as a client-rendered SPA with no public Socrata/JSON API
and no DCAT feed at the standard `/api/feed/dcat-us/1.1` path. The dataset listings
load via JavaScript that calls Esri's internal Hub API with auth tokens generated
client-side.

Path forward (not tonight):
- per-portal investigation to find each city's "businesses" or "active business licenses"
  dataset, then call its FeatureServer query endpoint directly:
  `https://services.arcgis.com/<orgId>/ArcGIS/rest/services/<dataset>/FeatureServer/0/query?where=...`
- OR a Playwright pass that visits each portal, extracts dataset links from the rendered
  catalog, and discovers the FeatureServer URLs.

Beverly Hills + Santa Monica are likely low-yield (small cities, may not even publish
business license data). Long Beach + Pasadena are higher-value targets.