Subway API endpoint
Use Crawlora's Subway Menu API to extract supported public Subway data as structured JSON. This page includes request parameters, cURL examples, response schema, error behavior, credit cost, and a Playground link for testing before integration.
/subway/menuReturns one Subway store's complete menu: every category, every product, and for each purchasable size (Footlong, 6-inch, etc.) its price, full nutrition panel (calories, fat, sodium, protein and more) and allergen disclosures. Store IDs come from a GET /subway/store result's store_id field. Categories carry is_main_category: true for human-browsable menu sections (Sandwiches, Drinks, Salads, ...) and false for Subway's own internal build/customization groupings, which are included for completeness but are not meant to be shown as menu sections on their own. Developers commonly use this endpoint for data enrichment, monitoring, research dashboards, internal automation, and agent-native workflows that need repeatable structured public web data. Authentication uses the documented Crawlora headers, and usage is metered with the credit cost shown on this page.
Request parameters are generated from the active endpoint catalog. Required values must be sent before Crawlora can call the upstream public web data source.
| Parameter | Type | Required | Default | Description | Example |
|---|---|---|---|---|---|
| store_id | string | Yes | Store ID from a /subway/store result's store_id | ||
| x-api-key (header) | string | Yes | API key required |
curl -X GET "https://api.crawlora.net/api/v1/subway/menu" \ -H "x-api-key: $CRAWLORA_API_KEY"
Send your scraping API key in the x-api-key header. Use the console API Keys page to rotate or select the active key.
Endpoint usage is metered in credits. The plan prices, included credits, limits, and overage rates below match the active backend billing configuration.
| Plan | Price | Included credits | Daily cap | Rate limit | Overage |
|---|---|---|---|---|---|
| Free | $0/mo | 2,000 | 500 daily credits | 5/min | No overage |
| Starter | $9/mo | 20,000 | 5,000 daily credits | 15/min | $0.75/1,000 overage credits when enabled |
| Growth | $29/mo | 100,000 | 25,000 daily credits | 45/min | $0.45/1,000 overage credits when enabled |
| Pro | $79/mo | 400,000 | No daily cap | 120/min | $0.30/1,000 overage credits |
| Business | $199/mo | 1,200,000 | No daily cap | 300/min | $0.20/1,000 overage credits |
| Enterprise | $499/mo | 5,000,000 | No daily cap | 1,000/min | $0.12/1,000 overage credits |
This endpoint is executed through Crawlora's managed scraping infrastructure.
Crawlora does not silently return bad data when the upstream page cannot be used.
| Status | Common failure case |
|---|---|
| 400 | Invalid input or missing required parameter |
| 429 | Plan or endpoint rate limit exceeded |
| 500 | Internal execution error |
| 502 | Upstream platform failed, returned unusable HTML, or served a challenge page that could not be resolved |
When possible, Crawlora returns structured error context so your integration can retry, back off, or inspect the request.
| Status | Description | Schema |
|---|---|---|
| 400 | Bad Request | #/definitions/app.Response |
| 404 | Not Found | #/definitions/app.Response |
| 429 | Too Many Requests | #/definitions/app.Response |
| 503 | Service Unavailable | #/definitions/app.Response |
{
"code": 200,
"msg": "OK",
"data": {
"store_id": "75376-0",
"currency": "USD",
"category_count": 1,
"product_count": 1,
"categories": [
{
"id": "1187",
"name": "Steak",
"is_main_category": true,
"items": [
{
"id": "50080",
"name": "Steak Philly",
"slug": "steak-philly",
"variants": [
{
"id": "50081",
"name": "Steak Philly Sandwich (1DM)",
"size": "Footlong",
"price": 13.99,
"available": true,
"nutrition": [
{
"name": "CALORIES",
"value": 1010
},
{
"name": "TOTAL FAT (g)",
"value": 50
}
],
"allergens": [
{
"name": "Milk/Lactose",
"contains": true,
"may_contain": false
}
],
"image_asset_urn": "urn:aaid:aem:steak-philly-footlong"
}
]
}
]
}
],
"source_url": "https://www.subway.com/api/store-menu/75376-0?locale=en-us",
"fetched_at": "2026-09-02T12:00:00Z"
}
}Request schema
No body schema
Response schema
#/definitions/subway.menuResponseDoc
| 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 | subway.MenuResponse | No | ||||
| data.categories | array | No | ||||
| data.categories[].description | string | No | ||||
| data.categories[].id | string | No | ||||
| data.categories[].is_main_category | boolean | No | ||||
| data.categories[].items | array | No | ||||
| data.categories[].items[].id | string | No | ||||
| data.categories[].items[].name | string | No | ||||
| data.categories[].items[].slug | string | No | ||||
| data.categories[].items[].variants | array | No | ||||
| data.categories[].items[].variants[].allergens | array | No | ||||
| data.categories[].items[].variants[].allergens[].contains | boolean | No | ||||
| data.categories[].items[].variants[].allergens[].may_contain | boolean | No | ||||
| data.categories[].items[].variants[].allergens[].name | string | No | ||||
| data.categories[].items[].variants[].available | boolean | No | ||||
| data.categories[].items[].variants[].id | string | No | ||||
| data.categories[].items[].variants[].image_asset_urn | string | No | ImageAssetURN is Subway's own Adobe AEM asset identifier, not a directly fetchable URL -- confirmed live 2026-09-02 that the upstream's own imageUrl field is always empty; this is what is actually populated. Kept as-is rather than inventing an unverified delivery-URL scheme. | |||
| data.categories[].items[].variants[].name | string | No | Name is the upstream product name, which sometimes carries an internal build code in parentheses (e.g. "(1DM)") -- passed through verbatim rather than stripped, since the meaning of that code is not documented anywhere this family could confirm. | |||
| data.categories[].items[].variants[].nutrition | array | No | ||||
| data.categories[].items[].variants[].nutrition[].name | string | No | ||||
| data.categories[].items[].variants[].nutrition[].value | number | No | ||||
| data.categories[].items[].variants[].price | number | No | ||||
| data.categories[].items[].variants[].size | string | No | Size is the build label ("Footlong", "6''", "Kids") distinguishing this variant from siblings of the same MenuItem. | |||
| data.categories[].name | string | No | ||||
| data.categories[].slug | string | No | ||||
| data.category_count | integer | No | ||||
| data.currency | string | No | USD | |||
| data.fetched_at | string | No | ||||
| data.product_count | integer | No | ||||
| data.source_url | string | No | ||||
| data.store_id | string | No | ||||
| msg | unknown | No | Msg is the message that describes the result of the request @example "Request successful" |
Use environment variables for secrets and keep Crawlora API keys server-side.
curl -X GET "https://api.crawlora.net/api/v1/subway/menu" \
-H "x-api-key: $CRAWLORA_API_KEY"Crawlora is designed for responsible structured public web data workflows. Customers are responsible for using Crawlora in compliance with applicable laws, third-party rights, target-platform rules, and Crawlora terms.
Read Crawlora terms