Swiggy API endpoint
Returns restaurants delivering to a latitude/longitude, optionally filtered by a keyword or browsed within a curated collection. With no query and no collection_id this browses the nearby-restaurant listing; with a query it runs a keyword search across restaurant names, cuisines, and dishes; with a collection_id (from /swiggy/collections) it browses restaurants within that curated collection. query and collection_id are mutually exclusive. Keyword search has two result tabs, selected with tab: dish (the default) returns restaurants that serve a matching dish, each with the matching dishes, their prices, and Swiggy's own per-dish rating where it has one, in a dishes array; restaurant returns restaurants whose own name or cuisine matches, a wider set with no dishes. tab, veg, min_rating and offers are only valid together with query. sort works with either query (relevance, delivery_time, rating) or collection_id (those three plus cost_low_to_high and cost_high_to_low), and is rejected on a plain nearby browse. Each restaurant carries its id (the value the restaurant and menu endpoints take), name, cuisines, cost for two, rating, delivery time, open/closed status, a hero image, and, where one is shown, an external_rating block with the third-party aggregate score, count, and source. Where the result card advertises a promotion it also carries offers, the same title/description/tag shape /swiggy/restaurant returns (a listing card never carries a coupon code, and a card showing both a discount and a separate free-delivery benefit returns them as two entries). is_promoted is present and true only for a result Swiggy itself labels a sponsored placement rather than an organic one. unavailable_message is present only when Swiggy says the restaurant cannot currently be ordered from and carries its own reason; it is not the inverse of is_open, since Swiggy reports a restaurant as open while still refusing orders for the requested location. A plain nearby browse also returns is_serviceable, which says whether Swiggy delivers to the requested coordinates at all: false means the coordinates are outside Swiggy's delivery coverage, so the empty restaurants list is a coverage answer rather than a no-matches answer, while an empty list without the field means no matches in a served area. It is omitted on keyword search and on a collection_id browse, neither of which carries Swiggy's own coverage marker.
/swiggy/searchQuery parameters:
latitude (required) — search center latitude, e.g. 12.9716.longitude (required) — search center longitude, e.g. 77.5946.query (optional) — keyword to search restaurants and dishes by, at least 2 characters, e.g. pizza. A single-character query is rejected as an invalid parameter (the upstream search rejects it too). With no query and no collection_id this browses Swiggy's own nearby-restaurant listing; with a query it uses Swiggy's own keyword search across restaurant names, cuisines, and dishes. Mutually exclusive with collection_id.collection_id (optional) — a curated collection id from /swiggy/collections's id field, e.g. 80440. Browses restaurants within that collection instead of the plain nearby listing. Mutually exclusive with query.sort (optional) — sort order. Valid with query or collection_id, rejected on a plain nearby browse (the site itself only exposes sort controls on those two surfaces). With collection_id, one of: relevance, delivery_time, rating, cost_low_to_high, cost_high_to_low. With query, only relevance, delivery_time, rating — keyword search has no cost-for-two ordering, and cost_low_to_high/cost_high_to_low are rejected there.offset (optional) — opaque pagination cursor from a prior response's next_offset. Not meaningful when query is set (the keyword-search source does not paginate the same way); works for both the plain listing and a collection_id browse.tab (optional) — which of the two keyword-search result tabs to read. One of: dish, restaurant. Only valid together with query. dish returns restaurants that serve a matching dish, each with the matching dishes in a dishes[] array; restaurant returns restaurants whose own name or cuisine matches, typically a much wider set, with no dishes[]. Omitting tab lets the upstream pick by query intent — a dish-like query (pizza) returns the dish tab, a brand-like query (dominos) the restaurant tab — so pass it explicitly when the shape matters.veg (optional, boolean) — only return vegetarian results. On tab=dish this filters to veg dishes; on tab=restaurant it filters to pure-veg restaurants. Only valid together with query.min_rating (optional, number 0-5) — only return restaurants rated at or above this score, e.g. 4. Only valid together with query.offers (optional, boolean) — only return restaurants currently running an offer. Only valid together with query.A location with no coverage returns an empty restaurants list, not an error — is_serviceable (below) is what tells the two apart. A keyword that matches nothing does the same — note that Swiggy often falls back to a loosely related nearby set rather than returning nothing, so a non-empty response does not by itself mean the query matched.
Response includes restaurants[], next_offset (only present for the location-browse path), and is_serviceable (only present for the location-browse path). Each restaurant has id, name, city, locality, area, address, cuisines[], cost_for_two (a display string, e.g. ₹350 for two), rating, rating_count (a display string, e.g. 41K+), delivery_time_minutes, is_open, and image_url.
This is a location-level answer, not a per-restaurant one. Whether an individual restaurant can be ordered from right now is unavailable_message, described above.
Where Swiggy shows a promotion on the result card, the restaurant also carries offers[] — the same title/description/tag/coupon_code shape /swiggy/restaurant returns, though a listing card never carries a coupon code. A card that shows both a discount and a separate free-delivery benefit returns them as two entries (e.g. [{"title":"50% OFF","tag":"FLAT DEAL"},{"title":"Free Delivery"}]); title is the headline (50% OFF, ITEMS, ₹200 OFF, FREE ITEM) and description its condition (AT ₹99, ABOVE ₹999, UPTO ₹140). offers[] is omitted for a restaurant with no current promotion. This is the promotion Swiggy advertises on the listing; /swiggy/restaurant returns that restaurant's fuller offer list, including coupon codes.
unavailable_message is present only when Swiggy says the restaurant cannot currently be ordered from, and carries its own reason — e.g. Currently not taking orders for this location, Opens next at 5 pm, today, Temporarily closed for delivery. It is not simply the inverse of is_open: Swiggy reports a restaurant as open while still refusing orders for the requested location, so a result can have is_open true and an unavailable_message at the same time.
Keyword-search results on tab=dish (the default for dish-like queries) additionally carry dishes[]: the menu items that actually matched the query, each with id, name, description, category, price, discounted_price when currently discounted, is_veg, in_stock, image_url, and — where Swiggy has one for that dish — rating and total_ratings, its own per-dish aggregate score and review count (aggregate only; individual reviews and reviewer identity are out of scope for this endpoint). dishes[] is absent on tab=restaurant, on a plain nearby browse, and on a collection_id browse — none of those surfaces carry per-restaurant dish matches.
Browse results (no query) may additionally carry external_rating, the third-party aggregate Swiggy shows next to its own score: source (currently only GOOGLE), rating, and count (a display string, e.g. 2.6K+). It is omitted for restaurants Swiggy has no third-party rating for, and is never present on keyword-search results. Only this headline aggregate is returned — individual reviews and reviewer identity are out of scope for this endpoint.
Address, coordinates, phone, and opening hours are not returned here — Swiggy's listing cards do not carry them. Use /swiggy/restaurant for those.
| Field | Filled in, of 50 checked | Values in the sample |
|---|---|---|
| id | 50 | |
| name | 50 | “Pizza Hut” and 49 other values |
| city | 50 | 1 |
| locality | 50 | “Richmond Town” and 41 other values |
| area | 50 | “Central Bangalore” and 23 other values |
| address | 50 | |
| cuisines | 50 | median 4 entries |
| cost_for_two | 50 | “₹600 FOR TWO” and 19 other values |
| rating | 50 | 4 to 4.6, median 4.3 |
| rating_count | 50 | “12K+” and 44 other values |
| delivery_time_minutes | 50 | 24 to 52, median 39 |
| is_open | 50 | true in 50 of 50 |
| image_url | 50 | media-assets.swiggy.com |
| external_rating | 23 | |
| is_promoted | 19 | true in 19 of 19 |
| dishes | 50 | median 2 entries |
| Parameter | Type | Required | Default | Description | Example |
|---|---|---|---|---|---|
| latitude | number | Yes | Search center latitude | 12.9716 | |
| longitude | number | Yes | Search center longitude | 77.5946 | |
| query | string | No | Optional keyword to search restaurants and dishes by, at least 2 characters. Mutually exclusive with collection_id. | pizza | |
| collection_id | string | No | Optional curated collection id from /swiggy/collections's id field. Browses restaurants within that collection instead of the plain nearby listing. Mutually exclusive with query. | 80440 | |
| sort | string | No | Optional sort order. With query: relevance, delivery_time, rating. With collection_id: those three plus cost_low_to_high and cost_high_to_low. Not valid on a plain nearby browse. Allowed values: relevance, delivery_time, rating, cost_low_to_high, cost_high_to_low. | rating | |
| offset | string | No | Opaque pagination cursor from a prior response's next_offset (not meaningful when query is set) | ||
| tab | string | No | Which keyword-search result tab to read: dish (default, restaurants serving a matching dish, each with a dishes array) or restaurant (restaurants whose own name/cuisine matches). Only valid together with query. Allowed values: dish, restaurant. | restaurant | |
| veg | boolean | No | Only return vegetarian results: veg dishes on tab=dish, pure-veg restaurants on tab=restaurant. Only valid together with query. | true | |
| min_rating | number | No | Only return restaurants rated at or above this score (0-5). Only valid together with query. | 4 | |
| offers | boolean | No | Only return restaurants currently running an offer. Only valid together with query. | true | |
| x-api-key (header) | string | Yes | API key required |
curl -X GET "https://api.crawlora.net/api/v1/swiggy/search?latitude=12.9716&longitude=77.5946&query=coffee&sort=relevance&tab=dish&veg=true&offers=true" \ -H "x-api-key: $CRAWLORA_API_KEY"
{
"code": 200,
"msg": "OK",
"data": {
"restaurants": [
{
"id": "537139",
"name": "Narmada Chain of Restaurant",
"locality": "Koramangala",
"area": "Koramangala",
"cuisines": [
"Biryani",
"Andhra",
"South Indian"
],
"cost_for_two": "₹500 for two",
"rating": 4.4,
"rating_count": "13K+",
"external_rating": {
"source": "GOOGLE",
"rating": 4.2,
"count": "2.6K+"
},
"delivery_time_minutes": 51,
"is_open": true,
"image_url": "https://media-assets.swiggy.com/swiggy/image/upload/fl_lossy,f_auto,q_auto/RX_THUMBNAIL/IMAGES/VENDOR/2025/11/29/753d7fd4-a3f2-46d0-b803-4e1682b33109_537139.jpg",
"offers": [
{
"title": "ITEMS",
"description": "AT ₹39"
},
{
"title": "Free Delivery"
}
],
"is_promoted": true
}
],
"next_offset": "CJhlELQ4KICY0ZzT+sHYBDCnEw==",
"is_serviceable": true
}
}Request schema
No body schema
Response schema
#/definitions/swiggy.searchResponseDoc
| Field | Type | Required | Enum | Bounds | Example | Description |
|---|---|---|---|---|---|---|
| code | integer | No | Code is the HTTP status code or a custom code used to indicate the result of the request @example 200 | |||
| data | swiggy.SearchResponse | No | ||||
| data.is_serviceable | boolean | No | IsServiceable reports whether Swiggy delivers to the requested coordinates at all. False means the coordinates are outside Swiggy's delivery coverage, so an empty restaurants list is a coverage answer rather than a no-matches answer; an empty list without this field means no matches in a served area. Returned only for the plain nearby browse -- keyword search and a collection_id browse omit it, because Swiggy answers neither with a coverage verdict. | |||
| data.next_offset | string | No | ||||
| data.restaurants | array | No | ||||
| data.restaurants[].address | string | No | ||||
| data.restaurants[].area | string | No | ||||
| data.restaurants[].city | string | No | ||||
| data.restaurants[].cost_for_two | string | No | ||||
| data.restaurants[].cuisines | array | No | ||||
| data.restaurants[].delivery_time_minutes | integer | No | ||||
| data.restaurants[].dishes | array | No | Dishes are the menu items that actually matched a /swiggy/search query, carried only by Swiggy's own "Dishes" search tab (tab=dish). Empty on the restaurant tab, on a plain nearby browse, on a collection browse, and on /swiggy/restaurant -- none of those upstream shapes carry per-restaurant dish matches. | |||
| data.restaurants[].dishes[].category | string | No | ||||
| data.restaurants[].dishes[].description | string | No | ||||
| data.restaurants[].dishes[].discounted_price | number | No | ||||
| data.restaurants[].dishes[].id | string | No | ||||
| data.restaurants[].dishes[].image_url | string | No | ||||
| data.restaurants[].dishes[].in_stock | boolean | No | ||||
| data.restaurants[].dishes[].is_veg | boolean | No | ||||
| data.restaurants[].dishes[].name | string | No | ||||
| data.restaurants[].dishes[].price | number | No | ||||
| data.restaurants[].dishes[].rating | number | No | Rating and TotalRatings are Swiggy's own aggregate score and review count for this individual dish, the same two fields a restaurant carries. Omitted when the dish has no rating yet. Only the headline aggregate is returned -- individual reviews and reviewer identity are out of scope for this platform. | |||
| data.restaurants[].dishes[].total_ratings | integer | No | ||||
| data.restaurants[].external_rating | swiggy.ExternalRating | No | ||||
| data.restaurants[].external_rating.count | string | No | ||||
| data.restaurants[].external_rating.rating | number | No | ||||
| data.restaurants[].external_rating.source | string | No | ||||
| data.restaurants[].hours_message | string | No | ||||
| data.restaurants[].hours_status | string | No | HoursStatus/HoursMessage are Swiggy's own live open/close callout for this outlet ("Open now" / "Closes 11:30 pm"); OpeningHours is its weekly schedule. Only the restaurant detail and menu responses carry these -- search and collection listing cards do not, so they are empty on /swiggy/search results. | |||
| data.restaurants[].id | string | No | ||||
| data.restaurants[].image_url | string | No | ||||
| data.restaurants[].is_open | boolean | No | ||||
| data.restaurants[].is_promoted | boolean | No | IsPromoted reports whether Swiggy itself labels this a promoted (sponsored, paid-placement) result rather than an organic one. Present and true only for those; Swiggy marks none on a plain nearby browse. | |||
| data.restaurants[].latitude | number | No | ||||
| data.restaurants[].locality | string | No | ||||
| data.restaurants[].longitude | number | No | ||||
| data.restaurants[].name | string | No | ||||
| data.restaurants[].offers | array | No | Offers are the promotions Swiggy shows on this restaurant's own listing card in a search, browse, or collection result -- the headline discount and its condition, its badge, and any separate free-delivery benefit. Absent when the card shows no promotion, and on /swiggy/restaurant and /swiggy/restaurant/menu, whose responses carry the restaurant's fuller offer list at the top level instead. | |||
| data.restaurants[].offers[].coupon_code | string | No | ||||
| data.restaurants[].offers[].description | string | No | ||||
| data.restaurants[].offers[].tag | string | No | ||||
| data.restaurants[].offers[].title | string | No | ||||
| data.restaurants[].opening_hours | array | No | ||||
| data.restaurants[].opening_hours[].day | string | No | ||||
| data.restaurants[].opening_hours[].hours | string | No | ||||
| data.restaurants[].phone | string | No | ||||
| data.restaurants[].postal_code | string | No | ||||
| data.restaurants[].rating | number | No | ||||
| data.restaurants[].rating_count | string | No | ||||
| data.restaurants[].total_ratings | integer | No | ||||
| data.restaurants[].unavailable_message | string | No | UnavailableMessage is Swiggy's own reason this listed restaurant cannot be ordered from right now ("Currently not taking orders for this location", "Opens next at 5 pm, today", "Temporarily closed for delivery"). Absent for a restaurant that is currently orderable. Note it is not simply the inverse of is_open: a restaurant Swiggy reports as open can still be unavailable for the requested location. | |||
| msg | unknown | No | Msg is the message that describes the result of the request @example "Request successful" |
| Status | Description | Schema |
|---|---|---|
| 400 | Bad Request | #/definitions/app.Response |
| 503 | Service Unavailable | #/definitions/app.Response |
Use environment variables for secrets and keep Crawlora API keys server-side.
curl -X GET "https://api.crawlora.net/api/v1/swiggy/search?latitude=12.9716&longitude=77.5946&query=coffee&sort=relevance&tab=dish&veg=true&offers=true" \
-H "x-api-key: $CRAWLORA_API_KEY"