Pizza Hut API endpoint
Use Crawlora's Pizza Hut Menu API to extract supported public Pizza Hut 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.
/pizzahut/menuReturns one restaurant's full menu grouped into categories (e.g. "Pizza", "Wings", "Deals"). Every entry is a product, a bundle (a deal or combo), or a standalone priced variant -- type tells callers which -- and carries a price in USD cents plus a decimal dollar value, and an image when the upstream publishes one. A product item also lists variants: every other priced size/crust/style option beyond its default (e.g. a pizza's Personal Pan through Large Original Stuffed Crust). Prices reflect this specific restaurant and order channel, not a national default. channel selects which order channel the menu is priced for (web ordering by default); prices can genuinely differ by channel (e.g. a delivery-marketplace channel vs. web). Some restaurants also carry products with no category at all (e.g. individual dip cup flavors); these are returned separately as uncategorized_items rather than silently dropped. 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_number | string | Yes | Pizza Hut's store number, from /pizzahut/stores | ||
| channel | string | No | Order channel the menu is priced for (default WEB) Allowed values: WEB, MOBILE, POS, KIOSK, DOORDASH, UBEREATS, GRUBHUB, IOS, ANDROID, DELIVEROO, JUST_EAT, CALL_CENTER | ||
| x-api-key (header) | string | Yes | API key required |
curl -X GET "https://api.crawlora.net/api/v1/pizzahut/menu?channel=WEB" \ -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_number": "040937",
"menu_id": "22590d80-9482-4f7b-9594-d7ba2885b928",
"channel": "WEB",
"currency": "USD",
"categories": [
{
"category_code": "pizza",
"name": "Pizza",
"items": [
{
"type": "product",
"code": "CLSS001P|PROD220P",
"name": "Pepperoni Pizza",
"variant_code": "variant_CLSS001_220P_SIZE060L_BASE020H",
"price": {
"amount_cents": 2099,
"amount": 20.99,
"currency_code": "USD"
},
"image_url": "https://www.pizzahut.com/assets/w/POS/Pizza_ProductTile_PEPPERONI_Web_175x203.jpg",
"available": true,
"variants": [
{
"variant_code": "variant_CLSS001_220P_SIZE020P_BASE015P",
"name": "Personal Pan® Pepperoni Pizza",
"price": {
"amount_cents": 669,
"amount": 6.69,
"currency_code": "USD"
},
"available": true
},
{
"variant_code": "variant_CLSS001_220P_SIZE060L_BASE431S",
"name": "Large Original Stuffed Crust® Pepperoni Pizza",
"price": {
"amount_cents": 2509,
"amount": 25.09,
"currency_code": "USD"
},
"available": true
}
]
}
]
}
],
"item_count": 120,
"uncategorized_items": [
{
"type": "product",
"code": "CLSS070A|PROD871AN",
"name": "Ranch Dip Cup",
"variant_code": "variant_CLSS070_871AN_SIZE185O",
"price": {
"amount_cents": 99,
"amount": 0.99,
"currency_code": "USD"
},
"available": true
}
],
"source_url": "https://www.pizzahut.com/v1/tarmor/ph_us/storefront/graphql",
"fetched_at": "2026-09-05T00:00:00Z"
}
}Request schema
No body schema
Response schema
#/definitions/pizzahut.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 | pizzahut.MenuResponse | No | ||||
| data.categories | array | No | ||||
| data.categories[].category_code | string | No | pizza | |||
| data.categories[].description | string | No | ||||
| data.categories[].items | array | No | ||||
| data.categories[].items[].available | boolean | No | true | Available is false when this item (or, for a product, every one of its variants at once) is currently blacked out -- a real, live-confirmed "temporarily unavailable"/"sold out" signal (a dessert item was found blacked out at a real store, 2026-09-06), distinct from an item genuinely being removed from the menu (which simply would not appear here at all). Check a product's own Variants[].Available too -- a product itself can be orderable while one specific size/style variant is blacked out, and vice versa. | ||
| data.categories[].items[].code | string | No | CLSS001P|PROD220P | |||
| data.categories[].items[].description | string | No | ||||
| data.categories[].items[].image_url | string | No | ||||
| data.categories[].items[].name | string | No | Pepperoni Pizza | |||
| data.categories[].items[].price | pizzahut.Money | No | ||||
| data.categories[].items[].price.amount | number | No | 20.99 | |||
| data.categories[].items[].price.amount_cents | integer | No | 2099 | |||
| data.categories[].items[].price.currency_code | string | No | USD | |||
| data.categories[].items[].type | string | No | product | |||
| data.categories[].items[].variant_code | string | No | variant_CLSS001_220P_SIZE060L_BASE020H | VariantCode is the specific priced variant this item's Price reflects (present for type=product, whose price comes from its default variant). | ||
| data.categories[].items[].variants | array | No | Variants lists every other priced size/crust/style variant this product item offers beyond its default (type=product only). Empty when the product has no additional variants beyond the default, or for bundle/variant items. | |||
| data.categories[].items[].variants[].available | boolean | No | true | Available is false when this specific variant is currently blacked out (temporarily unavailable) -- confirmed live 2026-09-06 that this genuinely varies independently per variant, not just per product. | ||
| data.categories[].items[].variants[].name | string | No | Large Original Stuffed Crust® Pepperoni Pizza | |||
| data.categories[].items[].variants[].price | pizzahut.Money | No | ||||
| data.categories[].items[].variants[].price.amount | number | No | 20.99 | |||
| data.categories[].items[].variants[].price.amount_cents | integer | No | 2099 | |||
| data.categories[].items[].variants[].price.currency_code | string | No | USD | |||
| data.categories[].items[].variants[].variant_code | string | No | variant_CLSS001_220P_SIZE060L_BASE431S | |||
| data.categories[].name | string | No | Pizza | |||
| data.channel | string | No | WEB | |||
| data.currency | string | No | USD | |||
| data.fetched_at | string | No | ||||
| data.item_count | integer | No | 120 | ItemCount counts only items reachable through Categories, matching this field's original meaning -- it does not include UncategorizedItems. | ||
| data.menu_id | string | No | 22590d80-9482-4f7b-9594-d7ba2885b928 | |||
| data.source_url | string | No | ||||
| data.store_number | string | No | 040937 | |||
| data.uncategorized_items | array | No | UncategorizedItems lists real, separately-priced products and bundles this restaurant's menu carries that are not linked to any category -- confirmed live 2026-09-06 (coverage-expansion round 2): Pizza Hut's `Menu.products`/`Menu.bundles` support a `categorized: false` filter, and at least one store sampled had 9 such products (e.g. a $0.99 "Ranch Dip Cup", "Garlic Dip Cup") that Categories' own category walk never surfaces at all -- a real gap in the prior category-walk-only approach, not a parser omission. A platform-wide placeholder product named "Reserved" (price $0.00) appears in this list at every store sampled; it is included as upstream returns it rather than filtered, since this repo does not invent filtering heuristics without a confirmed upstream signal to key on. Empty when every product/bundle is reachable through Categories (no uncategorized bundle has been observed on any store sampled). | |||
| data.uncategorized_items[].available | boolean | No | true | Available is false when this item (or, for a product, every one of its variants at once) is currently blacked out -- a real, live-confirmed "temporarily unavailable"/"sold out" signal (a dessert item was found blacked out at a real store, 2026-09-06), distinct from an item genuinely being removed from the menu (which simply would not appear here at all). Check a product's own Variants[].Available too -- a product itself can be orderable while one specific size/style variant is blacked out, and vice versa. | ||
| data.uncategorized_items[].code | string | No | CLSS001P|PROD220P | |||
| data.uncategorized_items[].description | string | No | ||||
| data.uncategorized_items[].image_url | string | No | ||||
| data.uncategorized_items[].name | string | No | Pepperoni Pizza | |||
| data.uncategorized_items[].price | pizzahut.Money | No | ||||
| data.uncategorized_items[].price.amount | number | No | 20.99 | |||
| data.uncategorized_items[].price.amount_cents | integer | No | 2099 | |||
| data.uncategorized_items[].price.currency_code | string | No | USD | |||
| data.uncategorized_items[].type | string | No | product | |||
| data.uncategorized_items[].variant_code | string | No | variant_CLSS001_220P_SIZE060L_BASE020H | VariantCode is the specific priced variant this item's Price reflects (present for type=product, whose price comes from its default variant). | ||
| data.uncategorized_items[].variants | array | No | Variants lists every other priced size/crust/style variant this product item offers beyond its default (type=product only). Empty when the product has no additional variants beyond the default, or for bundle/variant items. | |||
| data.uncategorized_items[].variants[].available | boolean | No | true | Available is false when this specific variant is currently blacked out (temporarily unavailable) -- confirmed live 2026-09-06 that this genuinely varies independently per variant, not just per product. | ||
| data.uncategorized_items[].variants[].name | string | No | Large Original Stuffed Crust® Pepperoni Pizza | |||
| data.uncategorized_items[].variants[].price | pizzahut.Money | No | ||||
| data.uncategorized_items[].variants[].price.amount | number | No | 20.99 | |||
| data.uncategorized_items[].variants[].price.amount_cents | integer | No | 2099 | |||
| data.uncategorized_items[].variants[].price.currency_code | string | No | USD | |||
| data.uncategorized_items[].variants[].variant_code | string | No | variant_CLSS001_220P_SIZE060L_BASE431S | |||
| 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/pizzahut/menu?channel=WEB" \
-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