# OpenTable + Resy Scraper (`crawlerbros/opentable-resy-scraper`) Actor

Scrape restaurant data from OpenTable and Resy in a single actor. Search by city/cuisine, look up specific restaurants by URL or slug, fetch reviews, and check Resy availability. No login required for either platform.

- **URL**: https://apify.com/crawlerbros/opentable-resy-scraper.md
- **Developed by:** [Crawler Bros](https://apify.com/crawlerbros) (community)
- **Categories:** Automation, Developer tools, Travel
- **Stats:** 2 total users, 1 monthly users, 100.0% runs succeeded, 11 bookmarks
- **User rating**: 5.00 out of 5 stars

## Pricing

from $3.00 / 1,000 results

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

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

## What's an Apify Actor?

Actors are a software tools running on the Apify platform, for all kinds of web data extraction and automation use cases.
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.

In JavaScript/TypeScript projects, use official [JavaScript/TypeScript client](https://docs.apify.com/api/client/js.md):

```bash
npm install apify-client
```

In Python projects, use official [Python client library](https://docs.apify.com/api/client/python.md):

```bash
pip install apify-client
```

In shell scripts, use [Apify CLI](https://docs.apify.com/cli/docs.md):

````bash
# MacOS / Linux
curl -fsSL https://apify.com/install-cli.sh | bash
# Windows
irm https://apify.com/install-cli.ps1 | iex
```bash

In AI frameworks, you might use the [Apify MCP server](https://docs.apify.com/platform/integrations/mcp.md).

If your project is in a different language, use 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

## OpenTable + Resy Scraper

A single Apify actor that scrapes restaurant data from both **OpenTable** and **Resy**. Switch between platforms with the `platform` input. Find restaurants by city or cuisine, look up specific venues by URL or slug, and (on Resy) check live reservation availability.

No login required for either platform.

### Features

- **Two platforms in one actor** — `platform` input picks OpenTable or Resy.
- **Five modes per platform**: search, by-restaurant, by-cuisine, by-city, by-URL.
- **Rich record fields** — name, cuisine, price range, neighborhood, address, coordinates, rating, photos, contact info, and full-text reviews (OpenTable detail pages).
- **Resy availability** (optional) — append live reservation slots from Resy's `/4/find` API.
- **Cuisine taxonomy** — 50-entry curated dropdown maps to OpenTable + Resy search terms.
- **Country filter** — drop records outside a target ISO country.
- **Price-range filter** — `$` through `$$$$`, mapped to each platform's price-band IDs.
- **Auto-escalation** — TLS-impersonated `curl_cffi` first; auto-switches to Apify Proxy (datacenter, then residential) on `403` / `429`.

### Sample input

```json
{
  "platform": "opentable",
  "mode": "search",
  "city": "New York",
  "cuisine": "italian",
  "partySize": 2,
  "maxItems": 10
}
````

```json
{
  "platform": "resy",
  "mode": "byRestaurant",
  "urls": ["https://resy.com/cities/ny/venues/carbone"],
  "includeAvailability": true,
  "day": "2026-07-15"
}
```

### Modes

| Mode | OpenTable | Resy |
|---|---|---|
| `search` | `/s/?term=...&metroId=...` — extracts `multiSearch.restaurants[]` from the SSR window-vars JSON. | `POST /3/venuesearch/search` with geo + query. |
| `byRestaurant` / `byUrl` | Detail page `/{slug}` — extracts `restaurantProfile.restaurant` + `reviewsData`. | `GET /3/venue?url_slug=...&location=...` — full venue detail. |
| `byCuisine` | Search with cuisine as the search term. | Search with cuisine as the query. |
| `byCity` | Search with city / metroId only. | Search by geo coordinates. |

### Output (per platform)

Both platforms expose a unified `entityId` (string) for cross-platform joins. The platform-specific `restaurantId` (OpenTable) and `venueId` (Resy) are still emitted alongside `entityId` for backwards compatibility.

#### OpenTable

```json
{
  "platform": "opentable",
  "entityId": "96577",
  "restaurantId": "96577",
  "name": "Sistina",
  "url": "https://www.opentable.com/sistina",
  "primaryCuisine": "Italian",
  "priceBand": "$31 to $50",
  "priceBandId": 3,
  "priceLabel": "$$$",
  "currencySymbol": "$",
  "neighborhood": "Upper East Side",
  "address": {"line1": "24 E 81st Street", "city": "New York", "state": "NY", "postCode": "10028", "country": "United States"},
  "coordinates": {"latitude": 40.776, "longitude": -73.962},
  "totalReviews": 1894,
  "overallRating": 4.7,
  "isInstantBookable": true,
  "hasPrivateDining": true,
  "coverImageUrl": "https://resizer.otstatic.com/...",
  "recordType": "restaurant",
  "scrapedAt": "..."
}
```

In `byRestaurant` mode the record additionally includes `recentReviews[]`, `hoursOfOperation[]`, `cuisines[]`, `contact`, `executiveChef`, `dressCode`, `paymentOptions`, `parkingDetails`, etc.

#### Resy

```json
{
  "platform": "resy",
  "entityId": "6194",
  "venueId": 6194,
  "name": "Carbone",
  "urlSlug": "carbone",
  "url": "https://resy.com/cities/ny/venues/carbone",
  "cuisine": ["Italian"],
  "neighborhood": "Greenwich Village",
  "priceRangeId": 4,
  "priceLabel": "$$$$",
  "currencySymbol": "$",
  "coordinates": {"latitude": 40.728, "longitude": -74.000},
  "rating": {"average": 4.74, "count": 31498},
  "address": {"line1": "181 Thompson Street", "city": "New York", "state": "NY", "country": "United States", "countryIso": "US"},
  "isGlobalDiningAccess": true,
  "coverImageUrl": "https://image.resy.com/...",
  "recordType": "restaurant",
  "scrapedAt": "..."
}
```

With `includeAvailability=true` (byRestaurant mode), each Resy record gains:

```json
"availability": {
  "day": "2026-07-15",
  "partySize": 2,
  "slotCount": 6,
  "slots": [{"start": "...", "type": "Dining Room", "id": "..."}]
}
```

### High-churn output fields

Some fields evolve rapidly between runs and should be treated as snapshot-in-time:

- **Resy `availability.slots[]` and `availability.slotCount`** — Resy slots change every few minutes as bookings fill up; the same `(venue, day, partySize)` query can return different counts on consecutive runs. Compare across the timestamp captured in `scrapedAt`, not against historical exports.
- **OpenTable `recentReservationCount`** — daily booking counter; rolls over each midnight in the venue's local timezone.
- **`overallRating`, `totalReviews`, Resy `rating.average`/`rating.count`** — providers' aggregate review stats update as new reviews are posted; expect minor drift on each run.
- **`recentReviews[]` (OpenTable)** — most-recent review window changes daily; absent from a run does not mean the venue lost reviews.
- **Photos and `coverImageUrl`** — CDN URLs may rotate; the resource itself is usually stable but the URL string can change.

Stable fields safe for diff/dedup: `restaurantId`/`venueId`, `entityId`, `name`, `url`, `address`, `coordinates`, `priceBand`/`priceRangeId`, `cuisines`/`primaryCuisine`.

### Limitations

- **Resy reviews are not exposed** in the public API — only aggregate rating + count. Use OpenTable for full review text.
- **OpenTable detail URL has two forms**: `/{slug}` (legacy) and `/r/{slug}` (newer). Only one form returns a populated SSR page per restaurant; the actor probes the user-supplied form first, then auto-falls back to the alternate.
- **OpenTable search returns ~50 restaurants per page** — beyond that, paginate by changing `metroId` or `cuisine`.
- **Resy availability requires a `day` parameter** — the actor defaults to 14 days from today; override via the `day` input. Dates farther than 365 days in the future are rejected.
- The Resy widget `api_key` may rotate; the actor harvests a fresh one from `resy.com/modules/app.*.js` at startup if the bundled key fails.

### FAQ

**Do I need login cookies?** No. Both APIs are public, served from datacenter IPs.

**Does it support international markets?** Yes — OpenTable covers 25+ countries (US, CA, UK, France, Germany, Italy, Spain, Australia, Mexico, etc.). Resy covers US, UK, Mexico, Australia, France, and a handful of other markets. Use the `country` filter to scope output.

**Can I scrape both platforms in one run?** Not in a single call — run the actor twice with `platform=opentable` and `platform=resy` and merge the datasets downstream.

**Why does my run keep getting 403?** OpenTable is fronted by Akamai BMP. The actor auto-escalates to Apify Proxy (datacenter, then residential) on 403/429 if `autoEscalateOnBlock=true`.

**Is this legal?** This actor only fetches public, unauthenticated restaurant directory data (names, addresses, cuisines, public reviews) — the same data any visitor sees on the website. No reservations are placed and no user data is collected. You are responsible for complying with each platform's Terms of Service in your jurisdiction.

# Actor input Schema

## `platform` (type: `string`):

Which restaurant platform to scrape.

## `mode` (type: `string`):

What to scrape.

## `city` (type: `string`):

City name. OpenTable resolves popular cities to a metroId; Resy resolves them to (lat, long). Falls back to free-text on OpenTable, NYC on Resy.

## `metroId` (type: `integer`):

Override OpenTable's city resolution by passing a metroId directly. e.g. 8=NYC, 4=LA, 6=Chicago, 113=London. Most users should leave blank and use `city`.

## `cuisine` (type: `string`):

Cuisine taxonomy. Supplied as a search term on both platforms.

## `query` (type: `string`):

Free-text query in addition to / instead of `cuisine`. Combined into a single search term.

## `urls` (type: `array`):

OpenTable URLs (`https://www.opentable.com/{slug}`), Resy URLs (`https://resy.com/cities/{city}/venues/{slug}`), or plain slugs. The actor parses both forms.

## `country` (type: `string`):

Drop records whose address country doesn't match.

## `priceRange` (type: `string`):

Filter by price band. $ = under $30, $$ = $30-50, $$$ = $50-75, $$$$ = $75+ (per platform's own bands).

## `minRating` (type: `integer`):

Drop restaurants with overall rating below this. 1-5 scale on both platforms.

## `partySize` (type: `integer`):

Used for OpenTable search availability scoring and Resy availability lookup.

## `dateTime` (type: `string`):

ISO datetime for OpenTable search (e.g. `2026-06-15T19:00:00`). Defaults to two weeks from today at 19:00.

## `day` (type: `string`):

ISO date (`YYYY-MM-DD`) for Resy availability lookup. Defaults to two weeks from today. Required by Resy's `/4/find` API.

## `latitude` (type: `string`):

Override Resy geo lookup with explicit latitude. Use with `longitude`.

## `longitude` (type: `string`):

Override Resy geo lookup with explicit longitude. Use with `latitude`.

## `includeAvailability` (type: `boolean`):

Add a `/4/find` lookup per venue and append the available reservation slots. Slows the run.

## `enrichDetailPages` (type: `boolean`):

After OpenTable search, also fetch each restaurant's detail page (slow). Adds reviews, hours, contact info.

## `resyApiKey` (type: `string`):

Override the bundled Resy widget api\_key. Leave blank — actor harvests a fresh key from resy.com on startup if the bundled one breaks.

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

Hard cap on emitted records.

## `autoEscalateOnBlock` (type: `boolean`):

If true (default), the actor automatically engages Apify Proxy when it hits HTTP 403 / 429 from a raw datacenter IP. Set false to fail fast without proxy.

## `proxyGroups` (type: `array`):

Apify proxy groups to use when auto-escalating after a block. Empty = datacenter (default), then residential fallback.

## Actor input object example

```json
{
  "platform": "opentable",
  "mode": "search",
  "city": "New York",
  "urls": [],
  "partySize": 2,
  "includeAvailability": false,
  "enrichDetailPages": false,
  "maxItems": 10,
  "autoEscalateOnBlock": true,
  "proxyGroups": []
}
```

# Actor output Schema

## `records` (type: `string`):

Dataset of all scraped restaurants.

# 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 = {
    "platform": "opentable",
    "mode": "search",
    "city": "New York",
    "partySize": 2,
    "includeAvailability": false,
    "enrichDetailPages": false,
    "maxItems": 10,
    "autoEscalateOnBlock": true
};

// Run the Actor and wait for it to finish
const run = await client.actor("crawlerbros/opentable-resy-scraper").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 = {
    "platform": "opentable",
    "mode": "search",
    "city": "New York",
    "partySize": 2,
    "includeAvailability": False,
    "enrichDetailPages": False,
    "maxItems": 10,
    "autoEscalateOnBlock": True,
}

# Run the Actor and wait for it to finish
run = client.actor("crawlerbros/opentable-resy-scraper").call(run_input=run_input)

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

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

```

## CLI example

```bash
echo '{
  "platform": "opentable",
  "mode": "search",
  "city": "New York",
  "partySize": 2,
  "includeAvailability": false,
  "enrichDetailPages": false,
  "maxItems": 10,
  "autoEscalateOnBlock": true
}' |
apify call crawlerbros/opentable-resy-scraper --silent --output-dataset

```

## MCP server setup

```json
{
    "mcpServers": {
        "apify": {
            "command": "npx",
            "args": [
                "mcp-remote",
                "https://mcp.apify.com/?tools=crawlerbros/opentable-resy-scraper",
                "--header",
                "Authorization: Bearer <YOUR_API_TOKEN>"
            ]
        }
    }
}

```

## OpenAPI specification

```json
{
    "openapi": "3.0.1",
    "info": {
        "title": "OpenTable + Resy Scraper",
        "description": "Scrape restaurant data from OpenTable and Resy in a single actor. Search by city/cuisine, look up specific restaurants by URL or slug, fetch reviews, and check Resy availability. No login required for either platform.",
        "version": "1.0",
        "x-build-id": "uwhTh9uFwlH7Zeb2B"
    },
    "servers": [
        {
            "url": "https://api.apify.com/v2"
        }
    ],
    "paths": {
        "/acts/crawlerbros~opentable-resy-scraper/run-sync-get-dataset-items": {
            "post": {
                "operationId": "run-sync-get-dataset-items-crawlerbros-opentable-resy-scraper",
                "x-openai-isConsequential": false,
                "summary": "Executes an Actor, waits for its completion, and returns Actor's dataset items in response.",
                "tags": [
                    "Run Actor"
                ],
                "requestBody": {
                    "required": true,
                    "content": {
                        "application/json": {
                            "schema": {
                                "$ref": "#/components/schemas/inputSchema"
                            }
                        }
                    }
                },
                "parameters": [
                    {
                        "name": "token",
                        "in": "query",
                        "required": true,
                        "schema": {
                            "type": "string"
                        },
                        "description": "Enter your Apify token here"
                    }
                ],
                "responses": {
                    "200": {
                        "description": "OK"
                    }
                }
            }
        },
        "/acts/crawlerbros~opentable-resy-scraper/runs": {
            "post": {
                "operationId": "runs-sync-crawlerbros-opentable-resy-scraper",
                "x-openai-isConsequential": false,
                "summary": "Executes an Actor and returns information about the initiated run in response.",
                "tags": [
                    "Run Actor"
                ],
                "requestBody": {
                    "required": true,
                    "content": {
                        "application/json": {
                            "schema": {
                                "$ref": "#/components/schemas/inputSchema"
                            }
                        }
                    }
                },
                "parameters": [
                    {
                        "name": "token",
                        "in": "query",
                        "required": true,
                        "schema": {
                            "type": "string"
                        },
                        "description": "Enter your Apify token here"
                    }
                ],
                "responses": {
                    "200": {
                        "description": "OK",
                        "content": {
                            "application/json": {
                                "schema": {
                                    "$ref": "#/components/schemas/runsResponseSchema"
                                }
                            }
                        }
                    }
                }
            }
        },
        "/acts/crawlerbros~opentable-resy-scraper/run-sync": {
            "post": {
                "operationId": "run-sync-crawlerbros-opentable-resy-scraper",
                "x-openai-isConsequential": false,
                "summary": "Executes an Actor, waits for completion, and returns the OUTPUT from Key-value store in response.",
                "tags": [
                    "Run Actor"
                ],
                "requestBody": {
                    "required": true,
                    "content": {
                        "application/json": {
                            "schema": {
                                "$ref": "#/components/schemas/inputSchema"
                            }
                        }
                    }
                },
                "parameters": [
                    {
                        "name": "token",
                        "in": "query",
                        "required": true,
                        "schema": {
                            "type": "string"
                        },
                        "description": "Enter your Apify token here"
                    }
                ],
                "responses": {
                    "200": {
                        "description": "OK"
                    }
                }
            }
        }
    },
    "components": {
        "schemas": {
            "inputSchema": {
                "type": "object",
                "required": [
                    "platform",
                    "mode"
                ],
                "properties": {
                    "platform": {
                        "title": "Platform",
                        "enum": [
                            "opentable",
                            "resy"
                        ],
                        "type": "string",
                        "description": "Which restaurant platform to scrape.",
                        "default": "opentable"
                    },
                    "mode": {
                        "title": "Mode",
                        "enum": [
                            "search",
                            "byRestaurant",
                            "byCuisine",
                            "byCity",
                            "byUrl"
                        ],
                        "type": "string",
                        "description": "What to scrape.",
                        "default": "search"
                    },
                    "city": {
                        "title": "City (mode=search/byCuisine/byCity)",
                        "type": "string",
                        "description": "City name. OpenTable resolves popular cities to a metroId; Resy resolves them to (lat, long). Falls back to free-text on OpenTable, NYC on Resy.",
                        "default": "New York"
                    },
                    "metroId": {
                        "title": "OpenTable metroId (advanced, optional)",
                        "minimum": 1,
                        "maximum": 100000,
                        "type": "integer",
                        "description": "Override OpenTable's city resolution by passing a metroId directly. e.g. 8=NYC, 4=LA, 6=Chicago, 113=London. Most users should leave blank and use `city`."
                    },
                    "cuisine": {
                        "title": "Cuisine (mode=search/byCuisine)",
                        "enum": [
                            "italian",
                            "french",
                            "japanese",
                            "chinese",
                            "thai",
                            "indian",
                            "mexican",
                            "spanish",
                            "greek",
                            "mediterranean",
                            "korean",
                            "vietnamese",
                            "american",
                            "steakhouse",
                            "seafood",
                            "sushi",
                            "pizza",
                            "tapas",
                            "bbq",
                            "vegan",
                            "vegetarian",
                            "fusion",
                            "asian",
                            "latin american",
                            "caribbean",
                            "middle eastern",
                            "lebanese",
                            "turkish",
                            "moroccan",
                            "ethiopian",
                            "german",
                            "british",
                            "irish",
                            "scandinavian",
                            "argentinian",
                            "brazilian",
                            "peruvian",
                            "tex-mex",
                            "soul food",
                            "southern",
                            "diner",
                            "gastropub",
                            "bistro",
                            "brasserie",
                            "fine dining",
                            "small plates",
                            "raw bar",
                            "wine bar",
                            "cocktail bar",
                            "brunch",
                            "breakfast"
                        ],
                        "type": "string",
                        "description": "Cuisine taxonomy. Supplied as a search term on both platforms."
                    },
                    "query": {
                        "title": "Free-text search query (mode=search)",
                        "type": "string",
                        "description": "Free-text query in addition to / instead of `cuisine`. Combined into a single search term."
                    },
                    "urls": {
                        "title": "Restaurant URLs or slugs (mode=byRestaurant/byUrl)",
                        "type": "array",
                        "description": "OpenTable URLs (`https://www.opentable.com/{slug}`), Resy URLs (`https://resy.com/cities/{city}/venues/{slug}`), or plain slugs. The actor parses both forms.",
                        "default": [],
                        "items": {
                            "type": "string"
                        }
                    },
                    "country": {
                        "title": "Country filter (ISO 3166-1 alpha-2)",
                        "enum": [
                            "US",
                            "CA",
                            "GB",
                            "IE",
                            "FR",
                            "DE",
                            "IT",
                            "ES",
                            "PT",
                            "NL",
                            "AT",
                            "CH",
                            "BE",
                            "DK",
                            "SE",
                            "NO",
                            "FI",
                            "AU",
                            "NZ",
                            "JP",
                            "HK",
                            "SG",
                            "AE",
                            "MX",
                            "AR",
                            "BR"
                        ],
                        "type": "string",
                        "description": "Drop records whose address country doesn't match."
                    },
                    "priceRange": {
                        "title": "Price range",
                        "enum": [
                            "$",
                            "$$",
                            "$$$",
                            "$$$$"
                        ],
                        "type": "string",
                        "description": "Filter by price band. $ = under $30, $$ = $30-50, $$$ = $50-75, $$$$ = $75+ (per platform's own bands)."
                    },
                    "minRating": {
                        "title": "Minimum rating",
                        "minimum": 1,
                        "maximum": 5,
                        "type": "integer",
                        "description": "Drop restaurants with overall rating below this. 1-5 scale on both platforms."
                    },
                    "partySize": {
                        "title": "Party size",
                        "minimum": 1,
                        "maximum": 12,
                        "type": "integer",
                        "description": "Used for OpenTable search availability scoring and Resy availability lookup.",
                        "default": 2
                    },
                    "dateTime": {
                        "title": "OpenTable reservation datetime (advanced)",
                        "type": "string",
                        "description": "ISO datetime for OpenTable search (e.g. `2026-06-15T19:00:00`). Defaults to two weeks from today at 19:00."
                    },
                    "day": {
                        "title": "Resy availability day (mode=byRestaurant on Resy)",
                        "type": "string",
                        "description": "ISO date (`YYYY-MM-DD`) for Resy availability lookup. Defaults to two weeks from today. Required by Resy's `/4/find` API."
                    },
                    "latitude": {
                        "title": "Latitude (Resy advanced)",
                        "type": "string",
                        "description": "Override Resy geo lookup with explicit latitude. Use with `longitude`."
                    },
                    "longitude": {
                        "title": "Longitude (Resy advanced)",
                        "type": "string",
                        "description": "Override Resy geo lookup with explicit longitude. Use with `latitude`."
                    },
                    "includeAvailability": {
                        "title": "Include Resy availability (mode=byRestaurant on Resy)",
                        "type": "boolean",
                        "description": "Add a `/4/find` lookup per venue and append the available reservation slots. Slows the run.",
                        "default": false
                    },
                    "enrichDetailPages": {
                        "title": "Enrich OpenTable search hits with detail pages",
                        "type": "boolean",
                        "description": "After OpenTable search, also fetch each restaurant's detail page (slow). Adds reviews, hours, contact info.",
                        "default": false
                    },
                    "resyApiKey": {
                        "title": "Resy api_key (advanced override)",
                        "type": "string",
                        "description": "Override the bundled Resy widget api_key. Leave blank — actor harvests a fresh key from resy.com on startup if the bundled one breaks."
                    },
                    "maxItems": {
                        "title": "Max items",
                        "minimum": 1,
                        "maximum": 1000,
                        "type": "integer",
                        "description": "Hard cap on emitted records.",
                        "default": 10
                    },
                    "autoEscalateOnBlock": {
                        "title": "Auto-escalate to Apify proxy on block",
                        "type": "boolean",
                        "description": "If true (default), the actor automatically engages Apify Proxy when it hits HTTP 403 / 429 from a raw datacenter IP. Set false to fail fast without proxy.",
                        "default": true
                    },
                    "proxyGroups": {
                        "title": "Apify proxy groups (used on auto-escalation)",
                        "type": "array",
                        "description": "Apify proxy groups to use when auto-escalating after a block. Empty = datacenter (default), then residential fallback.",
                        "default": [],
                        "items": {
                            "type": "string"
                        }
                    }
                }
            },
            "runsResponseSchema": {
                "type": "object",
                "properties": {
                    "data": {
                        "type": "object",
                        "properties": {
                            "id": {
                                "type": "string"
                            },
                            "actId": {
                                "type": "string"
                            },
                            "userId": {
                                "type": "string"
                            },
                            "startedAt": {
                                "type": "string",
                                "format": "date-time",
                                "example": "2025-01-08T00:00:00.000Z"
                            },
                            "finishedAt": {
                                "type": "string",
                                "format": "date-time",
                                "example": "2025-01-08T00:00:00.000Z"
                            },
                            "status": {
                                "type": "string",
                                "example": "READY"
                            },
                            "meta": {
                                "type": "object",
                                "properties": {
                                    "origin": {
                                        "type": "string",
                                        "example": "API"
                                    },
                                    "userAgent": {
                                        "type": "string"
                                    }
                                }
                            },
                            "stats": {
                                "type": "object",
                                "properties": {
                                    "inputBodyLen": {
                                        "type": "integer",
                                        "example": 2000
                                    },
                                    "rebootCount": {
                                        "type": "integer",
                                        "example": 0
                                    },
                                    "restartCount": {
                                        "type": "integer",
                                        "example": 0
                                    },
                                    "resurrectCount": {
                                        "type": "integer",
                                        "example": 0
                                    },
                                    "computeUnits": {
                                        "type": "integer",
                                        "example": 0
                                    }
                                }
                            },
                            "options": {
                                "type": "object",
                                "properties": {
                                    "build": {
                                        "type": "string",
                                        "example": "latest"
                                    },
                                    "timeoutSecs": {
                                        "type": "integer",
                                        "example": 300
                                    },
                                    "memoryMbytes": {
                                        "type": "integer",
                                        "example": 1024
                                    },
                                    "diskMbytes": {
                                        "type": "integer",
                                        "example": 2048
                                    }
                                }
                            },
                            "buildId": {
                                "type": "string"
                            },
                            "defaultKeyValueStoreId": {
                                "type": "string"
                            },
                            "defaultDatasetId": {
                                "type": "string"
                            },
                            "defaultRequestQueueId": {
                                "type": "string"
                            },
                            "buildNumber": {
                                "type": "string",
                                "example": "1.0.0"
                            },
                            "containerUrl": {
                                "type": "string"
                            },
                            "usage": {
                                "type": "object",
                                "properties": {
                                    "ACTOR_COMPUTE_UNITS": {
                                        "type": "integer",
                                        "example": 0
                                    },
                                    "DATASET_READS": {
                                        "type": "integer",
                                        "example": 0
                                    },
                                    "DATASET_WRITES": {
                                        "type": "integer",
                                        "example": 0
                                    },
                                    "KEY_VALUE_STORE_READS": {
                                        "type": "integer",
                                        "example": 0
                                    },
                                    "KEY_VALUE_STORE_WRITES": {
                                        "type": "integer",
                                        "example": 1
                                    },
                                    "KEY_VALUE_STORE_LISTS": {
                                        "type": "integer",
                                        "example": 0
                                    },
                                    "REQUEST_QUEUE_READS": {
                                        "type": "integer",
                                        "example": 0
                                    },
                                    "REQUEST_QUEUE_WRITES": {
                                        "type": "integer",
                                        "example": 0
                                    },
                                    "DATA_TRANSFER_INTERNAL_GBYTES": {
                                        "type": "integer",
                                        "example": 0
                                    },
                                    "DATA_TRANSFER_EXTERNAL_GBYTES": {
                                        "type": "integer",
                                        "example": 0
                                    },
                                    "PROXY_RESIDENTIAL_TRANSFER_GBYTES": {
                                        "type": "integer",
                                        "example": 0
                                    },
                                    "PROXY_SERPS": {
                                        "type": "integer",
                                        "example": 0
                                    }
                                }
                            },
                            "usageTotalUsd": {
                                "type": "number",
                                "example": 0.00005
                            },
                            "usageUsd": {
                                "type": "object",
                                "properties": {
                                    "ACTOR_COMPUTE_UNITS": {
                                        "type": "integer",
                                        "example": 0
                                    },
                                    "DATASET_READS": {
                                        "type": "integer",
                                        "example": 0
                                    },
                                    "DATASET_WRITES": {
                                        "type": "integer",
                                        "example": 0
                                    },
                                    "KEY_VALUE_STORE_READS": {
                                        "type": "integer",
                                        "example": 0
                                    },
                                    "KEY_VALUE_STORE_WRITES": {
                                        "type": "number",
                                        "example": 0.00005
                                    },
                                    "KEY_VALUE_STORE_LISTS": {
                                        "type": "integer",
                                        "example": 0
                                    },
                                    "REQUEST_QUEUE_READS": {
                                        "type": "integer",
                                        "example": 0
                                    },
                                    "REQUEST_QUEUE_WRITES": {
                                        "type": "integer",
                                        "example": 0
                                    },
                                    "DATA_TRANSFER_INTERNAL_GBYTES": {
                                        "type": "integer",
                                        "example": 0
                                    },
                                    "DATA_TRANSFER_EXTERNAL_GBYTES": {
                                        "type": "integer",
                                        "example": 0
                                    },
                                    "PROXY_RESIDENTIAL_TRANSFER_GBYTES": {
                                        "type": "integer",
                                        "example": 0
                                    },
                                    "PROXY_SERPS": {
                                        "type": "integer",
                                        "example": 0
                                    }
                                }
                            }
                        }
                    }
                }
            }
        }
    }
}
```
