Yelp API & Scraper
The Yelp API returns business search, reviews and ratings as clean JSON.
🤖 Using an AI assistant? Copy this link into ChatGPT / Claude / Cursor — it reads every endpoint and parameter instantly and tells you if this API fits your use case.
The primary business/reviews endpoint returns a business with its id, name, rating, review count, categories, phone, address and coordinates — plus the review text. You can also search businesses, pull business/details, list popular_dishes and menus, get photos and review_highlights, and resolve a Yelp URL to an id. It is built for local-data products, reputation monitoring and lead generation that need Yelp data without a scraper. One ReefAPI key, one shared credit pool, the standard envelope.
The business id is not the slug, and the price band changes field name per action
Two things send people in circles on Yelp. The identifier in a yelp.com/biz/ URL is a slug, not the id the API takes, and there is a dedicated action to convert one into the other. And the price band arrives under a different field name depending on which action returned it. Everything below is from measured calls on San Francisco and New York businesses.
| Field | Format | Measured |
|---|---|---|
| enc_biz_id | 22 characters, opaque, mixed case with - and _. This is what every action takes. | mSMZJj2pFvttWLpcDmgrEA for Tony's Pizza Napoletana, gZz9A8k8ORC_xl0aHxtY4w for Monkey Bar |
| slug / alias | The path segment in yelp.com/biz/<slug>. Never accepted where an id is required. | tonys-pizza-napoletana-san-francisco. business/url-to-id converts a URL into the id. |
| rating | One decimal, not a half-star. The half-star on the website is display rounding. | 4.1, 4.2, 4.3 and 4.6 all appeared on a single search page |
| rating_histogram | Keys "5" down to "1", integer counts. | Tony's returned 5:5442, 4:1770, 3:703, 2:399, 1:631, a weighted mean of 4.229 matching the reported 4.2 |
| price and price_level (search) | A band string and its integer, 1 through 4. Both null when Yelp has no band for that business. | "$$" with price_level 2, "$" on a budget listing, and null with null on another row |
| price_range (details, reviews) | The same band under a different field name, with no numeric twin. | "$$" on both business/details and business/reviews |
| price filter | Applied by the source. Verified in both directions. | price [4] returned eight $$$$ restaurants; price [1] returned six $ pizzerias |
| hours | Passed through unflattened, with the source's __typename keys intact. | hours[0].regularHoursMergedWithSpecialHoursForCurrentWeek[] of {dayOfWeekShort, dayOfWeek, regularHours[]}, e.g. "Mon", "Monday", ["11:45 AM - 10:30 PM"] |
| reviewer.elite_year | A two-digit string on elite reviewers, and the key is absent entirely otherwise. | "26" with is_elite true on one reviewer, and no elite_year key at all on the next |
| review reactions | A fixed four-key object, always present. | {HELPFUL, THANKS, LOVE_THIS, OH_NO}, alongside a separate useful_count |
The histogram and review_count can disagree slightly. Tony's histogram sums to 8945 against a review_count of 8942, because Yelp counts recommended reviews and builds the histogram at a different moment. Treat a difference of a few as normal, and do not use one to validate the other.
Real request and response JSON
Captured from the indexed primary action, search, on .
{
"method": "POST",
"url": "https://api.reefapi.com/yelp/v1/search",
"headers": {
"x-api-key": "$REEF_KEY",
"content-type": "application/json"
},
"body": {
"term": "Pizza",
"location": "San Francisco, CA",
"limit": 10
}
}{
"ok": true,
"meta": {
"api": "yelp",
"endpoint": "search",
"mode": "live",
"latency_ms": 3059.3,
"record_count": 10,
"bytes": 1283323,
"cache_hit": false,
"parse_source": "relay",
"offset": 0,
"limit": 10,
"filters": null
},
"data": {
"results": [
{
"enc_biz_id": "loZXJPwZujUlDE6_wVY7dQ",
"name": "[redacted-name]",
"slug": "seniores-pizza-san-francisco-5",
"url": "https://www.yelp.com/biz/seniores-pizza-san-francisco-5",
"rating": 3.4,
"review_count": 1421,
"price": "$",
"price_level": 1,
"categories": [
"Pizza",
"Burgers",
"American"
],
"address": "2415 19th Ave",
"city": "San Francisco",
"state": "CA",
"neighborhoods": [
"Parkside"
],
"image": null
},
{
"enc_biz_id": "NGoAss2hlQWXMSRYROCfYA",
"name": "[redacted-name]",
"slug": "joe-s-garage-café-and-market-san-francisco",
"url": "https://www.yelp.com/biz/joe-s-garage-café-and-market-san-francisco",
"rating": null,
"review_count": 0,
"price": null,
"price_level": null,
"categories": [
"Convenience Stores",
"Beer, Wine & Spirits",
"Pizza"
],
"address": "320 11th St",
"city": "San Francisco",
"state": "CA",
"neighborhoods": [
"SoMa"
],
"image": null
},
{
"enc_biz_id": "wEzg_lla5jqAzIXokYnZJA",
"name": "[redacted-name]",
"slug": "thats-amore-woodfire-pizza-san-francisco",
"url": "https://www.yelp.com/biz/thats-amore-woodfire-pizza-san-francisco",
"rating": 4.5,
"review_count": 354,
"price": "$$",
"price_level": 2,
"categories": [
"Pizza",
"Beer, Wine & Spirits",
"Italian"
],
"address": "1901 Ocean Ave",
"city": "San Francisco",
"state": "CA",
"neighborhoods": [
"Ingleside Terraces"
],
"image": "https://s3-media0.fl.yelpcdn.com/bphoto/bQDgDwmOfrUfK9eofcripA/ls.jpg"
}
],
"term": "Pizza",
"location": "San Francisco, CA"
}
}What the Yelp API does
| Action | Description | Concrete use case | Key params |
|---|---|---|---|
| business/reviews | Fetch all reviews (with full pagination — newest, oldest, highest rated or elite first) plus the complete Yelp business profile — rating, review count, categories, price, phone, address, hours, amenities and photos. Accepts up to 39 businesses per call via their Yelp business ID. | Support teams call business/reviews to fetch all reviews (with full pagination. | encBizIds, maxReviews, sortBy, ratings, language, ... |
| business/details | Get the full Yelp business profile without reviews — name, categories, star rating, review count, price level, phone, full address, coordinates, hours, amenities and photo. Faster and cheaper than business/reviews when you only need the listing. Accepts up to 39 businesses per call via their Yelp business ID. | Reputation platforms call business/details to get the full Yelp business profile without reviews. | encBizIds, includePii |
| search | Search Yelp by keyword or category in a location — just like typing 'Pizza in San Francisco, CA' on the Yelp website — with the same filters the site offers (price, rating, open-now, sort order and feature attributes). Returns a ranked list of businesses, each with its Yelp business ID, name, Yelp URL, star rating, review count, price level, categories, address and photo. Pass the business ID directly into business/reviews or business/details. Paginate with the offset parameter. | Market researchers call search to search Yelp by keyword or category in a location. | term, location, limit, offset, sort_by, ... |
| popular_dishes | Get a restaurant's popular dishes from Yelp — the 'Popular dishes' section shown on the Yelp business page — returning each dish's name and photo. Identify the restaurant by its Yelp business URL, its Yelp business ID (from the search or business details actions), or its Yelp slug. Restaurant pages only; returns an empty list when Yelp shows no popular dishes for that restaurant. | B2B review analysts call popular_dishes to get a restaurant's popular dishes from Yelp. | business_url, business_id, slug, limit |
| menus | Get a restaurant's menu from Yelp when Yelp hosts it — returning menu sections with each item's name, description, price and photo. Identify the restaurant by its Yelp business URL, Yelp business ID, or slug. Only menus hosted on Yelp are returned; many restaurants link to an external menu, which Yelp has no structured data for — `menu_available` is false in those cases. | Support teams call menus to get a restaurant's menu from Yelp when Yelp hosts it. | business_url, business_id, slug |
| business/photos | Get a Yelp business's photos — the images shown on its Yelp page, with captions and categories (food, menu, interior, etc.) where Yelp provides them. Identify the business by its Yelp business URL, Yelp business ID, or slug. | Reputation platforms call business/photos to get a Yelp business's photos. | business_url, business_id, slug, limit |
| review_highlights | Get a Yelp business's review highlights — the recurring phrases reviewers mention (e.g. 'happy hour', 'great service'), each with a sample snippet from a real review. A fast at-a-glance read on what the business is known for. Identify the business by its Yelp business URL, Yelp business ID, or slug. | Market researchers call review_highlights to get a Yelp business's review highlights. | business_url, business_id, slug, limit |
| business/url-to-id | Convert any yelp.com/biz/… business page URL into the Yelp business ID used by business/details, business/reviews, popular_dishes and menus. | B2B review analysts call business/url-to-id to convert any yelp.com/biz/… business page URL into the Yelp business ID used by business/detai…. | business_url |
| business/search | Find a Yelp business by name (plus optional location) and return its Yelp business ID, name and Yelp URL. Pass the business ID straight into business/reviews or business/details. No Yelp account required. | Support teams call business/search to find a Yelp business by name (plus optional location) and. | name, location, limit, resolveAll |
Call search from your stack
curl -X POST https://api.reefapi.com/yelp/v1/search \
-H "x-api-key: $REEF_KEY" \
-H "content-type: application/json" \
-d '{"term":"Pizza","location":"San Francisco, CA","limit":10}'import requests
r = requests.post(
"https://api.reefapi.com/yelp/v1/search",
headers={"x-api-key": REEF_KEY},
json={
"term": "Pizza",
"location": "San Francisco, CA",
"limit": 10
},
)
print(r.json()["data"])const res = await fetch("https://api.reefapi.com/yelp/v1/search", {
method: "POST",
headers: {
"x-api-key": process.env.REEF_KEY,
"content-type": "application/json",
},
body: JSON.stringify({
"term": "Pizza",
"location": "San Francisco, CA",
"limit": 10
}),
});
const { ok, data, meta, error } = await res.json();Ask your MCP-connected assistant: call reefapi.yelp.search with {"term":"Pizza","location":"San Francisco, CA","limit":10}.Who uses this API and why
- Reputation tools call business/reviews to monitor a business's Yelp rating and new reviews.
- Lead-generation products use search to build lists of local businesses by category and city.
- Local-data apps use business/details, menus and popular_dishes to enrich a restaurant listing.
Questions developers ask before integrating
I have a yelp.com/biz/ URL. Why does the last part of it not work as a business id?
Because that is the slug, and the id is a separate 22-character encoded string. For Tony's Pizza Napoletana the slug is tonys-pizza-napoletana-san-francisco and the id is mSMZJj2pFvttWLpcDmgrEA. Pass a URL to business/url-to-id and it returns {enc_biz_id, name, slug, url} in one call. search and business/search also return enc_biz_id on every row, so if you are starting from a name you already have the id. A few actions (popular_dishes, menus, business/photos and review_highlights) accept the slug or the URL directly.
Is rating rounded to a half star?
No, that is a display convention on the website. The API returns one decimal: a single measured search page held 4.1, 4.2, 4.3 and 4.6, none of which is a half-step. You can check it against the histogram, since Tony's counts of 5442, 1770, 703, 399 and 631 give a weighted mean of 4.2289, which is exactly the 4.2 reported even though the page draws four and a half stars. Sort and threshold on rating directly, and round only when you draw the stars.
Why is price null on some businesses?
Because Yelp has no price band for them, usually a newer listing or a non-restaurant. A measured search returned one pizzeria with price "$$" and price_level 2 and another with both null on the same page. Note the field name changes by action: search returns price plus price_level (the integer 1 to 4), while business/details and business/reviews return price_range with no numeric twin. The price filter on search does work and was verified in both directions, with [4] returning only $$$$ and [1] only $.
A result came back with rating null and review_count 0. Is the record broken?
No, that is a listing with no reviews yet, and Yelp does show them in search results. A measured search for pizza in San Francisco returned a cafe with rating null and review_count 0 sitting among businesses with hundreds of reviews. Guard for it, because sorting on rating will either throw or push nulls to an arbitrary end depending on your language. It is the expected shape for a brand-new business rather than an error.
My search for San Francisco returned a business in Daly City. Why?
Yelp widens the radius when a query does not fill the page from inside the named location, exactly as the website does. A measured search for "Pizza" in "San Francisco, CA" returned Mountain Mike's Pizza in Daly City as the second result. Every row carries city, state and neighborhoods[], so filter on those yourself if you need a hard boundary. neighborhoods[] is empty for businesses outside a named Yelp neighborhood, which is another hint that a row is out of town.
completeness_pct says 0.1 but the profile looks complete. What is it measuring?
The share of the business's reviews this call actually harvested, not the completeness of the profile. A measured business/reviews call with maxReviews 5 against a business holding 8942 reviews returned scraped_review_count 5, claimed_review_count 8942 and completeness_pct 0.1. On business/details, which fetches no reviews at all, it sits near zero by definition even though every profile field came back populated. Read scraped_review_count against claimed_review_count if you want to know how much of the review body you hold.
What does the hours object look like, and why is __typename in it?
Hours arrive nested and we pass them through unflattened so nothing is lost in translation. You get hours[0].regularHoursMergedWithSpecialHoursForCurrentWeek, an array of seven entries of {dayOfWeekShort, dayOfWeek, regularHours, __typename}, measured as {"Mon", "Monday", ["11:45 AM - 10:30 PM"]}. regularHours is an array because a business can have split hours in one day, the times are 12-hour strings in the business's local time, and the field name says "merged with special hours", so a holiday can move a day with no separate flag. Ignore __typename.
What is on a review row besides the text?
Quite a lot. Measured: review_id, rating as an integer 1 to 5, text, language, localized_date ("2026-08-25") alongside created_at carrying the business's UTC offset ("2026-08-25T21:57:13-07:00"), useful_count, a reactions object with the four fixed keys HELPFUL, THANKS, LOVE_THIS and OH_NO, photos[] of full-size image URLs, is_not_recommended, and owner_reply_text with owner_reply_date whenever has_owner_reply is true. The nested reviewer object carries friend_count, review_count, photo_count and is_elite, with elite_year present as a two-digit string like "26" only on elite reviewers.
How do I pull only negative reviews?
Pass ratings, which takes an array of star values and defaults to all five. ratings [1, 2] gives you the complaints, and it combines with maxReviews and sortBy. sortBy takes RELEVANCE_DESC, DATE_DESC (the default here), DATE_ASC, RATING_DESC, RATING_ASC and ELITES_DESC. Also worth knowing: includeNotRecommended pulls Yelp's filtered reviews into a separate not_recommended_reviews[] array rather than mixing them into reviews[], with not_recommended_count reported beside it.
What is the Yelp API?
Yelp API is a ReefAPI endpoint group for local business reviews, ratings and details. It returns live JSON through POST requests under /yelp/v1.
Is the Yelp API free to try?
Yes. ReefAPI starts with 1,000 free credits, no card required. Yelp calls use the same shared credit balance as every other ReefAPI engine.
Do I need a Yelp login or account?
No login to Yelp is needed for the API response. You call ReefAPI with your x-api-key header, and the playground can run live examples before you create a production key.
How fresh is the Yelp data?
The page example is captured from a live business/reviews call, and production requests fetch live data through ReefAPI rather than a static sample.
How many credits does the Yelp API use?
Yelp actions currently cost 1 credit per successful call. Failed or blocked calls are free, and all APIs draw from one credit pool.