NYC Restaurant Inspections - Grades, Scores & Violations avatar

NYC Restaurant Inspections - Grades, Scores & Violations

Pricing

from $0.03 / 1,000 nyc restaurant inspection records

Go to Apify Store
NYC Restaurant Inspections - Grades, Scores & Violations

NYC Restaurant Inspections - Grades, Scores & Violations

NYC DOHMH restaurant inspections (295k violation records / 31.5k restaurants): grade, score, critical flag, violation code, cuisine, borough, BBL/BIN. Search, aggregate by cuisine or borough, profile a restaurant, roll up one row per restaurant, or read the violation-code dictionary.

Pricing

from $0.03 / 1,000 nyc restaurant inspection records

Rating

0.0

(0)

Developer

Wenhao Yang

Wenhao Yang

Maintained by Community

Actor stats

0

Bookmarked

2

Total users

1

Monthly active users

37 minutes ago

Last modified

Categories

Security

Limited permissions

Share

NYC Restaurant Inspections - 295,292 Inspection & Violation Records

New York City's Department of Health and Mental Hygiene inspection results as a queryable dataset: 295,292 inspection/violation records across 31,488 restaurants (measured 10 November 2026), refreshed daily (newest record 9 November 2026, newest inspection 7 November 2026). Records carry the letter grade, the inspection score, the critical-violation flag, the violation code and description, the cuisine, the borough and street address, BBL/BIN and coordinates where the city publishes them - an inspection with no violation has no code or description, and 51% of rows have no letter grade yet (both are counted below).

Low cost

From $0.00005 per record, down to $0.00003 at Gold. Pay only for the records you receive - the full file stays queryable and you are never billed for the scan behind it.

What you get per record

fieldmeaning
restaurantId, restaurantNameCAMIS id and the DBA name
address, borough, zipcodebuilding + street, borough and ZIP
phone, cuisinethe published business phone and cuisine
inspectionDate, inspectionType, actionwhen and what kind of inspection, and the action taken
notYetInspectedthe string "true" for the 4,008 permit rows that have no inspection yet, else "false"
violationCode, violationDescriptionthe DOHMH violation code and its text
criticalFlagCritical / Not Critical / Not Applicable
score, grade, gradeDateinspection score, letter grade and the date it was issued
recordDatethe city's record stamp
latitude, longitudepoint coordinates
bbl, bin, communityBoard, councilDistrict, censusTract, ntaproperty and district identifiers for joins
totalMatchedwhat the filters matched, by mode: violation rows (rows and aggregate), rows for that restaurant (profile), restaurants (restaurants), codes (codes)

Search it

  • Restaurant - name="pizza", camis="40745618".
  • Area - boro="Brooklyn", zipcode="11221", bin="...", bbl="...".
  • Cuisine - cuisine="Chinese", "Pizza", "Latin".
  • Grade - grade="C" for the lowest published grade.
  • Food-safety severity - criticalFlag="Critical".
  • Violation - violationCode="04K" (evidence of rats), 04L (mice), 04M (roaches), 04H (food adulterated or contaminated).
  • Date window - dateFrom="2026-01-01", dateTo="2026-12-31".
  • Inspection type - inspectionType="Pre-permit".

Example inputs

Pizza places in Brooklyn (3,250 matching rows)

{ "name": "pizza", "boro": "Brooklyn", "maxResults": 100 }

Critical violations recorded since 1 January 2026 (45,582 rows)

{ "criticalFlag": "Critical", "dateFrom": "2026-01-01", "maxResults": 100 }

One restaurant's full inspection history

{ "mode": "profile", "camis": "40745618" }

In mode="profile", the top-level grade/score/gradeDate are the restaurant's latest issued grade (the newest row that carries a grade and a grade date); profileLatestGrade/profileLatestScore/profileLatestGradeDate repeat the same values, and the raw newest row is still visible in the other fields.

Rows graded C

{ "grade": "C", "maxResults": 200 }

Roll a filter up to one record per restaurant

mode="restaurants" folds the matching rows into one record per CAMIS: the latest inspection in the matched set (inspectionDate, inspectionType, action), the violation and critical-violation counts across the matched rows (profileViolations, profileCriticalViolations), the latest grade in the matched set (grade, score, gradeDate), the restaurant's inspection count and its first/last inspection date.

{ "mode": "restaurants", "boro": "Brooklyn", "cuisine": "Pizza", "maxResults": 500 }

That matches 4,416 records from 430 restaurants and delivers all 430 of them. { "mode": "restaurants", "grade": "C" } matches 1,955 restaurants; { "mode": "restaurants", "boro": "Brooklyn" } matches 8,027. maxResults caps how many restaurant records are delivered (default 50, max 5,000). The whole matched set is always folded before delivery, and totalMatched reports how many restaurants matched, so you can see how many a larger maxResults would return.

Filters select rows, so every count and the grade shown are computed over the rows that matched - with grade="C" you are looking at each restaurant's most recent C-grade inspection, not necessarily the grade it holds today. Use mode="profile" when you need one restaurant's current state.

Restaurants mode scans the matched rows to build the rollup, so it requires a filter that narrows the scan and refuses to run rather than silently truncate: an unfiltered call, or a match set above 80,000 rows, fails with a message asking for a narrower filter (borough, ZIP, cuisine, grade, violation code or a date window). Brooklyn alone is 74,577 rows and Manhattan is 109,259 - above the ceiling, so pair a large borough with a cuisine or a date window. You are billed per delivered restaurant record, not for the scan.

Violation-code dictionary

{ "mode": "codes" }

Returns the 146 DOHMH codes present in the file with violationCode, violationDescription, criticalFlag and the number of records citing it. Filters still apply, so they narrow the dictionary as well as the counts: boro="Brooklyn" returns the 125 codes cited in Brooklyn with Brooklyn-only counts, and grade="C" returns 63. Unfiltered, the most-cited code is 10F (non-food contact surface not kept clean) with 41,129 records, then 08A (vermin harbourage) 25,074 and 06C (food not protected from contamination) 19,067.

Aggregate it

{ "mode": "aggregate", "groupBy": "cuisine", "metric": "count" }

groupBy = cuisine (default), boro, grade, criticalFlag, inspectionType, violationCode or zipcode; metric = count (matching rows), avgScore or restaurants.

Use metric="restaurants" when the question is "how many restaurants". count counts violation rows; restaurants counts distinct CAMIS.

{ "mode": "aggregate", "groupBy": "boro", "metric": "restaurants" }

Returns Manhattan 12,586, Brooklyn 8,027, Queens 7,010, Bronx 2,641, Staten Island 1,121, plus 103 restaurants whose borough the city codes as 0.

Measured records by borough: Manhattan 109,259, Brooklyn 74,577, Queens 74,216, Bronx 27,514, Staten Island 9,428; by cuisine: American 43,691, Chinese 28,646, Coffee/Tea 21,469, Pizza 16,896, Latin American 15,536, Mexican 12,136. Row-weighted average score by cuisine: Bangladeshi 42.05, Pakistani 36.83, African 36.28 - each violation row contributes its inspection score, so inspections with many citations weigh more. (Rows with no cuisine description average 37.65 and form their own group, so they are not counted inside any cuisine above.)

Row grain and how to read it

  • One row = one violation cited at one inspection of one restaurant. An inspection that found nothing is published as one row with empty violation fields (7,095 such rows). totalMatched counts these rows, not restaurants.
  • score is inspection-level and repeats on every violation row of that inspection - do not sum it across rows. Use
    mode="aggregate", "metric":"avgScore"
    for averages.
  • grade is blank on 150,638 rows - inspections before a letter grade was issued, or not yet graded. Blank means "no grade", not an error. Grades N (not yet graded), P (pending) and Z (reopened) also appear; the published counts are A 97,746, B 17,842, C 12,862, N 10,296, Z 5,212, P 696. 10,284 rows carry a grade but no grade date; a profile's latest grade uses only rows that have both.
  • inspection_date = 1900-01-01 is a sentinel, not a real date: 4,008 rows belong to restaurants that applied for a permit and have not been inspected yet. Those rows emit inspectionDate empty and notYetInspected true.
  • The feed contains active restaurants only. A restaurant that closes drops out of the dataset, and its history with it - so historical coverage is not a census of every restaurant that ever operated.
  • The source itself contains 233 exactly duplicated rows (0.08%); they are delivered as filed and each counts as one record.
  • When maxResults or the run-level charge cap stops a query, the dataset also carries one unbilled _meta row with truncated, delivered, totalMatched and stopReason.
  • 298 rows carry borough 0, the source's code for an address the city could not place in a borough.
  • Not every row has every field: 17,483 rows have no score, 1,639 have no latitude/longitude/BBL, 5,840 have no BIN and 4,088 have no cuisine description. A field being empty means the city did not publish it for that inspection.
  • Cuisine has 90 distinct values, ZIP code 253, violation code 146.

Source and licence

New York City Department of Health and Mental Hygiene, published on the NYC Open Data portal (public open data).