# TheFork Europe Restaurant Directory & Review Scraper (`jungle_synthesizer/thefork-europe-restaurant-directory-review-scraper`) Actor

Extract restaurant listings and diner reviews from TheFork across European markets. Get venue details (address, cuisine, price band, Michelin distinctions, opening hours, menu, promotions) and full review history (ratings, text, dates, replies), joined by restaurant ID.

- **URL**: https://apify.com/jungle\_synthesizer/thefork-europe-restaurant-directory-review-scraper.md
- **Developed by:** [BowTiedRaccoon](https://apify.com/jungle_synthesizer) (community)
- **Categories:** Lead generation
- **Stats:** 2 total users, 1 monthly users, 100.0% runs succeeded, 0 bookmarks
- **User rating**: No ratings yet

## Pricing

from $1.60 / 1,000 record scrapeds

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

## TheFork Restaurant Directory & Review Scraper

Scrape restaurant listings and diner reviews from [TheFork](https://www.thefork.com), the dominant reservation platform in France, Spain and Italy. Returns venue details — address, cuisine, price band, Michelin distinctions, opening hours, menu items, active promotions — and full review history, joined by restaurant ID in one dataset.

***

### TheFork Scraper Features

- Covers restaurants across TheFork's European markets — France, Spain, Italy, the UK, Germany, and more, no city or country filter required.
- Returns 28 fields per record, split across two row types: restaurant venue rows and diner review rows.
- Joins reviews to their restaurant via `restaurant_id`, so a distributor prospecting a city gets the venue list and its review volume in one run, not two datasets to reconcile.
- Extracts active promotions (`promo_offer`) and live booking availability (`booking_slots_available`) — the signals that tell you which venue is trying to fill covers.
- Pulls Michelin distinctions, average price band, full opening hours by day, and the venue's menu with item-level pricing.
- Reviews carry rating, text, visit date, reviewer alias, and the restaurant's own reply when it left one.

***

### Who Uses TheFork Restaurant Data?

- **POS and restaurant-tech vendors** — build a prospect list of venues by cuisine, price band, and city, then prioritize outreach using promotion activity as a buying signal.
- **Food-service distributors** — map accounts across a market and cross-reference review volume against your existing customer list.
- **Reputation-management agencies** — pull a venue's full review history to pitch a response strategy, backed by actual numbers instead of a screenshot.
- **Market researchers** — track price bands, cuisine mix, and Michelin distribution across a city or country over time.
- **Beverage and hospitality brands** — identify venues by cuisine and price tier for account mapping, or just to see who's discounting and why.

***

### How TheFork Scraper Works

1. Set `maxItems` — the maximum number of records (restaurant + review rows combined) you want back. Leave everything else alone; the scraper covers TheFork's full European catalog by default.
2. The scraper walks TheFork's restaurant catalog and visits each venue's page, pulling address, cuisine, pricing, hours, menu, and Michelin status.
3. For every restaurant, it also pages through that venue's diner reviews — rating, text, visit date, and any management reply — up to 400 reviews per venue.
4. Records land in your dataset as they're found. Stop the run early and you keep everything collected so far.

***

### Input

```json
{
  "maxItems": 500
}
```

| Field      | Type    | Default | Description |
|------------|---------|---------|-------------|
| `maxItems` | integer | 10      | Maximum number of records to save (restaurant + review rows combined). Restaurants are discovered from the full TheFork European catalog, so a small value still spans many cities and countries. Set to `0` for no cap. |

***

### TheFork Scraper Output Fields

#### Restaurant rows

```json
{
  "restaurant_id": "717120",
  "name": "Mâche",
  "cuisine_types": ["French"],
  "street": "61 Rue de Chabrol",
  "postal_code": "75010",
  "city": "Paris",
  "city_id": "415144",
  "country": "France",
  "latitude": 48.8769636,
  "longitude": 2.3509406,
  "price_band": "80.00 EUR",
  "michelin_distinction": "MICHELIN",
  "rating_avg": 9.6,
  "rating_count": 655,
  "opening_hours": {
    "mon": [],
    "tue": [{ "opens": "19:00", "closes": "21:00" }]
  },
  "booking_slots_available": true,
  "promo_offer": "-20%",
  "menu_items": [
    { "name": "Menu memphis - 4 temps", "description": null, "price": 80, "currency": "EUR" }
  ],
  "photos": ["https://cdn.thefork.com/tf-lab/image/upload/restaurant/.../photo.jpg"],
  "restaurant_url": "https://www.thefork.com/restaurant/mache-r717120"
}
```

| Field                      | Type    | Description |
|-----------------------------|---------|-------------|
| `restaurant_id`             | string  | TheFork's numeric venue ID — the `r<id>` in the restaurant URL, and the join key to review rows. |
| `name`                      | string  | Restaurant name. |
| `cuisine_types`              | array   | Cuisine types the venue serves. |
| `street`                    | string  | Street address. |
| `postal_code`                | string  | Postal code. |
| `city`                      | string  | City name. |
| `city_id`                   | string  | TheFork's numeric city ID. |
| `country`                   | string  | Country name. |
| `latitude` / `longitude`    | number  | Venue coordinates. |
| `price_band`                | string  | Average price, formatted with currency (e.g. `"80.00 EUR"`). |
| `michelin_distinction`      | string  | `"MICHELIN"` when the venue carries a Michelin distinction, otherwise absent. |
| `rating_avg`                | number  | Average diner rating (0-10 scale). |
| `rating_count`               | integer | Total number of ratings behind `rating_avg`. |
| `opening_hours`             | object  | Opening intervals by day (`mon`-`sun`), each an array of `{opens, closes}` in 24-hour time. |
| `booking_slots_available`   | boolean | Whether the venue currently shows live booking availability. |
| `promo_offer`               | string  | Active discount, e.g. `"-20%"`, when the venue is running one. |
| `menu_items`                 | array   | Menu items with `name`, `description`, `price`, and `currency`. |
| `photos`                    | array   | Venue photo URLs. |
| `restaurant_url`             | string  | Canonical TheFork URL for the venue. |

#### Review rows

```json
{
  "review_id": "0c217ddf-57de-40f6-87f2-ac1dbcc79f79",
  "review_restaurant_id": "717120",
  "review_rating": 10,
  "review_text": "Excellent",
  "review_date": "2026-08-15T18:30:00.000Z",
  "review_author_alias": "Flavien D.",
  "review_management_reply": "Thank you so much for your nice review"
}
```

| Field                       | Type    | Description |
|-------------------------------|---------|-------------|
| `review_id`                   | string  | TheFork's review ID. |
| `review_restaurant_id`        | string  | Matches `restaurant_id` on the venue row — the join key. |
| `review_rating`               | number  | Diner's rating for this visit (0-10 scale). |
| `review_text`                 | string  | Review text. |
| `review_date`                 | string  | Visit date (ISO 8601). |
| `review_author_alias`         | string  | Reviewer's display name as shown on TheFork. |
| `review_management_reply`     | string  | The restaurant's reply to the review, when it left one. |

Every record also carries a `scraped_at` timestamp.

***

### FAQ

#### How do I scrape TheFork restaurant data?

Set `maxItems` and run. TheFork Scraper pulls venue details and review history from TheFork's full European catalog — no city, country, or search term required to get started.

#### What data can I get from TheFork?

Restaurant details (address, cuisine, price band, Michelin status, hours, menu) and diner reviews (rating, text, date, reviewer alias, management replies), joined by restaurant ID. Both row types land in the same dataset.

#### Does this cover restaurants outside France?

Yes. TheFork operates across France, Spain, Italy, the UK, Germany, Switzerland, Belgium, the Netherlands, Portugal, and Sweden, and this scraper walks the full catalog by default — it isn't scoped to one country.

#### Can I limit how many reviews come back per restaurant?

Not per-restaurant, but the scraper caps review pagination at 400 per venue on its own, so one heavily-reviewed restaurant can't crowd out the rest of a run. Set `maxItems` to control the total record count across the run.

#### Do I need an account or API key for TheFork?

No. TheFork Scraper works from restaurant and review pages that are publicly visible — no login required.

***

### Need More Features?

Need a different field, a filtered subset, or another region prioritized? [File an issue](https://console.apify.com/actors/issues) or get in touch.

### Why Use TheFork Scraper?

- **One dataset, not two** — venue details and review history joined by `restaurant_id`, so you're not reconciling a separate restaurants export against a separate reviews export.
- **Full catalog by default** — most alternatives scope you to one city or search term; this one walks TheFork's European catalog out of the box, and a small `maxItems` still spans many cities.
- **Demand signals included** — `promo_offer` and `booking_slots_available` tell you which venues are actively discounting or showing open tables, not just their static listing details.

# Actor input Schema

## `sp_intended_usage` (type: `string`):

What will this data feed? E.g. lead lists, KYB checks, price tracking.

## `sp_improvement_suggestions` (type: `string`):

Provide any feedback or suggestions for improvements.

## `sp_contact` (type: `string`):

We'll personally help with your use case. No spam.

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

Maximum number of records to save (restaurant + review rows combined). Restaurants are discovered from the full TheFork European catalog, so a small value still spans many cities and countries.

## Actor input object example

```json
{
  "sp_intended_usage": "Describe your intended use...",
  "sp_improvement_suggestions": "Share your suggestions here...",
  "sp_contact": "Share your email here...",
  "maxItems": 10
}
```

# Actor output Schema

## `results` (type: `string`):

No description

# 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 = {
    "sp_intended_usage": "Describe your intended use...",
    "sp_improvement_suggestions": "Share your suggestions here...",
    "sp_contact": "Share your email here...",
    "maxItems": 10
};

// Run the Actor and wait for it to finish
const run = await client.actor("jungle_synthesizer/thefork-europe-restaurant-directory-review-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 = {
    "sp_intended_usage": "Describe your intended use...",
    "sp_improvement_suggestions": "Share your suggestions here...",
    "sp_contact": "Share your email here...",
    "maxItems": 10,
}

# Run the Actor and wait for it to finish
run = client.actor("jungle_synthesizer/thefork-europe-restaurant-directory-review-scraper").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 '{
  "sp_intended_usage": "Describe your intended use...",
  "sp_improvement_suggestions": "Share your suggestions here...",
  "sp_contact": "Share your email here...",
  "maxItems": 10
}' |
apify call jungle_synthesizer/thefork-europe-restaurant-directory-review-scraper --silent --output-dataset

```

## MCP server setup

```json
{
    "mcpServers": {
        "apify": {
            "type": "http",
            "url": "https://mcp.apify.com/?tools=fetch-actor-details,jungle_synthesizer/thefork-europe-restaurant-directory-review-scraper"
        }
    }
}

```

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/d83w2r1slqcN2wxCq/builds/6XGdopBT8gx88ryyD/openapi.json
