# Resy Real-Time Data — Restaurants, Contacts & Leads (`b2b_leads/resy-real-time-data`) Actor

Collect fresh Resy restaurant data from any market: cuisine, price tier, ratings, reviews, address, coordinates and curated lists. Add contact enrichment for websites, phones, emails and socials. Free plan returns a 2-result sample; paid plans are unlimited.

- **URL**: https://apify.com/b2b\_leads/resy-real-time-data.md
- **Developed by:** [Emmanuel](https://apify.com/b2b_leads) (community)
- **Stats:** 2 total users, 1 monthly users, 100.0% runs succeeded, 0 bookmarks
- **User rating**: No ratings yet

## Pricing

from $2.00 / 1,000 results

This Actor is paid per event. You are not charged for the Apify platform usage, but only a fixed price for specific events.

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

## What's an Apify Actor?

An Actor is a serverless cloud program that runs on the Apify platform. It has two run modes.
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.

Apify vocabulary and the platform model are defined once, in the agent quickstart at https://apify.com/agents.md.

## 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.

Do not guess an integration path. Every one of them is in the agent quickstart at https://apify.com/agents.md: the Apify MCP server, Agent Skills with the Apify CLI, the JavaScript and Python clients, the REST API, and the account-free path for an agent with no human to sign in. It also carries the rule on stating cost before the first paid run.

For examples already wired to this Actor's own input schema, see the [API](#api) section below.

Each client library has reference documentation the quickstart does not restate: [JavaScript/TypeScript](https://docs.apify.com/api/client/js/docs.md) (`npm install apify-client`) and [Python](https://docs.apify.com/api/client/python/docs.md) (`pip install apify-client`).

# README

## Resy Real-Time Data

**Turn Resy into a clean, structured restaurant database.** Discover restaurants across any market and cuisine, pull full venue profiles, and capture names, cuisines, price tiers, average spend, ratings, review counts, full street addresses, cross streets, coordinates, neighbourhoods, restaurant groups, curated list memberships, descriptions, photos and location IDs — all as **clean, structured JSON streamed to your Apify dataset in real time.**

Switch on **Contact Enrichment** and each row also carries the venue's own **website, phone number, email addresses and social profiles** — turning market data into an outreach-ready lead list without a second tool.

Built for lead-gen agencies, restaurant-tech companies, hospitality groups, market researchers, real-estate and site-selection teams, sales teams and AI workflows that need **reliable Resy data without slow, high-maintenance tooling.**

> 💡 **Free plan vs paid plan.** This Actor is designed for **paid Apify plans**. Free (non-paying) Apify accounts run in a **restricted mode and receive only a small sample (2 results)** — upgrade to a **paid Apify plan** to unlock full, unlimited output. The restriction is intentional (not a bug), is repeated on the relevant input fields, and is reported in the run output under `paywall`.

***

### Why this Actor

| | Resy Real-Time Data | Typical Resy setup |
|---|---------------------|--------------------|
| **Speed** | Fast collection, many markets at once | Often 5–20 s per venue |
| **Memory** | **1024 MB** default — light, streaming output | 2–4 GB+, data accumulates in memory |
| **Reliability** | Managed Apify residential proxy + automatic recovery from temporary hiccups | Breaks on the first hiccup |
| **Setup** | Clean, organised input UI — run in seconds | Fragile scripts you maintain yourself |
| **Output** | One flat, LLM-ready JSON row per venue | Messy markup that still needs cleaning |
| **Multi-market** | Many keyword + market pairs per run | Usually one query at a time |
| **Coverage** | Single market, many markets, **or the entire catalog** | Usually one city at a time |
| **Delivery** | Dataset streaming **+ optional real-time webhook** | Dataset only |

***

### What you get — 68 data points per venue

Every row is tagged with `featureType` and `scrapedAt` so you can filter, join and pipe it into any workflow.

| Group | Fields |
|-------|--------|
| **Identity** | `venueId`, `name`, `slug`, `url`, `deepLink`, `cuisine` |
| **Story** | `description`, `whyWeLikeIt`, `needToKnow`, `tagline`, `fromTheVenue`, `pickupDescription` |
| **Location** | `addressLine1`, `addressLine2`, `crossStreet1`, `crossStreet2`, `neighborhood`, `city`, `region`, `postCode`, `country`, `countryCode`, `formattedAddress`, `latitude`, `longitude` |
| **Pricing & spend** | `priceTierId`, `priceRange` (`$`–`$$$$`), `averageBillSize`, `currencySymbol`, `currencyCode` |
| **Reputation** | `rating`, `reviewCount`, `ratingsBySource[]` |
| **Curation** | `collections[]` (e.g. *Top Rated*, *Date Night*, *Good for Groups*), `collectionSlugs[]`, `globalDiningAccess`, `globalDiningAccessOnly` |
| **Group & availability** | `venueGroupId`, `venueGroupName`, `waitlistAvailable`, `waitlistLabel`, `locationId` |
| **Media** | `photoUrl`, `imageUrls[]` |
| **Join keys** | `googlePlaceId`, `foursquareId` |
| **📇 Contacts** *(with Contact Enrichment)* | `website`, `phone`, `email`, `emails[]`, `emailIsGeneric`, `socials[]`, `instagram`, `facebook`, `x`, `tiktok` |
| **Enrichment audit** | `enrichmentStatus`, `enrichmentMatchConfidence`, `enrichmentDistanceMeters`, `enrichedAt` |
| **Traceability** | `marketCode`, `marketLabel`, `searchKeyword`, `searchIndex`, `sourceUrl`, `featureType`, `scrapedAt` |

Available dataset views: **Overview**, **Discovery**, **Catalog**, **Locations**, **Contacts**, **Lead list**, **Profiles**.

***

### Features

#### 🍽️ Venue Discovery — on by default

Discover restaurants by **market**, with an optional **keyword** filter on every task. Add as many rows as you like — *sushi in New York*, *steakhouse in Chicago*, *brunch in Austin* — and they all run in a single job.

- Keyword matches the venue name, cuisine, neighbourhood, city and curated list memberships, so searches like `"Date Night"`, `"omakase"` or `"West Village"` all work.
- Target any market — dozens of major US, Canadian and European markets are recognised out of the box, and custom areas work through coordinates.
- Optional **party size** and **day** for availability-aware collection.
- Control results per task and collection depth for very large runs.
- Every row streams to the dataset as it is collected — memory stays flat on long runs.

#### 🌍 Full Catalog Scan

Walk the **entire catalog** and narrow it down with your own scope filters — countries, states/regions, cities and a keyword. This is the feature for national and multi-country projects:

- *“Every venue in Texas”* → `catalogRegions: ["TX"]`
- *“Every venue in Canada”* → `catalogCountries: ["CA"]`
- *“Every sushi venue across the US”* → `catalogCountries: ["US"]`, `catalogKeyword: "sushi"`

Results stream to the dataset as they are found, so the run stays light no matter how deep it goes.

#### 📍 Venue Details

Already have a list of Resy venues? Paste **venue URLs** and/or **numeric venue IDs** to receive a **complete structured profile** for each one — cuisine, price tier, rating, review count, full address, cross streets, coordinates, curated list memberships, descriptions, photos and location IDs.

- **Venue URLs** (e.g. `https://resy.com/cities/new-york-ny/venues/caviar-cafe`) resolve quickly and precisely, including Resy deep links.
- **Venue IDs** are resolved from the catalog, so allow a little extra time per ID.

#### 📇 Contact Enrichment — website, phone, email, socials

Venue listings carry no phone number, email address or website of their own, so contact details have to be resolved separately. Turn this on and the Actor does it for you:

- **Website & phone number** — each venue's own site and phone number are resolved and attached.
- **Email addresses** — that website is then read for email addresses (`emails[]` plus a primary `email`), including contact and about pages.
- **`emailIsGeneric`** — flags a shared/role mailbox (`info@`, `reservations@`) versus a named person, so you can prioritise.
- **Social profiles** — `instagram`, `facebook`, `x`, `tiktok` and a `socials[]` list.

**Nothing is ever guessed.** Details are attached **only when the venue is confidently identified**, using both a strong name match *and* proximity. An uncertain result is reported instead of forced:

| `enrichmentStatus` | Meaning |
|---|---|
| `enriched` | Website and/or phone attached (plus email/socials where the site publishes them) |
| `partial` | Venue matched but its listing publishes no website or phone |
| `not_found` | No confident match — record saved unchanged |
| `failed` | Resolution was temporarily unavailable — record saved unchanged |
| `skipped_no_location` | Venue has no name or coordinates to resolve from |
| `not_requested` | Enrichment was switched off |

Use `enrichmentMatchConfidence` (0–1) and `enrichmentDistanceMeters` to triage borderline rows yourself. Enrichment is **off by default** because it adds a little extra time per venue — turn it on when you need contactable leads. It also fills gaps only: a value the venue itself published always wins.

#### 🔔 Webhooks (real-time delivery)

Every record is **always written to the Apify dataset first**. If you set a **Webhook URL**, each new record is **also POSTed in real time** to your CRM, Slack, Zapier, Make, Google Sheets or custom destination. Choose JSON (full record) or a Slack-friendly message. Delivery is best-effort — a failed webhook never stops the run.

#### 💳 Billing

Billed per result via Apify pay-per-event. Runs respect your **maximum cost per run** and finish gracefully at the limit.

***

### Use cases

- **Restaurant lead generation** — build outreach lists for any market and cuisine with full address, neighbourhood and coordinates.
- **Cold outreach lists with phone & email** — enable **Contact Enrichment** to get a callable, emailable list of venues, plus whose websites and social profiles to review before you pitch.
- **Local SEO & web-agency prospecting** — find venues whose website is missing, thin or an unmanaged social page, and pitch them site and marketing work.
- **Restaurant marketing & PR agencies** — assemble prospect lists with the venue's own email address and Instagram already attached.
- **Menu, POS & payments vendors** — reach owners and operators directly instead of guessing contact details.
- **Supplier & distributor outreach** — find every venue by cuisine, price tier and neighbourhood, then contact them without a separate lookup step.
- **Restaurant-tech sales prospecting** — POS, reservations, delivery, marketing, payments and supply vendors can size any market in one run.
- **Market mapping & density** — see how many venues exist per neighbourhood, city or state, and at what price tiers.
- **Competitive intelligence** — track ratings, review counts and curated list placements across competitors.
- **Cuisine gap analysis** — find under-served cuisines and neighbourhoods before opening or expanding.
- **Site selection & real estate** — score locations by surrounding dining density, price tier and ratings.
- **Territory planning for field sales** — export addresses plus coordinates and route reps by neighbourhood.
- **Hospitality group expansion** — benchmark a concept against every comparable venue in a new metro.
- **Price positioning studies** — benchmark price tiers by cuisine and market.
- **Reputation monitoring** — watch rating and review-count movement for a portfolio of venues.
- **Curated list intelligence** — find every venue on lists like *Top Rated*, *Date Night*, *Best of Brunch* or *Good for Groups*.
- **Award & credibility screening** — use curated list membership as a quality proxy for target lists.
- **Data enrichment** — start from a URL or ID list and backfill complete structured profiles.
- **Data licensing & enrichment products** — join on `googlePlaceId` / `foursquareId` to blend with any other dataset.
- **AI & LLM pipelines** — JSON for RAG, scoring, outreach drafts and territory summaries.
- **CRM & warehouse feeds** — stream to your systems via webhook or the Apify API.
- **Travel & tourism research** — map dining options for any destination city.
- **Event & group planning products** — power “where should we eat” tools with real venue data.
- **Franchise feasibility studies** — size demand for a concept in a new region.
- **Supplier prospecting** — find venues by cuisine, price tier and location for B2B outreach.

***

### Input reference

Enable only what you need. All features are independent.

| Input | Type | Default | Description |
|-------|------|---------|-------------|
| **Venue Discovery** | | | |
| `enableSearch` | boolean | `true` | Discover restaurants by keyword + market |
| `searchTasks` | object\[] | 2 example rows | Primary input: `{ keyword?, location, maxItems?, partySize?, day?, latitude?, longitude? }` per row |
| `maxPagesPerTask` | integer | `30` | Collection-depth safety ceiling per market |
| **Full Catalog Scan** | | | |
| `enableCatalogScan` | boolean | `false` | Scan the whole catalog and keep what matches your filters |
| `catalogCountries` | string\[] | — | Keep only these countries (ISO code or name) |
| `catalogRegions` | string\[] | — | Keep only these states / provinces / regions |
| `catalogCities` | string\[] | — | Keep only these cities or neighbourhoods |
| `catalogKeyword` | string | — | Keyword applied to the whole catalog scan |
| **Venue Details** | | | |
| `enableVenueDetails` | boolean | `false` | Get full profiles for specific venues |
| `venueUrls` | string\[] | — | Resy venue URLs or deep links |
| `venueIds` | string\[] | — | Numeric Resy venue IDs |
| **Contact Enrichment** | | | |
| `enableContactEnrichment` | boolean | `false` | Also resolve each venue's own website, phone number, email addresses and social profiles. Adds a little extra time per venue |
| **Output & limits** | | | |
| `maxItems` | integer | `1000` | Global cap on dataset rows for the run (set higher for large runs) |
| `webhookUrl` | string | — | Optional real-time POST URL — dataset is always written; webhook is additional |
| `webhookFormat` | enum | `json` | `json` (full record) or `slack` (Slack message) |
| **Connection** | | | |
| `proxyConfiguration` | object | Apify residential (US) | Apify proxy settings (on by default) |

Full schema: see `.actor/input_schema.json` or the **Input** tab on Apify Console.

***

### Output reference

Each dataset row is one venue. Filter by `featureType`:

| `featureType` | Description |
|---------------|-------------|
| `venue_discovery` | Venue from a keyword + market task |
| `market_catalog` | Venue kept from the full catalog scan |
| `venue_details` | Full profile from a venue URL or venue ID |

**Traceability fields on discovery results:**

- `marketLabel` — e.g. `"sushi \| New York, NY"`
- `searchKeyword` — the keyword that produced this row
- `searchIndex` — 1-based position within the market

**Contact fields** (populated when `enableContactEnrichment` is on): `website`, `phone`, `email`, `emails[]`, `emailIsGeneric`, `socials[]`, `instagram`, `facebook`, `x`, `tiktok`, plus the audit fields `enrichmentStatus`, `enrichmentMatchConfidence`, `enrichmentDistanceMeters` and `enrichedAt`.

**Built-in dataset views:** Overview · Discovery · Catalog · Locations · **Contacts** · **Lead list** · Profiles.

Export formats: **JSON**, **CSV**, **Excel**, **RSS**, or via the **API**.

**Run order.** When several features are enabled, explicitly requested **Venue Profiles** run first (so a URL/ID list is always delivered), then **Venue Discovery**, then the **Full Catalog Scan** — each filling whatever remains of `maxItems`. Records are deduplicated within each feature, so you never pay twice for the same venue.

#### Example record — discovery

```json
{
  "featureType": "venue_discovery",
  "venueId": 94731,
  "slug": "caviar-cafe",
  "name": "Caviar Cafe",
  "url": "https://resy.com/cities/new-york-ny/venues/caviar-cafe",
  "deepLink": "resy://resy.com/VenueDetails?venue_id=94731",
  "cuisine": "Russian",
  "description": "Caviar Cafe is a relaxed yet refined spot for elevated breakfast, specialty coffee, and premium caviar service.",
  "whyWeLikeIt": "It's rare to find a spot so fully devoted to brunch…",
  "needToKnow": "Walk-ins welcome at the bar; reservations recommended for brunch.",
  "tagline": null,
  "fromTheVenue": null,
  "neighborhood": "West Village",
  "city": "New York",
  "region": "NY",
  "postCode": "10014",
  "country": "United States",
  "countryCode": "US",
  "addressLine1": "394 West Street",
  "addressLine2": "west village",
  "crossStreet1": "10th",
  "crossStreet2": null,
  "formattedAddress": "394 West Street, west village, West Village, New York, NY, 10014",
  "latitude": 40.73324714751342,
  "longitude": -74.00999967491748,
  "priceTierId": 3,
  "priceRange": "$$$",
  "currencySymbol": "$",
  "currencyCode": "USD",
  "timeZone": "EST5EDT",
  "rating": 4.99,
  "reviewCount": 1039,
  "ratingsBySource": [
    { "source": "Resy", "score": 4.99, "scale": 5, "count": 1039 }
  ],
  "collections": ["Best of Brunch", "New on Resy", "Top Rated"],
  "globalDiningAccess": false,
  "photoUrl": "https://image.resy.com/3/003/2/94731/…/jpg/16:9/800",
  "imageUrls": ["https://image.resy.com/3/003/2/94731/…/jpg/16:9/800"],
  "googlePlaceId": "ChIJA2fUPjtZwokRu7rKAvna6XE",
  "foursquareId": "4fccfed41081ba9a64ce9613",
  "marketCode": "ny",
  "marketLabel": "New York, NY, US",
  "searchKeyword": null,
  "searchIndex": 1,
  "sourceUrl": "https://resy.com/cities/new-york-ny/venues/caviar-cafe",
  "scrapedAt": "2026-09-22T12:00:00.000Z"
}
```

> **Note:** text fields such as `description`, `whyWeLikeIt`, `needToKnow` and `tagline` are returned **in the language the venue publishes for that market**. Venue names, ratings, review counts, prices, addresses, coordinates, list memberships and URLs are language-neutral.

#### Example run summary (`OUTPUT` key-value record)

```json
{
  "features": ["venue_discovery"],
  "markets": ["sushi | New York, NY"],
  "recordsByType": { "venue_discovery": 100, "market_catalog": 0, "venue_details": 0 },
  "totalRecords": 100,
  "errors": [],
  "spendingLimitReached": false,
  "paywall": {
    "detected": true,
    "isPaying": true,
    "pricingTier": "SILVER",
    "limited": false,
    "blocked": false,
    "freeTierMaxItems": null,
    "freeTierMaxUsersPerAccount": null
  },
  "enrichment": {
    "enabled": true,
    "attempted": 100,
    "enriched": 91,
    "notFound": 8,
    "failed": 1,
    "skippedNoLocation": 0,
    "withWebsite": 88,
    "withPhone": 86,
    "withEmail": 54,
    "withSocials": 63
  }
}
```

***

### Webhook delivery (optional)

Every record is **always saved to the Apify dataset** first. If you set `webhookUrl` in the **Output & limits** section, each new record is **also POSTed in real time** to your destination — useful for CRMs, Slack, Zapier, Make or custom pipelines.

| Setting | Description |
|---------|-------------|
| `webhookUrl` | Your destination URL (http/https). Leave empty to use the dataset only. |
| `webhookFormat` | `json` — full record object. `slack` — compact Slack incoming-webhook message. |

Webhook delivery is **best-effort**: a failed webhook never stops the run or prevents dataset writes.

**Example — Slack alerts while collecting**

```json
{
  "enableSearch": true,
  "searchTasks": [{ "location": "New York, NY", "maxItems": 10 }],
  "webhookUrl": "https://hooks.slack.com/services/YOUR/WEBHOOK/URL",
  "webhookFormat": "slack"
}
```

**Example — push straight into your CRM**

```json
{
  "enableSearch": true,
  "searchTasks": [{ "keyword": "italian", "location": "Chicago, IL", "maxItems": 100 }],
  "webhookUrl": "https://your-crm.example.com/api/venues",
  "webhookFormat": "json"
}
```

***

### Quick start examples

**Multi-market discovery (the default pattern)**

```json
{
  "enableSearch": true,
  "searchTasks": [
    { "location": "New York, NY", "maxItems": 100 },
    { "location": "Los Angeles, CA", "maxItems": 100 }
  ]
}
```

**Cuisine-specific prospecting**

```json
{
  "enableSearch": true,
  "searchTasks": [
    { "keyword": "steakhouse", "location": "Miami, FL", "maxItems": 60 },
    { "keyword": "steakhouse", "location": "Dallas, TX", "maxItems": 60 }
  ]
}
```

**Curated list intelligence — every “Date Night” venue in a market**

```json
{
  "enableSearch": true,
  "searchTasks": [{ "keyword": "Date Night", "location": "New York, NY", "maxItems": 200 }]
}
```

**National scan — every venue in Texas**

```json
{
  "enableSearch": false,
  "enableCatalogScan": true,
  "catalogRegions": ["TX"],
  "maxItems": 5000
}
```

**Multi-country keyword scan**

```json
{
  "enableSearch": false,
  "enableCatalogScan": true,
  "catalogCountries": ["US", "CA"],
  "catalogKeyword": "sushi",
  "maxItems": 5000
}
```

**Enrich a URL / ID list**

```json
{
  "enableSearch": false,
  "enableVenueDetails": true,
  "venueUrls": ["https://resy.com/cities/new-york-ny/venues/caviar-cafe"],
  "venueIds": ["94731"]
}
```

**One market at scale, mapped**

```json
{
  "enableSearch": true,
  "searchTasks": [{ "location": "Austin, TX", "maxItems": 300 }]
}
```

Every row carries `priceTierId`, `latitude` and `longitude`, so price-band and mapping views are one client-side filter away.

**Outreach-ready lead list with phone and email**

```json
{
  "enableSearch": true,
  "searchTasks": [{ "location": "New York, NY", "maxItems": 300 }],
  "enableContactEnrichment": true
}
```

**Web & marketing agencies: find venues to pitch**

```json
{
  "enableCatalogScan": true,
  "catalogCities": ["Brooklyn"],
  "enableContactEnrichment": true,
  "maxItems": 500
}
```

Use the **Contacts** and **Lead list** views to work the list by `website`, `phone` and `emailIsGeneric`. Check `instagram` / `facebook`: an active social profile with no website is a strong web-agency lead. Rows with `enrichmentStatus: "not_found"` still carry the full venue record — they are simply venues with no findable web presence.

**Contactable venues across a whole country**

```json
{
  "enableCatalogScan": true,
  "catalogCountries": ["GB"],
  "enableContactEnrichment": true,
  "maxItems": 5000
}
```

***

### LLM & MCP integration

Output is **JSON Lines–friendly structured data** — ideal for ChatGPT, Claude, Gemini, LangChain, LlamaIndex and custom agents.

#### Recommended workflow

1. Run the Actor with the features you need.
2. Pull dataset items via the [Apify API](https://docs.apify.com/api/v2) or export JSON/CSV.
3. Pass records to your LLM with a system prompt, or index them into a vector store.

#### Apify MCP (Model Context Protocol)

Use the [Apify MCP server](https://docs.apify.com/platform/integrations/mcp) so AI assistants can:

- **Run** this Actor with natural-language instructions
- **Read** dataset results directly in the chat
- **Chain** it with other Actors (collect → score → enrich → CRM)

```
User: "Find Italian restaurants in Chicago with full addresses and summarise each for outreach"
→ MCP runs the Actor with searchTasks=[{ keyword: "italian", location: "Chicago, IL" }]
→ MCP reads dataset items
→ LLM summarises and drafts emails
```

```
User: "Map every restaurant in Austin and group them by neighbourhood and price tier"
→ MCP runs the Actor with searchTasks=[{ location: "Austin, TX", maxItems: 500 }]
→ MCP reads dataset items
→ LLM builds the neighbourhood / price breakdown
```

```
User: "Which venues in New York are on the Date Night list?"
→ MCP runs the Actor with searchTasks=[{ keyword: "Date Night", location: "New York, NY" }]
→ MCP reads dataset items
→ LLM ranks and explains them
```

#### API quick start

```bash
curl -X POST "https://api.apify.com/v2/acts/YOUR_ACTOR_ID/runs?token=YOUR_TOKEN" \
  -H "Content-Type: application/json" \
  -d '{
    "enableSearch": true,
    "searchTasks": [
      { "location": "New York, NY", "maxItems": 50 },
      { "keyword": "italian", "location": "Chicago, IL", "maxItems": 50 }
    ],
    "enableContactEnrichment": true
  }'
```

Dataset items: `GET https://api.apify.com/v2/datasets/{datasetId}/items?format=json`

***

### Proxy & performance

- **Apify residential proxy is enabled by default** — no extra setup required on Apify. Switch the proxy country in the input for markets outside the United States.
- Default memory: **1024 MB**. The Actor also runs comfortably at **512 MB**.
- Results are **streamed to the dataset as they are collected**, so long runs never pile up data in memory.
- **Contact Enrichment adds a little extra time per venue.** It resolves each venue's own website and phone number, then reads that website for emails and socials. It is off by default, and it runs in batches so results keep streaming while it works — memory stays flat even with it on.
- Discovery and catalog scans both **deduplicate venues automatically** within a feature, so you never pay twice for the same venue.
- A single run can mix features: discovery for one market, a catalog scan for another region, and profile lookups for a URL list — all streamed into one dataset.

***

### Plan limits & transparency

This Actor is transparent about plan restrictions, as Apify policy requires:

| Plan | Behaviour |
|------|-----------|
| **Paid Apify plan** | Full, uncapped output. All features, all limits you configure. |
| **Free Apify plan** | Restricted: a **2-result sample** per run, then the run finishes with a clear upgrade message. |
| **Local development** (`apify run`, direct Node) | Not restricted. |

Every run reports this in the run summary under `paywall` (`detected`, `isPaying`, `pricingTier`, `limited`, `blocked`), so you always know exactly what happened. Restricted runs **exit cleanly with a status message** — never with a system error.

***

### FAQ

**How many venues can I get in one run?**
There is no hard limit — set `maxItems` high (e.g. 5,000+) and add as many keyword + market rows as you need.

**Can I run many markets in one job?**
Yes. Each `searchTasks` row is an independent market, and they all run in the same job.

**Can I collect an entire state or country?**
Yes — use **Full Catalog Scan** with `catalogRegions` or `catalogCountries`. Add `catalogKeyword` to narrow by cuisine or concept.

**What is the difference between Venue Discovery and Full Catalog Scan?**
Discovery is market-first and keyword-optional: give it a city and get that city's venues. The catalog scan is scope-first: filter the whole catalog by country, region, city and keyword. Both produce identical rows and can run together.

**Do I get street addresses?**
Yes. Most venues include `addressLine1`, neighbourhood, city, state/region, postal code, country and coordinates.

**Do I get phone numbers or emails?**
Yes — with **Contact Enrichment** switched on. Venue listings publish no phone number, email address or website of their own, so the Actor resolves each venue's own website and phone number separately, then reads that website for email addresses and social profiles. Because that is a genuinely harder problem than reading a listing, expect a **high but not perfect hit rate** and check `enrichmentStatus` on each row:

- `enriched` — website and/or phone attached (`withEmail` counts are in the run summary)
- `partial` — matched, but that venue publishes no website or phone
- `not_found` — no confident match was made, so nothing was attached

The Actor **never guesses**. It attaches details only when the venue is confidently identified by both name *and* proximity — a wrong phone number or email is worse than a blank one. `enrichmentMatchConfidence` and `enrichmentDistanceMeters` let you set your own bar, and `googlePlaceId` / `foursquareId` remain strong join keys for any other source you trust.

**Why is `enrichmentStatus` sometimes `not_found`?**
Usually because the venue is small or recently opened and has no findable web presence, or its name is a single common word ("Essex", "Provence") that cannot be told apart from nearby businesses by name alone. Rather than attach a stranger's phone number, the Actor reports `not_found` and leaves the record untouched. Narrow, distinctive venue names resolve best.

**Does Contact Enrichment work for any market?**
Yes — it is country-agnostic, so the same toggle works for New York, London, Toronto or Lisbon. Coverage is naturally higher for venues with an established web presence.

**Does Contact Enrichment slow the run down?**
It adds a little extra time per venue, because each one's website and contact details have to be resolved and read. It is off by default for that reason — leave it off for pure market data and turn it on when you need outreach-ready contacts. It never slows down a run to the point of failing it.

**What are `collections`?**
Resy's editorial and curated list memberships for each venue — for example *Top Rated*, *Date Night*, *Good for Groups*, *Al Fresco Dining*, *Best of Brunch* or *Climbing*. They are an excellent quality and segmentation signal.

**Can I filter to high-quality venues only?**
Yes — every row carries `rating`, `reviewCount`, `priceTierId`, `neighbourhood`, `formattedAddress` and coordinates, so a one-line filter in your spreadsheet, script or CRM keeps exactly the venues you consider high quality. This keeps runs fast and predictable: the Actor collects every venue for your markets and you slice the results however you like afterwards.

**Can I enrich a list I already have?**
Yes. Use **Venue Details** with your Resy venue URLs (fastest) or numeric venue IDs.

**Can I get results in my own systems in real time?**
Yes. Set a **Webhook URL** and choose JSON or Slack formatting.

**Which format is the output?**
One flat JSON object per venue, plus CSV, Excel and RSS export options.

**Are there fields that may be empty?**
Yes. Availability depends on what each venue publishes — for example, not every venue has a tagline or a second address line. Empty fields are returned as `null` or `[]`, never guessed.

**Why does resolving by venue ID take a little longer?**
Venue IDs have to be located in the catalog first, so the Actor adds a little extra time per ID. Using venue URLs instead removes that step entirely.

**Is the run safe to stop?**
Yes. Records are saved as they are collected, so whatever has already been written stays in your dataset.

***

### Limitations & compliance

- Field availability depends on what each venue publishes.
- Some text fields are returned in the language the venue publishes for that market.
- Resy does not publish venue phone numbers or email addresses; this Actor does not invent them.
- Venue IDs add a little extra time per lookup compared with URLs.
- Not affiliated with Resy. Use responsibly and comply with applicable laws and Resy's Terms of Service.
- Always respect rate limits and local regulations when collecting business data.

***

### Contact & custom work

Need something beyond this Actor? I build **custom data products**, **pipelines**, and **full-stack web applications** for startups and enterprises.

- **Email:** <dubem115@gmail.com>
- **GitHub:** [github.com/DrunkCodes](https://github.com/DrunkCodes)

Reach out for:

- Custom Apify Actors (any website or data source)
- Restaurant / hospitality / local-market data projects at scale
- LLM & MCP integrations with your data stack
- Web apps, dashboards and automation tools

***

*Resy Real-Time Data · by [DrunkCodes](https://github.com/DrunkCodes)*

# Actor input Schema

## `enableSearch` (type: `boolean`):

Discover restaurants by keyword and market. Enabled by default.

## `searchTasks` (type: `array`):

One row per market, plus an optional keyword. Leave the keyword empty to collect every venue in the market.

## `maxPagesPerTask` (type: `integer`):

Safety ceiling on how deep each market is collected for very large runs. Raise it for the biggest markets. NOTE: on the Apify free plan this Actor returns only a small free sample (2 results) — upgrade to a paid Apify plan for full, unlimited output.

## `enableCatalogScan` (type: `boolean`):

Scan the complete venue catalog and keep only the venues matching your scope filters. Ideal for national or multi-country projects.

## `catalogCountries` (type: `array`):

Keep only venues in these countries. Accepts ISO codes ("US", "CA", "GB") or country names. Leave empty for all countries.

## `catalogRegions` (type: `array`):

Keep only venues in these states, provinces or regions (e.g. "TX", "Ontario", "NY"). Leave empty for all regions.

## `catalogCities` (type: `array`):

Keep only venues in these cities or neighbourhoods (e.g. "Austin", "Brooklyn"). Leave empty for all cities.

## `catalogKeyword` (type: `string`):

Optional keyword applied to the whole catalog scan. Matches the venue name, cuisine, neighbourhood, city and curated list memberships.

## `enableVenueDetails` (type: `boolean`):

Get a complete structured profile for specific Resy venues you already know about.

## `venueUrls` (type: `array`):

Resy venue URLs (e.g. https://resy.com/cities/new-york-ny/venues/caviar-cafe) or Resy deep links. These resolve quickly and precisely.

## `venueIds` (type: `array`):

Numeric Resy venue IDs. These are resolved from the catalog, so allowing a little extra time per ID is expected.

## `enableContactEnrichment` (type: `boolean`):

Also resolve each venue's own website, phone number, email addresses and social profiles. Off by default — it adds a little extra time per venue. NOTE: on the Apify free plan this Actor returns only a small free sample (2 results) — upgrade to a paid Apify plan for full, unlimited output.

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

Global cap on dataset rows for this run across all features. Set it high for large runs. NOTE: on the Apify free plan this Actor returns a small free sample (2 results) — upgrade to a paid Apify plan for full, unlimited output.

## `webhookUrl` (type: `string`):

Optional. Every record is always saved to the run's dataset — this webhook is an ADDITIONAL real-time push. When set, each new record is also POSTed to this URL (CRM, Slack incoming webhook, Zapier, Make, Google Sheets). Full output requires a paid Apify plan.

## `webhookFormat` (type: `string`):

json = full record object; slack = Slack-friendly message payload.

## `proxyConfiguration` (type: `object`):

Apify residential proxy is enabled by default for reliable Resy collection. No setup needed.

## Actor input object example

```json
{
  "enableSearch": true,
  "searchTasks": [
    {
      "keyword": "sushi",
      "location": "New York, NY",
      "maxItems": 10
    },
    {
      "keyword": "italian",
      "location": "Chicago, IL",
      "maxItems": 10
    }
  ],
  "maxPagesPerTask": 30,
  "enableCatalogScan": false,
  "catalogCountries": [],
  "catalogRegions": [],
  "catalogCities": [],
  "catalogKeyword": "",
  "enableVenueDetails": false,
  "venueUrls": [],
  "venueIds": [],
  "enableContactEnrichment": false,
  "maxItems": 1000,
  "webhookUrl": "",
  "webhookFormat": "json",
  "proxyConfiguration": {
    "useApifyProxy": true,
    "apifyProxyGroups": [
      "RESIDENTIAL"
    ],
    "apifyProxyCountry": "US"
  }
}
```

# Actor output Schema

## `allResults` (type: `string`):

Complete dataset with every venue from all enabled features in this run.

## `discovery` (type: `string`):

Venues collected from keyword + market tasks.

## `catalog` (type: `string`):

Venues kept from the full catalog scan after your scope filters.

## `locations` (type: `string`):

Venues with a full street address and coordinates.

## `details` (type: `string`):

Full profiles from venue URL and venue ID lookups.

## `contacts` (type: `string`):

Venues resolved with a website, phone number or email address (Contact enrichment).

## `leads` (type: `string`):

Contactable venues with a full address and a phone or email — the tightest outreach view.

## `runSummary` (type: `string`):

Per-run metadata: record counts by feature, markets, errors, contact-enrichment stats, spending-limit status and plan information.

# 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 = {
    "enableSearch": true,
    "searchTasks": [
        {
            "keyword": "sushi",
            "location": "New York, NY",
            "maxItems": 10
        },
        {
            "keyword": "italian",
            "location": "Chicago, IL",
            "maxItems": 10
        }
    ],
    "maxPagesPerTask": 30,
    "maxItems": 1000
};

// Run the Actor and wait for it to finish
const run = await client.actor("b2b_leads/resy-real-time-data").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 = {
    "enableSearch": True,
    "searchTasks": [
        {
            "keyword": "sushi",
            "location": "New York, NY",
            "maxItems": 10,
        },
        {
            "keyword": "italian",
            "location": "Chicago, IL",
            "maxItems": 10,
        },
    ],
    "maxPagesPerTask": 30,
    "maxItems": 1000,
}

# Run the Actor and wait for it to finish
run = client.actor("b2b_leads/resy-real-time-data").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 '{
  "enableSearch": true,
  "searchTasks": [
    {
      "keyword": "sushi",
      "location": "New York, NY",
      "maxItems": 10
    },
    {
      "keyword": "italian",
      "location": "Chicago, IL",
      "maxItems": 10
    }
  ],
  "maxPagesPerTask": 30,
  "maxItems": 1000
}' |
apify call b2b_leads/resy-real-time-data --silent --output-dataset

```

## MCP server setup

```json
{
    "mcpServers": {
        "apify": {
            "type": "http",
            "url": "https://mcp.apify.com/?tools=fetch-actor-details,b2b_leads/resy-real-time-data"
        }
    }
}
```

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/TAIcr6AUbePUhbOIS/builds/x3YJEb8h1FgU35RTw/openapi.json
