# LA County Restaurant Inspection Scraper (`crawlerbros/la-county-restaurant-inspection-scraper`) Actor

Scrape restaurant and food-facility health inspection records for Los Angeles County, CA - facility name, address, placard grade, score, violations, and geolocation. Search by name, owner, city, facility ID, or location.

- **URL**: https://apify.com/crawlerbros/la-county-restaurant-inspection-scraper.md
- **Developed by:** [Crawler Bros](https://apify.com/crawlerbros) (community)
- **Categories:** Automation, Lead generation, Other
- **Stats:** 2 total users, 1 monthly users, 100.0% runs succeeded, 0 bookmarks
- **User rating**: No ratings yet

## Pricing

from $3.00 / 1,000 results

This Actor is paid per event and usage. You are charged both the fixed price for specific events and for Apify platform usage.
Since this Actor supports Apify Store discounts, the price gets lower the higher subscription plan you have.

Learn more: https://docs.apify.com/platform/actors/running/actors-in-store#pay-per-event

## What's an Apify Actor?

Actors are web data automations that power AI and operations. They run on the Apify platform to scrape websites, process data, connect APIs, and automate workflows.
In Batch mode, an Actor accepts a well-defined JSON input, performs an action which can take anything from a few seconds to a few hours,
and optionally produces a well-defined JSON output, datasets with results, or files in key-value store.
In Standby mode, an Actor provides a web server which can be used as a website, API, or an MCP server.
Actors are written with capital "A".

## How to integrate an Actor?

If asked about integration, you help developers integrate Actors into their projects.
You adapt to their stack and deliver integrations that are safe, well-documented, and production-ready.
The best way to integrate Actors is as follows.

- **AI agents and MCP clients** — the [Apify MCP server](https://docs.apify.com/integrations/mcp.md) at `https://mcp.apify.com` (remote, streamable HTTP, OAuth on first use).
- **Agentic workflows and local Actor development** — [Agent Skills](https://apify.com/.well-known/agent-skills/index.json) with the [Apify CLI](https://docs.apify.com/cli/docs.md): `npm install -g apify-cli`, then `apify login`.
- **JavaScript/TypeScript projects** — the official [JS/TS client](https://docs.apify.com/api/client/js/docs.md): `npm install apify-client`.
- **Python projects** — the official [Python client](https://docs.apify.com/api/client/python/docs.md): `pip install apify-client`.
- **Any other language** — the [REST API](https://docs.apify.com/api/v2.md).

For usage examples, see the [API](#api) section below.

For more details, see Apify documentation as [Markdown index](https://docs.apify.com/llms.txt) and [Markdown full-text](https://docs.apify.com/llms-full.txt).

# README

## LA County Restaurant Inspection Scraper

Scrape restaurant and food-facility health inspection records for **Los Angeles County, California** — over 100 cities and unincorporated communities inspected by the LA County Department of Public Health, Environmental Health Division (Pasadena, Long Beach, and Vernon mostly run their own local health departments; only a small number of border-area facilities under LA County jurisdiction appear here from those three cities). Get facility name, address, letter grade (A/B/C), numeric score, itemized health-code violations, business owner, and precise geolocation — sourced directly from the department's public open-data feed. No login, no cookies, no paid proxy required.

### What this actor does

- **Five lookup modes:** search by restaurant name, search by owner name, browse by city, look up an exact facility ID, or find inspections near a lat/lon point
- **Rich filtering:** letter grade, risk level, facility program category, inspection type, program status, ZIP code, and inspection-date range — usable together or in any combination, on top of any mode
- **Itemized violations** — each inspection record can include every specific health-code violation found (code, description, compliance status, point deduction), plus a violation count and total points deducted
- **Live county data** — pulled straight from the LA County Department of Public Health's public ArcGIS open-data feed (the same data source the department's own [inspection-results page](https://publichealth.lacounty.gov/eh/i-want-to/view-inspection-results.htm) points the public to)
- **Geolocation on every record** — latitude/longitude plus a ready-to-click Google Maps link
- **Empty fields are omitted** — every emitted record only contains fields that could actually be populated

### Output per inspection record

- `facilityId` — county facility identifier (e.g. `FA0069601`)
- `facilityName`, `programName` — business name and the specific department/program inspected (a market's meat counter and bakery may be separate programs under one facility)
- `programStatus` — `ACTIVE` or `INACTIVE`
- `programElement`, `facilityType` — the county's facility-category code and its description (e.g. `RESTAURANT (0-30) SEATS HIGH RISK`)
- `riskLevel`, `riskLevelLabel` — `LOW` / `MODERATE` / `HIGH`, derived from the facility category
- `address`, `city`, `state`, `zipCode`
- `latitude`, `longitude`
- `ownerId`, `ownerName` — registered business owner
- `serviceCode`, `serviceDescription` — inspection type (routine vs. owner-initiated)
- `score` — numeric inspection score (0-100)
- `grade`, `gradeLabel` — posted letter grade and a friendly score-range label
- `serialNumber` — unique inspection visit identifier
- `employeeId` — county inspector ID
- `activityDate` — inspection date (`YYYY-MM-DD`)
- `violations` — array of `{ code, description, status, points }` for every violation found during this inspection (when `includeViolations` is on)
- `violationCount`, `totalViolationPoints`
- `mapUrl` — Google Maps link built from the facility's coordinates
- `sourceUrl` — the live county REST endpoint returning this exact record
- `recordType: "restaurantInspection"`, `scrapedAt`

### Input

| Field | Type | Default | Description |
|---|---|---|---|
| `mode` | select | `search` | `search` / `byOwner` / `byCity` / `byFacilityId` / `nearby` |
| `searchQuery` | string | `pizza` | Facility-name keyword (mode=search) |
| `ownerName` | string | – | Owner-name keyword (mode=byOwner) |
| `cities` | array (select, 160 options) | – | Cities/communities to browse or filter to (mode=byCity, or an extra filter on any mode) |
| `facilityIds` | array | – | Exact facility IDs (mode=byFacilityId) |
| `latitude` / `longitude` | number | `34.0522` / `-118.2437` | Center point (mode=nearby, defaults to downtown LA) |
| `radiusKm` | number | `2` | Search radius in km (mode=nearby) |
| `grades` | array (select) | – | Filter by letter grade(s): `A` / `B` / `C` |
| `minScore` / `maxScore` | integer | – | Filter by numeric inspection score range (0-100), finer-grained than `grades` |
| `riskLevels` | array (select) | – | Filter by risk classification: `LOW` / `MODERATE` / `HIGH` |
| `programElements` | array (select, 18 options) | – | Filter by facility category/size/risk program code |
| `serviceCodes` | array (select) | – | Filter by inspection type: routine (`001`) or owner-initiated (`401`) |
| `programStatus` | select | (any) | Filter to `ACTIVE` or `INACTIVE` facilities |
| `zipCodes` | array | – | Filter by 5-digit ZIP code(s) |
| `dateFrom` / `dateTo` | string | – | Inspection date range (`YYYY-MM-DD`) |
| `sortBy` | select | `newest` | `newest` / `oldest` (by inspection date) |
| `includeViolations` | boolean | `true` | Attach itemized violation details to each record |
| `maxItems` | integer | `100` | Hard cap on emitted records (1–5000) |

#### Example: search a keyword, restrict to one city and grade

```json
{
  "mode": "search",
  "searchQuery": "taqueria",
  "cities": ["LOS ANGELES"],
  "grades": ["A"],
  "maxItems": 100
}
```

#### Example: browse every inspection in a city within a date range, high-risk facilities only

```json
{
  "mode": "byCity",
  "cities": ["SANTA MONICA", "VENICE"],
  "riskLevels": ["HIGH"],
  "dateFrom": "2025-01-01",
  "dateTo": "2025-12-31",
  "maxItems": 500
}
```

#### Example: exact facility lookup with full violation history

```json
{
  "mode": "byFacilityId",
  "facilityIds": ["FA0069601"],
  "includeViolations": true
}
```

#### Example: inspections near a point

```json
{
  "mode": "nearby",
  "latitude": 34.0522,
  "longitude": -118.2437,
  "radiusKm": 1.5,
  "maxItems": 100
}
```

#### Example: all locations under one owner

```json
{
  "mode": "byOwner",
  "ownerName": "starbucks",
  "maxItems": 200
}
```

### Use cases

- **Consumer safety apps** — surface up-to-date letter grades and specific violations near a user's location
- **Real-estate / relocation research** — check food-safety history around a neighborhood before moving
- **Journalism & public-health research** — track violation trends across LA County cities and facility types over time
- **Restaurant discovery apps** — filter listings to A-grade establishments only
- **Franchise / multi-location compliance monitoring** — pull every location under one owner or facility ID and review violation history

### FAQ

**What area does this cover?** Cities and unincorporated communities in Los Angeles County served by the county's Environmental Health Division (100+ appear in the live data at any given time). Pasadena, Long Beach, and Vernon mostly operate their own local health departments, so only a small number of border-area facilities from those three cities appear in this feed.

**What do the grade letters mean?** `A` = score 90-100 (Excellent), `B` = score 80-89 (Good), `C` = score 70-79 (Needs improvement) — LA County's standard restaurant-grading scale.

**What's the difference between `grade` and `riskLevel`?** `grade` is the inspection outcome (how the facility scored on this visit). `riskLevel` is the county's baseline classification of how complex the facility's food handling is (e.g. a large high-seat-count restaurant is inherently higher risk than a small retail market), independent of any single inspection's score.

**Is one row per restaurant or per inspection?** One output record = one inspection visit (identified by `serialNumber`). A facility inspected quarterly will have multiple records, one per visit, each with its own score/grade and (optionally) its own violation list.

**How current is the data?** The inspections feed is updated by the county on an ongoing basis; the violations detail feed is refreshed quarterly.

**Do I need a proxy or login?** No. This is a public, unauthenticated open-data API — no cookies, no paid proxy, no API key.

**Can I search multiple cities, grades, or program categories at once?** Yes — `cities`, `grades`, `riskLevels`, `programElements`, `serviceCodes`, and `zipCodes` all accept multiple values and are combined with AND logic across filter types, OR logic within each filter.

**What if my filters match nothing?** The actor finishes cleanly with 0 records and a status message explaining that no matches were found — try widening the date range or removing a filter.

**Why does turning off `includeViolations` make the run faster?** Violation details come from a separate quarterly county file covering ~400,000 violation line items. Fetching and matching it against your results adds roughly 10 seconds to the run. Turn it off if you only need scores/grades and want the fastest possible run.

# Actor input Schema

## `mode` (type: `string`):

What to fetch.

## `searchQuery` (type: `string`):

Free-text keyword matched against the facility name (case-insensitive, partial match).

## `ownerName` (type: `string`):

Free-text keyword matched against the registered business owner name (case-insensitive, partial match).

## `cities` (type: `array`):

One or more LA County cities/unincorporated communities to browse. Also usable as an extra filter on other modes.

## `facilityIds` (type: `array`):

Exact LA County facility IDs, e.g. `FA0069601`. Returns the inspection history for each facility.

## `latitude` (type: `number`):

Center point latitude in decimal degrees, e.g. `34.0522` (downtown Los Angeles).

## `longitude` (type: `number`):

Center point longitude in decimal degrees, e.g. `-118.2437` (downtown Los Angeles).

## `radiusKm` (type: `number`):

Distance from the center point to search within.

## `grades` (type: `array`):

Restrict to one or more posted letter grades. A = 90-100, B = 80-89, C = 70-79.

## `minScore` (type: `integer`):

Drop inspections with a numeric score below this (0-100). Finer-grained than the letter-grade filter. Inspections with no numeric score on file always pass through.

## `maxScore` (type: `integer`):

Drop inspections with a numeric score above this (0-100). Inspections with no numeric score on file always pass through.

## `riskLevels` (type: `array`):

Restrict to facilities classified by the county at one or more risk levels (based on food-handling complexity, not grade).

## `programElements` (type: `array`):

Restrict to one or more county facility-type/size/risk program codes (restaurants by seat count, food markets by square footage).

## `serviceCodes` (type: `array`):

Restrict to one or more inspection service types.

## `programStatus` (type: `string`):

Restrict to facilities whose program is currently active or inactive with the county.

## `zipCodes` (type: `array`):

Restrict to one or more 5-digit ZIP codes.

## `dateFrom` (type: `string`):

Only include inspections on or after this date.

## `dateTo` (type: `string`):

Only include inspections on or before this date.

## `sortBy` (type: `string`):

Order inspection records by activity date.

## `includeViolations` (type: `boolean`):

Attach the specific health-code violations (code, description, status, points) found during each inspection, plus a violation count and total point deduction. Adds a one-time ~10s county violations-file download per run.

## `maxItems` (type: `integer`):

Hard cap on emitted records.

## Actor input object example

```json
{
  "mode": "search",
  "searchQuery": "pizza",
  "ownerName": "starbucks",
  "cities": [],
  "facilityIds": [
    "FA0069601"
  ],
  "latitude": 34.0522,
  "longitude": -118.2437,
  "radiusKm": 2,
  "grades": [],
  "riskLevels": [],
  "programElements": [],
  "serviceCodes": [],
  "programStatus": "",
  "zipCodes": [],
  "dateFrom": "",
  "dateTo": "",
  "sortBy": "newest",
  "includeViolations": true,
  "maxItems": 100
}
```

# Actor output Schema

## `inspections` (type: `string`):

Dataset containing all scraped restaurant inspection records.

# API

You can run this Actor programmatically using our API. Below are code examples in JavaScript, Python, and CLI, as well as the OpenAPI specification and MCP server setup.

## JavaScript example

```javascript
import { ApifyClient } from 'apify-client';

// Initialize the ApifyClient with your Apify API token
// Replace the '<YOUR_API_TOKEN>' with your token
const client = new ApifyClient({
    token: '<YOUR_API_TOKEN>',
});

// Prepare Actor input
const input = {
    "mode": "search",
    "searchQuery": "pizza",
    "ownerName": "starbucks",
    "cities": [],
    "facilityIds": [
        "FA0069601"
    ],
    "latitude": 34.0522,
    "longitude": -118.2437,
    "radiusKm": 2,
    "grades": [],
    "riskLevels": [],
    "programElements": [],
    "serviceCodes": [],
    "programStatus": "",
    "zipCodes": [],
    "dateFrom": "",
    "dateTo": "",
    "sortBy": "newest",
    "includeViolations": true,
    "maxItems": 100
};

// Run the Actor and wait for it to finish
const run = await client.actor("crawlerbros/la-county-restaurant-inspection-scraper").call(input);

// Fetch and print Actor results from the run's dataset (if any)
console.log('Results from dataset');
console.log(`💾 Check your data here: https://console.apify.com/storage/datasets/${run.defaultDatasetId}`);
const { items } = await client.dataset(run.defaultDatasetId).listItems();
items.forEach((item) => {
    console.dir(item);
});

// 📚 Want to learn more 📖? Go to → https://docs.apify.com/api/client/js/docs

```

## Python example

```python
from apify_client import ApifyClient

# Initialize the ApifyClient with your Apify API token
# Replace '<YOUR_API_TOKEN>' with your token.
client = ApifyClient("<YOUR_API_TOKEN>")

# Prepare the Actor input
run_input = {
    "mode": "search",
    "searchQuery": "pizza",
    "ownerName": "starbucks",
    "cities": [],
    "facilityIds": ["FA0069601"],
    "latitude": 34.0522,
    "longitude": -118.2437,
    "radiusKm": 2,
    "grades": [],
    "riskLevels": [],
    "programElements": [],
    "serviceCodes": [],
    "programStatus": "",
    "zipCodes": [],
    "dateFrom": "",
    "dateTo": "",
    "sortBy": "newest",
    "includeViolations": True,
    "maxItems": 100,
}

# Run the Actor and wait for it to finish
run = client.actor("crawlerbros/la-county-restaurant-inspection-scraper").call(run_input=run_input)

# Fetch and print Actor results from the run's dataset (if there are any)
print(f"💾 Check your data here: https://console.apify.com/storage/datasets/{run.default_dataset_id}")
for item in client.dataset(run.default_dataset_id).iterate_items():
    print(item)

# 📚 Want to learn more 📖? Go to → https://docs.apify.com/api/client/python/docs/quick-start

```

## CLI example

```bash
echo '{
  "mode": "search",
  "searchQuery": "pizza",
  "ownerName": "starbucks",
  "cities": [],
  "facilityIds": [
    "FA0069601"
  ],
  "latitude": 34.0522,
  "longitude": -118.2437,
  "radiusKm": 2,
  "grades": [],
  "riskLevels": [],
  "programElements": [],
  "serviceCodes": [],
  "programStatus": "",
  "zipCodes": [],
  "dateFrom": "",
  "dateTo": "",
  "sortBy": "newest",
  "includeViolations": true,
  "maxItems": 100
}' |
apify call crawlerbros/la-county-restaurant-inspection-scraper --silent --output-dataset

```

## MCP server setup

```json
{
    "mcpServers": {
        "apify": {
            "type": "http",
            "url": "https://mcp.apify.com/?tools=fetch-actor-details,crawlerbros/la-county-restaurant-inspection-scraper"
        }
    }
}

```

The hosted server signs you in with OAuth on first connect, so no API token belongs in this config. Clients without OAuth support can send an `Authorization: Bearer <APIFY_API_TOKEN>` header instead, using a token from API & Integrations in Apify Console (https://console.apify.com/settings/integrations).

## OpenAPI specification

Download the OpenAPI definition: https://api.apify.com/v2/actors/cpXojff82dXWUvDdZ/builds/eAynG1ezBpBaja3X2/openapi.json
