# Domino's Menus Scraper (`automation-lab/dominos-store-menus-pricing`) Actor

Find US Domino's stores and export current menus, item sizes, prices, availability, coupons, and ordering provenance by ZIP code or store ID.

- **URL**: https://apify.com/automation-lab/dominos-store-menus-pricing.md
- **Developed by:** [Stas Persiianenko](https://apify.com/automation-lab) (community)
- **Categories:** E-commerce
- **Stats:** 2 total users, 1 monthly users, 100.0% runs succeeded, 0 bookmarks
- **User rating**: No ratings yet

## Pricing

from $3.60 / 1,000 item extracteds

This Actor is paid per event. You are not charged for the Apify platform usage, but only a fixed price for specific events.
Since this Actor supports Apify Store discounts, the price gets lower the higher subscription plan you have.

Learn more: https://docs.apify.com/actors/running/actors-in-store.md#pay-per-event

## What's an Apify Actor?

Actors are web data automations that power AI and operations. They run on the Apify platform to scrape websites, process data, connect APIs, and automate workflows.
In Batch mode, an Actor accepts a well-defined JSON input, performs an action which can take anything from a few seconds to a few hours,
and optionally produces a well-defined JSON output, datasets with results, or files in key-value store.
In Standby mode, an Actor provides a web server which can be used as a website, API, or an MCP server.
Actors are written with capital "A".

## How to integrate an Actor?

If asked about integration, you help developers integrate Actors into their projects.
You adapt to their stack and deliver integrations that are safe, well-documented, and production-ready.
The best way to integrate Actors is as follows.

- **AI agents and MCP clients** — the [Apify MCP server](https://docs.apify.com/integrations/mcp.md) at `https://mcp.apify.com` (remote, streamable HTTP, OAuth on first use).
- **Agentic workflows and local Actor development** — [Agent Skills](https://apify.com/.well-known/agent-skills/index.json) with the [Apify CLI](https://docs.apify.com/cli/docs.md): `npm install -g apify-cli`, then `apify login`.
- **JavaScript/TypeScript projects** — the official [JS/TS client](https://docs.apify.com/api/client/js/docs.md): `npm install apify-client`.
- **Python projects** — the official [Python client](https://docs.apify.com/api/client/python/docs.md): `pip install apify-client`.
- **Any other language** — the [REST API](https://docs.apify.com/api/v2.md).

For usage examples, see the [API](#api) section below.

For more details, see Apify documentation as [Markdown index](https://docs.apify.com/llms.txt) and [Markdown full-text](https://docs.apify.com/llms-full.txt).

# README

## Domino's Menus Scraper

Export current US Domino's menus for selected ZIP codes or store IDs.
The Actor returns store metadata, service availability, menu categories, products,
priced sizes, coupons, and source provenance as analysis-ready dataset rows.

Use it for recurring restaurant catalog monitoring, local price comparisons,
market coverage analysis, and spreadsheet or data-pipeline exports.

### What does Domino's Menus Scraper do?

The Actor follows Domino's public ordering data flow without placing an order.
It can:

- discover nearby US stores from one or more five-digit ZIP codes;
- fetch a known store directly from its numeric Domino's store ID;
- report delivery and carryout support and current service-open flags;
- normalize each priced product variant as one menu-item row;
- attach product category, product family, size, price, and availability;
- export current public coupon names, codes, prices, and service methods;
- preserve the exact Domino's API URL used as record provenance;
- stop predictably at configured store and output-record limits.

The Actor is read-only. It does not add products to a cart, validate coupons,
submit customer information, or place orders.

### Who is it for?

**Restaurant intelligence teams** can compare visible prices and assortment
between stores and markets.

**Data analysts** can build a repeatable ZIP-to-store-to-menu dataset instead of
manually browsing ordering pages.

**Retail and delivery researchers** can observe service availability, local
coupons, and menu differences across selected US locations.

**Developers** can consume stable typed JSON through the Apify API, SDKs,
webhooks, schedules, Make, Zapier, or MCP.

### Why use this Actor?

A Domino's menu is store-specific. A national list alone does not answer which
variant is offered, what a selected store charges, or which coupons are visible.
This Actor resolves the store first and keeps `storeId` on every result.

Compared with a browser-only workflow, its structured HTTP route avoids loading
images, fonts, videos, and analytics. That reduces memory and transfer while
preserving public catalog fields. A US residential proxy is still required by
the source and is configured automatically.

### What data can I extract?

| Record | Important fields | Meaning |
| --- | --- | --- |
| Store | `storeId`, `address`, `phone`, `hoursDescription` | Public store identity and contact context |
| Service | `allowsDelivery`, `allowsCarryout`, `serviceIsOpen` | Ordering capability and observed open state |
| Wait | `estimatedWaitMinutes` | Current service-method wait estimate when supplied |
| Menu item | `productCode`, `variantCode`, `name`, `productName` | Product family and purchasable variant identity |
| Category | `productType`, `category`, `categoryPath` | Menu organization returned by Domino's |
| Size | `sizeCode`, `sizeName`, `sizeDescription` | Size or quantity represented by the variant |
| Price | `price`, `currency` | Current listed base price; nullable when not fixed |
| Availability | `available`, `local` | Prepared/not-excluded state and store-local marker |
| Coupon | `couponCode`, `name`, `price`, `bundle` | Public store coupon metadata |
| Provenance | `sourceUrl`, `orderingUrl`, `scrapedAt` | Source endpoint, ordering entry point, and collection time |

Store, menu-item, and coupon entities share the default dataset. Use
`recordType` to filter or split them downstream.

### Getting started

1. Open the Actor input page.
2. Keep the example ZIP code or enter your own five-digit US ZIP codes.
3. Optionally add known numeric Domino's store IDs.
4. Select `store`, `menuItem`, and/or `coupon` record types.
5. Set `maxStores` and `maxItems` to bound the run.
6. Choose the service method used for ZIP discovery.
7. Click **Start**.
8. Open the default dataset to preview, download, or integrate the rows.

Start with one ZIP, one store, and 25–100 records while validating a workflow.
Increase limits only after confirming that the selected markets meet your needs.

### Input parameters

#### `postalCodes`

Array of five-digit US ZIP codes.
The Actor finds stores visible for the selected `serviceMethod`.
Example: `["10001", "90210"]`.

#### `storeIds`

Optional numeric Domino's store IDs.
This route is useful for recurring checks after a first discovery run.
Example: `["3681"]`.

#### `serviceMethod`

`Delivery` or `Carryout`.
This affects store discovery; it does not filter menu variants or coupon rows.

#### `recordTypes`

Any combination of:

- `store` — store and service metadata;
- `menuItem` — one row per menu variant/size;
- `coupon` — one row per public coupon.

#### `maxStores`

Maximum unique stores processed across all inputs.
Allowed range: 1–25.
Default: 1.

#### `maxItems`

Maximum total dataset rows across all record types.
Allowed range: 1–10,000.
Default: 20.

When several stores are selected, the Actor allocates the remaining result
budget across them so one large menu does not starve later stores.

### Example input: one ZIP menu sample

```json
{
  "postalCodes": ["10001"],
  "recordTypes": ["store", "menuItem"],
  "maxStores": 1,
  "maxItems": 25
}
```

This exact input currently returns one store row and 24 priced menu-item rows.
Source data changes naturally over time.

### Example input: one store's coupons

```json
{
  "postalCodes": [],
  "storeIds": ["3681"],
  "recordTypes": ["coupon"],
  "maxStores": 1,
  "maxItems": 30
}
```

Use a store-specific task or schedule when you need repeatable snapshots for the
same location.

### Example output

A real normalized menu-item row has this shape:

```json
{
  "recordType": "menuItem",
  "storeId": "3681",
  "productCode": "F_PBITES",
  "variantCode": "B16PBIT",
  "name": "16-Piece Parmesan Bread Bites",
  "productName": "Parmesan Bread Bites",
  "productType": "Bread",
  "category": "Breads",
  "categoryPath": ["Breads"],
  "sizeCode": "BRD16",
  "sizeName": "16-Piece",
  "price": 6.49,
  "currency": "USD",
  "available": true,
  "local": false,
  "sourceUrl": "https://order.dominos.com/power/store/3681/menu?lang=en&structured=true",
  "orderingUrl": "https://www.dominos.com/en/pages/order/menu",
  "scrapedAt": "2026-09-12T20:15:58.237Z"
}
```

Prices shown above are source data, not Actor charges.
They may change whenever the store updates its catalog.

### How much does it cost to scrape Domino's menus?

Pay-per-event pricing has two parts:

- **Start:** $0.05 once per run.
- **Item:** one charge for each dataset record actually produced.

The BRONZE item price is **$0.006 per record**.
Tier discounts are applied automatically by Apify:

| Tier | Price per record |
| --- | ---: |
| FREE | $0.0069 |
| BRONZE | $0.006 |
| SILVER | $0.00468 |
| GOLD | $0.0036 |
| PLATINUM | $0.0036 |
| DIAMOND | $0.0036 |

Examples at BRONZE pricing:

- 25 records: $0.05 + (25 × $0.006) = **$0.20**;
- 100 records: $0.05 + (100 × $0.006) = **$0.65**;
- 500 records: $0.05 + (500 × $0.006) = **$3.05**.

Only accepted dataset rows trigger item events.
Failed requests, rejected values, and duplicates are not item-charged.
Platform compute and proxy usage are accounted for in the maintained price and
may vary with retries, but users pay the active Actor events shown by Apify.

### Recurring price and catalog monitoring

For recurring monitoring:

1. run ZIP discovery once and retain the returned store IDs;
2. create a Task using those `storeIds`;
3. select the record types your pipeline needs;
4. schedule the Task daily, weekly, or monthly;
5. export each dataset with `storeId`, variant/coupon code, and `scrapedAt`;
6. compare snapshots in your warehouse or spreadsheet.

The Actor reports observations; it does not maintain historical state or send
change alerts itself.

### Spreadsheet and data-pipeline exports

The default dataset can be downloaded as JSON, CSV, Excel, XML, RSS, or JSONL.
For clean menu-price tables, filter `recordType = menuItem`.
For location coverage, filter `recordType = store`.
For promotions, filter `recordType = coupon`.

Useful comparison keys are:

- store menu: `storeId + variantCode`;
- product family: `storeId + productCode`;
- coupon: `storeId + couponCode`;
- observation time: `scrapedAt`.

### API usage with cURL

```bash
curl -X POST \
  "https://api.apify.com/v2/acts/automation-lab~dominos-store-menus-pricing/runs?token=$APIFY_TOKEN" \
  -H "Content-Type: application/json" \
  -d '{"postalCodes":["10001"],"recordTypes":["store","menuItem"],"maxStores":1,"maxItems":25}'
```

Use the returned run's `defaultDatasetId` to fetch dataset items.
Do not embed an Apify token in public source code.

### API usage with JavaScript

```javascript
import { ApifyClient } from 'apify-client';

const client = new ApifyClient({ token: process.env.APIFY_TOKEN });
const run = await client.actor('automation-lab/dominos-store-menus-pricing').call({
  postalCodes: ['10001'],
  recordTypes: ['store', 'menuItem'],
  maxStores: 1,
  maxItems: 25,
});
const { items } = await client.dataset(run.defaultDatasetId).listItems();
console.log(items);
```

### API usage with Python

```python
import os
from apify_client import ApifyClient

client = ApifyClient(os.environ['APIFY_TOKEN'])
run = client.actor('automation-lab/dominos-store-menus-pricing').call(run_input={
    'postalCodes': ['10001'],
    'recordTypes': ['store', 'menuItem'],
    'maxStores': 1,
    'maxItems': 25,
})
items = client.dataset(run['defaultDatasetId']).list_items().items
print(items)
```

### MCP setup

Add the Actor to Claude Code:

```bash
claude mcp add --transport http apify \
  "https://mcp.apify.com?tools=automation-lab/dominos-store-menus-pricing"
```

#### Claude Desktop, Cursor, and VS Code setup

Claude Desktop, Cursor, and VS Code can use this equivalent MCP configuration:

```json
{
  "mcpServers": {
    "apify": {
      "url": "https://mcp.apify.com?tools=automation-lab/dominos-store-menus-pricing"
    }
  }
}
```

Example prompts:

- “Find one Domino's store near ZIP 10001 and return 25 current menu rows.”
- “Export current coupons for Domino's store 3681.”
- “Compare menu prices for two stores and group changes by variant code.”

### Reliability and retry behavior

Domino's protects its public ordering endpoints with geographic and anti-bot
controls. Direct and datacenter delivery did not provide reliable data during
development. The Actor therefore uses a US residential Apify Proxy connection.

Each endpoint receives at most three attempts.
A retry rotates to a fresh sticky residential identity after a network error,
HTTP 403, HTTP 429, or temporary server error.
Stable invalid-input and other non-transient responses fail without blind
retries.

If all attempts fail, the Actor exits non-zero instead of returning a misleading
successful empty dataset.

### Limits and interpretation

- Coverage is limited to US stores visible through Domino's public endpoints.
- ZIP search returns nearby stores selected by Domino's, not every store in a state.
- `maxStores` is capped at 25 to bound transfer, runtime, and proxy cost.
- A price is the listed base value and may exclude tax, fees, toppings, or cart rules.
- A coupon row describes public catalog metadata; it is not proof of cart eligibility.
- `available` reflects structured menu flags, not guaranteed physical inventory.
- Service-open and wait estimates are time-sensitive snapshots.
- Empty or absent upstream optional fields remain omitted or null.
- The source can change endpoint behavior or schema without notice.

### Legality and responsible use

Use public data responsibly and only for lawful purposes.
Review Domino's terms, applicable database rights, and local laws for your use
case. Keep request volumes proportionate, use bounded schedules, and avoid
collecting unnecessary personal data.

This Actor is not affiliated with, endorsed by, or sponsored by Domino's.
Domino's names and trademarks belong to their respective owners.

### Troubleshooting

#### “Provide at least one postalCodes or storeIds value”

Add at least one five-digit US ZIP or numeric store ID.
An empty input is rejected deliberately.

#### “Every postal code must contain exactly 5 digits”

Use strings such as `"10001"`.
Do not include ZIP+4 suffixes, country prefixes, or city names.

#### The run fails after three residential sessions

Inspect the run log for HTTP status and endpoint context.
Try a smaller one-store input later rather than immediately launching repeated
large runs. Persistent upstream protection changes require an Actor update.

#### I received fewer rows than expected

Check `maxItems`, `maxStores`, and `recordTypes`.
A selected limit can truncate the source catalog intentionally.
Some stores also expose fewer coupons or variants than others.

#### Why is a coupon price null?

Some public coupons represent percentage discounts or cart rules without a
single fixed dollar value. The Actor preserves null instead of inventing one.

### FAQ

#### Does this Actor place Domino's orders?

No. It performs read-only catalog and store lookups.

#### Can I search by city or street address?

Not in this version. Use five-digit US ZIP codes or known numeric store IDs.
This avoids pretending that partial addresses have deterministic coverage.

#### Are menu prices current?

They are current as returned by the selected store at `scrapedAt`.
The Actor does not guarantee how quickly a store publishes operational changes.

#### Can I monitor historical changes?

Yes, by scheduling a Task and comparing successive datasets externally.
The Actor does not combine snapshots or issue alerts itself.

#### Are coupons guaranteed to work?

No. Coupon availability and eligibility can depend on service method, cart,
time, location, and terms not represented by a fixed row.

#### Why are store and coupon rows charged like menu rows?

Every useful dataset record uses the single `item` event.
There are no hidden record-type events and no separate coupon charge.

### Related Automation Lab Actors

For broader restaurant-market coverage, use
[Uber Eats Menus & Reviews Scraper](https://apify.com/automation-lab/ubereats-menu-reviews-scraper)
to complement source-specific Domino's catalog observations with marketplace
restaurant, menu, price, and review data.

Choose this Actor when Domino's store-level product variants, sizes, prices,
service state, coupons, and source provenance are the required output.

# Actor input Schema

## `postalCodes` (type: `array`):

Five-digit US postal codes used to discover nearby Domino's stores.

## `storeIds` (type: `array`):

Optional numeric Domino's store IDs. Use these for repeatable store-specific catalog and price checks.

## `serviceMethod` (type: `string`):

Service method used when finding stores near ZIP codes.

## `recordTypes` (type: `array`):

Choose whether to export stores, priced menu variants, coupons, or any combination.

## `maxStores` (type: `integer`):

Maximum unique stores to process across all ZIP codes and store IDs.

## `maxItems` (type: `integer`):

Stops the run after this many total dataset records, across all selected record types.

## Actor input object example

```json
{
  "postalCodes": [
    "10001"
  ],
  "storeIds": [],
  "serviceMethod": "Delivery",
  "recordTypes": [
    "store",
    "menuItem",
    "coupon"
  ],
  "maxStores": 1,
  "maxItems": 20
}
```

# Actor output Schema

## `dataset` (type: `string`):

Domino's store, menu-item, and coupon records.

# API

You can run this Actor programmatically using our API. Below are code examples in JavaScript, Python, and CLI, as well as the OpenAPI specification and MCP server setup.

## JavaScript example

```javascript
import { ApifyClient } from 'apify-client';

// Initialize the ApifyClient with your Apify API token
// Replace the '<YOUR_API_TOKEN>' with your token
const client = new ApifyClient({
    token: '<YOUR_API_TOKEN>',
});

// Prepare Actor input
const input = {
    "postalCodes": [
        "10001"
    ]
};

// Run the Actor and wait for it to finish
const run = await client.actor("automation-lab/dominos-store-menus-pricing").call(input);

// Fetch and print Actor results from the run's dataset (if any)
console.log('Results from dataset');
console.log(`💾 Check your data here: https://console.apify.com/storage/datasets/${run.defaultDatasetId}`);
const { items } = await client.dataset(run.defaultDatasetId).listItems();
items.forEach((item) => {
    console.dir(item);
});

// 📚 Want to learn more 📖? Go to → https://docs.apify.com/api/client/js/docs

```

## Python example

```python
from apify_client import ApifyClient

# Initialize the ApifyClient with your Apify API token
# Replace '<YOUR_API_TOKEN>' with your token.
client = ApifyClient("<YOUR_API_TOKEN>")

# Prepare the Actor input
run_input = { "postalCodes": ["10001"] }

# Run the Actor and wait for it to finish
run = client.actor("automation-lab/dominos-store-menus-pricing").call(run_input=run_input)

# Fetch and print Actor results from the run's dataset (if there are any)
print(f"💾 Check your data here: https://console.apify.com/storage/datasets/{run.default_dataset_id}")
for item in client.dataset(run.default_dataset_id).iterate_items():
    print(item)

# 📚 Want to learn more 📖? Go to → https://docs.apify.com/api/client/python/docs/quick-start

```

## CLI example

```bash
echo '{
  "postalCodes": [
    "10001"
  ]
}' |
apify call automation-lab/dominos-store-menus-pricing --silent --output-dataset

```

## MCP server setup

```json
{
    "mcpServers": {
        "apify": {
            "type": "http",
            "url": "https://mcp.apify.com/?tools=fetch-actor-details,automation-lab/dominos-store-menus-pricing"
        }
    }
}
```

The hosted server signs you in with OAuth on first connect, so no API token belongs in this config. Clients without OAuth support can send an `Authorization: Bearer <APIFY_API_TOKEN>` header instead, using a token from API & Integrations in Apify Console (https://console.apify.com/settings/integrations).

## OpenAPI specification

Download the OpenAPI definition: https://api.apify.com/v2/actors/hAuhI2Uc9Rsxh7R8e/builds/hZ7o3RLkNIhBbQhyq/openapi.json
