# TheFork Scraper - Restaurants, Reviews & Menus (`clearpath/thefork-scraper`) Actor

Extract restaurant data, reviews, menus with prices, and photos from TheFork. Get ratings, Michelin stars, TripAdvisor scores, contact details, booking availability, and 100+ fields. Supports 5 languages. Export as JSON, CSV, Excel.

- **URL**: https://apify.com/clearpath/thefork-scraper.md
- **Developed by:** [ClearPath](https://apify.com/clearpath) (community)
- **Categories:** Lead generation, Travel, Automation
- **Stats:** 112 total users, 20 monthly users, 83.9% runs succeeded, 1 bookmarks
- **User rating**: 5.00 out of 5 stars

## Pricing

from $3.99 / 1,000 restaurants

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/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

## TheFork Scraper | Restaurant Data, Reviews, Menus & Photos (2026)

<table><tr>
<th style="border-bottom:2px solid #333;padding:12px 16px;text-align:left;font-weight:600">Restaurant Scrapers ➤</th>
<td style="border-bottom:1px solid #ddd;padding:12px 16px"><b>TheFork Scraper</b></td>
<td style="border-bottom:1px solid #ddd;padding:12px 16px"><a href="https://apify.com/clearpath/thefork-restaurant-reviews" style="color:#006D77;text-decoration:none;font-weight:600">TheFork Reviews</a></td>
<td style="border-bottom:1px solid #ddd;padding:12px 16px"><a href="https://apify.com/clearpath/resy-api" style="color:#006D77;text-decoration:none;font-weight:600">Resy Scraper</a></td>
</tr></table>
&nbsp;

[![Demo](https://asciinema.org/a/WtQLQiwEZeCCs0th.svg)](https://asciinema.org/a/WtQLQiwEZeCCs0th)

**Extract complete restaurant data from TheFork** across France, Germany, Italy, Spain, and the UK. Phone numbers, emails, addresses, full menus with dish prices, all reviews, photos, Michelin stars, TripAdvisor ratings, and booking availability. 100+ fields per restaurant.

[![thefork-restaurant-scraper-demo.png](https://i.postimg.cc/pdRh4cm5/thefork-restaurant-scraper-demo.png)](https://postimg.cc/QFYdWbkj)

#### Copy to your AI assistant

Copy this block into ChatGPT, Claude, Cursor, or any LLM to start using this actor.

````

clearpath/thefork-scraper on Apify. Call: ApifyClient("TOKEN").actor("clearpath/thefork-scraper").call(run\_input={...}), then client.dataset(run\["defaultDatasetId"]).list\_items().items for results. Key inputs: startUrls (array), searchLocation (string), maxRestaurants (integer). Full actor spec (input schema with all params/enums/defaults, output dataset fields, README): GET https://api.apify.com/v2/acts/clearpath~thefork-scraper/builds/default (Bearer TOKEN) → inputSchema, actorDefinition.storages.dataset, readme. Pricing: PPE $5.99/1k restaurants, $3.99/1k reviews (beyond 100 included per restaurant). Get token: https://console.apify.com/account/integrations

````

### Quick Start

#### Basic — Scrape restaurants in a city
```json
{
    "searchLocation": "Paris"
}
````

#### URL input — Scrape specific pages

```json
{
    "startUrls": [
        "https://www.thefork.com/restaurant/l-imperatif-r660609",
        "https://www.thefork.com/restaurants/paris-c415144"
    ]
}
```

#### Advanced — Filtered search with limits

```json
{
    "searchLocation": "Barcelona",
    "language": "es",
    "cuisineTagIds": ["436", "452"],
    "minRating": 8,
    "maxPrice": 40,
    "promotionsOnly": true,
    "sort": "avgRate",
    "maxRestaurants": 200,
    "maxReviews": 500,
    "maxPhotos": 50
}
```

### Input Parameters

| Parameter | Type | Description | Default |
|-----------|------|-------------|---------|
| `startUrls` | array | TheFork URLs to scrape. Supports restaurant, city, and search pages. | — |
| `searchLocation` | string | City, neighborhood, or address to search. Typos and non-English names work. | — |
| `searchRadiusKm` | integer | Radius (km) around `searchLocation`. Only applies when the location is a small town/village without a TheFork city profile (large cities use their own polygon). | `10` |
| `language` | string | Output language and TheFork domain. Options: `en`, `fr`, `de`, `it`, `es`. | `en` |
| `reviewLanguage` | string | Filter reviews by language. `all` returns default domain language. Options: `all`, `en`, `fr`, `de`, `it`, `es`, `nl`, `pt`. | `all` |
| `sort` | string | Sort order for location searches. Options: `popularity`, `avgRate`, `quality`, `promotion`, `newRestaurant`, `price`, `lastMonthAvg`, `lastMonthReservation`. | `popularity` |
| `bestRated` | boolean | Only return top-rated restaurants. | `false` |
| `promotionsOnly` | boolean | Only return restaurants with active promotions. | `false` |
| `minPrice` | integer | Minimum average price per person (EUR). | — |
| `maxPrice` | integer | Maximum average price per person (EUR). | — |
| `minRating` | number | Minimum TheFork rating (1-10). | — |
| `maxRating` | number | Maximum TheFork rating (1-10). | — |
| `cuisineTagIds` | array | Filter by cuisine type. 32 options including French, Italian, Japanese, Vegan, Seafood, etc. | all |
| `maxRestaurants` | integer | Max restaurants to scrape. Set `0` for unlimited. | `100` |
| `maxReviews` | integer | Reviews per restaurant, newest first. Set `0` to skip reviews entirely. For unlimited reviews from a single restaurant, use [TheFork Reviews](https://apify.com/clearpath/thefork-restaurant-reviews). | `100` |
| `maxPhotos` | integer | Customer photos per restaurant. Official photos always included. Set `0` to skip customer photos. | `20` |

### Output

Each restaurant includes 100+ fields organized into these categories:

#### Output Example

```json
{
    "id": "d878352e-a8c6-4483-9e99-f74a59b68078",
    "legacy_id": 35146,
    "slug": "l-atelier-de-joel-robuchon-etoile-champs-elysees",
    "url": "https://www.thefork.com/restaurant/l-atelier-de-joel-robuchon-etoile-champs-elysees-r35146",
    "name": "L'Atelier de Joel Robuchon Etoile - Champs Elysees",
    "cuisine": "French",
    "description": null,
    "chef_name": "Eric Bouchenoire",
    "phone": "+33147237575",
    "is_bookable": true,
    "is_new": false,
    "vacation": null,
    "has_available_offers": false,
    "main_photo_url": "https://cdn.thefork.com/tf-lab/image/upload/f_auto,q_auto,w_664,h_374/restaurant/d878352e-a8c6-4483-9e99-f74a59b68078/6e4e9b01-6174-4f6b-b379-d4afdbdaf15d.jpg",
    "food_requirements": ["Gluten free", "Locally produced", "Organic food", "Vegetarian dishes"],
    "payment_accepted": ["American Express", "Apple Pay", "Mastercard", "MobilePay", "Visa"],
    "rate_distinction": "Excellent",
    "avg_price": 97.0,
    "avg_price_currency": "EUR",
    "thefork_rating": 9,
    "thefork_review_count": 2463,
    "tripadvisor_rating": 4,
    "tripadvisor_review_count": 1658,
    "country": "France",
    "locality": "Paris",
    "street": "30 Rue Vernet",
    "zip_code": "75008",
    "formatted_address": "30 Rue Vernet, 75008, Paris",
    "latitude": 48.8723858,
    "longitude": 2.2970681,
    "parking": "Service voiturier",
    "transport": "Metro Charles de Gaulle- Etoile (M1, M9, RER A)",
    "michelin": {
        "stars": 1,
        "link": "https://guide.michelin.com/en/ile-de-france/paris/restaurant/l-atelier-de-joel-robuchon-etoile",
        "review": "With no less than two establishments in the French capital, Joel Robuchon's renowned Ateliers are literally making their way around the world..."
    },
    "michelin_distinctions": [
        {
            "value": "MICHELIN_1_star",
            "description": "One MICHELIN Star: High quality cooking, worth a stop!"
        }
    ],
    "michelin_review": "With no less than two establishments in the French capital...",
    "michelin_link": "https://guide.michelin.com/en/ile-de-france/paris/restaurant/l-atelier-de-joel-robuchon-etoile",
    "is_insider": true,
    "is_top_host": false,
    "top_chart_rank": null,
    "highlighted_review_rating": 10,
    "highlighted_review_content": "The food was delicious! And the mashed potatoes are a thing of beauty, you have to try. Service was exceptional and everyone was very nice and helpful with ordering.",
    "highlighted_review_reviewer_name": "Jim R.",
    "yums_is_super": false,
    "yums_count": 100,
    "has_reservations_today": 2,
    "customer_photos_total": 687,
    "food_photos_total": 582,
    "header_photos": [
        {
            "id": "6e4e9b01-6174-4f6b-b379-d4afdbdaf15d",
            "resizedImageUrls": {
                "url664x374": "https://cdn.thefork.com/tf-lab/image/upload/f_auto,q_auto,w_664,h_374,c_fill/restaurant/d878352e-.../6e4e9b01-....jpg",
                "url1080x": "https://cdn.thefork.com/tf-lab/image/upload/f_auto,q_auto,w_1080,c_fill/restaurant/d878352e-.../6e4e9b01-....jpg"
            }
        }
        // ... 8 more header photos
    ],
    "highlighted_tag": [
        { "text": "INSIDER", "highlightType": "INSIDER" },
        { "text": "MICHELIN", "highlightType": "MICHELIN_1_star" },
        { "text": "French", "highlightType": "DEFAULT" }
        // ... more tags
    ],
    "tags": [
        { "id": "2102", "name": "1 star MICHELIN" },
        { "id": "2311", "name": "INSIDER" },
        { "id": "434", "name": "French" },
        { "id": "81", "name": "Champs-Elysees" },
        { "id": "21", "name": "Arc de Triomphe" },
        { "id": "383", "name": "Fine Dining" },
        { "id": "1288", "name": "Sommelier" },
        { "id": "374", "name": "Valet parking" }
        // ... 30+ more tags
    ],
    "menus": [
        {
            "name": "A la carte",
            "menu_type": "A_LA_CARTE",
            "updated_ts": "2026-02-27T16:16:42.148Z",
            "sections": [
                {
                    "name": "Starter",
                    "items": [
                        {
                            "name": "LA LANGOUSTINE",
                            "description": "en papillote croustillante au basilic",
                            "price": 75.0,
                            "is_main_dish": false
                        },
                        {
                            "name": "LE CAVIAR IMPERIAL DE SOLOGNE",
                            "description": "les 50 grammes",
                            "price": 120.0,
                            "is_main_dish": false
                        }
                        // ... more starters
                    ]
                },
                {
                    "name": "Main course",
                    "items": [
                        {
                            "name": "LE HOMARD \"FRITE\"",
                            "description": "roti au beurre demi-sel ravigote d'une emulsion epicee aux aromates",
                            "price": 89.0,
                            "is_main_dish": true
                        },
                        {
                            "name": "LA CAILLE",
                            "description": "en duo de foie gras de canard caramelisee aux eclats de chataigne",
                            "price": 68.0,
                            "is_main_dish": true
                        }
                        // ... more main courses
                    ]
                },
                {
                    "name": "Dessert",
                    "items": [
                        {
                            "name": "LA FAMEUSE CREME CARAMEL DE JOEL ROBUCHON",
                            "description": null,
                            "price": 24.0,
                            "is_main_dish": false
                        }
                        // ... more desserts
                    ]
                }
                // ... more sections (cheese, drinks, etc.)
            ]
        },
        {
            "name": "Menu \"Signature\"",
            "menu_type": "MENU",
            "price": 220.0,
            "price_currency": "EUR",
            "description": "ENTREES + PLATS + DESSERTS"
        },
        {
            "name": "Menu a composer, seulement au dejeuner",
            "menu_type": "MENU",
            "price": 95.0,
            "price_currency": "EUR",
            "description": "ENTREES + PLATS + FROMAGE OU DESSERT + BOISSON CHAUDE"
        }
        // ... more menus (vegetarian menu, etc.)
    ],
    "bookable_intervals": [
        {
            "date": "2026-03-05",
            "isToday": true,
            "intervals": [
                { "start": 720, "end": 915 },
                { "start": 1140, "end": 1395 }
            ]
        }
        // ... 6 more days
    ],
    "feature_categories": [
        {
            "name": "Features",
            "category": "ESSENTIALS",
            "features": [
                { "name": "Air-conditioning" },
                { "name": "Wheelchair Accessible" },
                { "name": "Wifi" }
                // ... more features
            ]
        },
        {
            "name": "Languages spoken",
            "category": "SPOKEN_LANGUAGES",
            "features": [{ "name": "English spoken" }, { "name": "French spoken" }]
        },
        {
            "name": "Other services",
            "category": "OTHER",
            "features": [
                { "name": "Bar" },
                { "name": "Cellar" },
                { "name": "Sommelier" },
                { "name": "Valet parking" }
                // ... more services
            ]
        }
    ],
    "legal_website": "http://www.joel-robuchon.com/",
    "legal_email": "reservationetoile@atelierjr.fr",
    "exchange_rates": [
        {
            "yumsCost": 1000,
            "discountMoney": { "value": 2000, "currency": { "isoCurrency": "EUR" } }
        }
    ],
    "reviews": [
        {
            "id": "cb6c346e-2699-4405-b24d-521787524d63",
            "created_at": "2026-02-08T15:53:14.834Z",
            "rating_value": 6,
            "meal_date": "2026-02-07T12:00:00.000Z",
            "status": "PUBLISHED",
            "review_body": "We had lunch at L'Atelier de Joel Robuchon yesterday. The service was lacking...",
            "restaurant_reply_body": null,
            "reviewer_first_name": "Germanus",
            "reviewer_last_name": "P.",
            "reviewer_username": "Germanus P.",
            "reviewer_review_count": 1,
            "photos": [
                {
                    "title": "IMG_4171.jpeg",
                    "image_url": "https://cdn.thefork.com/tf-lab/image/upload/f_auto,q_auto,w_800,c_limit/customer/d878352e-.../0032a3ad-....jpg",
                    "preview_url": "https://cdn.thefork.com/tf-lab/image/upload/f_auto,q_auto,g_auto:subject,w_488,h_488,c_fill/customer/d878352e-.../0032a3ad-....jpg",
                    "created_ts": "2026-02-08T15:59:47.144Z",
                    "likes": 0
                }
                // ... more review photos
            ],
            "likes": 0
        }
        // ... up to 2,463 more reviews
    ]
}
```

### Pricing — Pay Per Event (PPE)

Two billable events:

1. **Restaurant scraped** — charged per restaurant extracted (includes the first 100 reviews)
2. **Review scraped** — charged per review beyond the 100 included with each restaurant

| Tier | Per 1,000 restaurants | Per 1,000 reviews (beyond 100) |
|------|----------------------|-------------------------------|
| Regular | $5.99 | $3.99 |
| Bronze | $5.33 | $3.49 |
| Silver | $4.66 | $2.99 |
| Gold | $3.99 | $2.49 |

#### Free Usage

Free plan includes **10 runs** with up to **50 restaurants per run** (and a sample of reviews per restaurant) — enough to evaluate the output before committing. [Upgrade your plan](https://console.apify.com/billing/subscription) for unlimited results.

### How to Scrape TheFork Restaurant Data

#### Using URLs

Paste any TheFork URL directly:

- **Restaurant page** — `https://www.thefork.com/restaurant/l-imperatif-r660609`
- **City page** — `https://www.thefork.com/restaurants/paris-c415144`
- **Search URL** — Copy a filtered search URL from TheFork, filters are preserved

Mix URL types freely. Each is processed independently.

#### Using Location Search

Enter any location name in `searchLocation`. Accepts cities, neighborhoods, addresses, landmarks. Typos and non-English names are handled automatically:

- `"Paris"`, `"Barclona"`, `"Milano"`, `"Montmartre"`, `"Champs-Elysees"`

Combine with filters (`cuisineTagIds`, `minPrice`, `maxPrice`, `minRating`, `bestRated`, `promotionsOnly`, `sort`) to narrow results.

**Small towns and villages.** Large cities have their own TheFork profile and return tightly-scoped results. Smaller places (no TheFork city profile) fall back to coordinate-based search and return restaurants from a wider area. Use `searchRadiusKm` to control this — defaults to `10` km, set tighter (e.g. `3`) for village-only results or wider (e.g. `50`) for the surrounding region. Ignored for large cities.

```json
{
    "searchLocation": "Saint-Tropez",
    "language": "fr",
    "searchRadiusKm": 5
}
```

#### Combining Both

Use `startUrls` and `searchLocation` together. URLs are processed first, then location search adds more results.

### API Integration

#### Python

```python
from apify_client import ApifyClient

client = ApifyClient("your_token")

run = client.actor("YOUR_ACTOR_ID").call(run_input={
    "searchLocation": "Paris",
    "language": "fr",
    "maxRestaurants": 50,
    "maxReviews": 200,
})

for restaurant in client.dataset(run["defaultDatasetId"]).iterate_items():
    print(f"{restaurant['name']} — {restaurant['thefork_rating']}/10 — {restaurant['avg_price']}€")
    for review in restaurant.get("reviews", []):
        print(f"  [{review['rating_value']}/10] {review['review_body'][:80]}")
```

#### JavaScript

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

const client = new ApifyClient({ token: 'your_token' });

const run = await client.actor('YOUR_ACTOR_ID').call({
    searchLocation: 'Rome',
    language: 'it',
    cuisineTagIds: ['436'],
    maxRestaurants: 100,
});

const { items } = await client.dataset(run.defaultDatasetId).listItems();
console.log(`Found ${items.length} Italian restaurants in Rome`);
```

### Advanced Usage

#### Scrape Italian restaurants in Barcelona with promotions

```json
{
    "searchLocation": "Barcelona",
    "language": "es",
    "cuisineTagIds": ["436"],
    "promotionsOnly": true,
    "sort": "promotion",
    "maxRestaurants": 200
}
```

#### Extract many reviews for specific restaurants

```json
{
    "startUrls": [
        "https://www.thefork.com/restaurant/l-imperatif-r660609"
    ],
    "maxReviews": 500,
    "reviewLanguage": "fr"
}
```

Need every review for one restaurant? Use [TheFork Reviews](https://apify.com/clearpath/thefork-restaurant-reviews) — it's purpose-built for unlimited single-restaurant review extraction.

#### Budget-friendly restaurants in Berlin

```json
{
    "searchLocation": "Berlin",
    "language": "de",
    "maxPrice": 25,
    "bestRated": true,
    "sort": "avgRate",
    "maxRestaurants": 100
}
```

#### Restaurant data only, no reviews

```json
{
    "searchLocation": "London",
    "maxReviews": 0,
    "maxRestaurants": 500
}
```

#### High-volume city export with minimal reviews

```json
{
    "searchLocation": "London",
    "maxRestaurants": 2000,
    "maxReviews": 10,
    "maxPhotos": 0
}
```

### Data Export

Results are available in multiple formats:

- **JSON** — Nested structures (menus, reviews, photos) fully preserved
- **CSV** — Flat fields, arrays serialized
- **Excel** — Spreadsheet-ready

### Automation

- **Scheduled runs** — Daily, weekly, or monthly data refreshes
- **Webhooks** — Get notified when a run completes
- **API** — Integrate into your data pipeline programmatically

### FAQ

**Q: What data does TheFork Scraper extract?**
A: Everything visible on a TheFork restaurant listing: name, contact info (phone, email), full menus with dish prices, all customer reviews, photos, ratings (TheFork + TripAdvisor), Michelin data, booking availability, promotions, tags, and more. Over 100 fields per restaurant.

**Q: How many restaurants can I scrape?**
A: No hard limit. Set `maxRestaurants` to control how many results come back from search/city pages. Direct restaurant URLs are always processed regardless of this limit.

**Q: How fast is it?**
A: Approximately 1,000 restaurants in under 60 seconds for basic data. Deep review extraction (hundreds of reviews per restaurant) adds only a few seconds.

**Q: Do I need a TheFork account?**
A: No. The scraper works without any login or authentication.

**Q: Which countries are supported?**
A: All countries where TheFork operates: France, Germany, Italy, Spain, UK, Belgium, Netherlands, Portugal, Switzerland, Austria, and others. Set the `language` parameter to match your target market.

**Q: Can I filter reviews by language?**
A: Yes. Use `reviewLanguage` to get reviews in English, French, German, Italian, Spanish, Dutch, or Portuguese. Default returns reviews matching your selected domain language.

**Q: How are reviews sorted?**
A: Reviews are returned newest first. Set `maxReviews` to control how many you get per restaurant. Set `0` to skip reviews entirely. For unlimited reviews from a single restaurant, use the dedicated [TheFork Reviews](https://apify.com/clearpath/thefork-restaurant-reviews) actor.

**Q: What about Michelin restaurants?**
A: Michelin data is included when available: star distinctions, Michelin review text, and a link to the Michelin Guide page.

**Q: Can I get full menu prices?**
A: Yes. The output includes complete a la carte menus and preset/fixed menus with every dish name, description, price, and section (starters, mains, desserts, wine list).

**Q: Is there a free trial?**
A: Yes. Free plan includes 10 runs with up to 50 restaurants per run (with a sample of reviews per restaurant). Enough to evaluate the data quality and format before upgrading.

**Q: How does the pricing work for reviews?**
A: The first 100 reviews per restaurant are included in the restaurant scrape cost. Reviews beyond 100 are charged separately. If you only need recent reviews, keep the default `maxReviews: 100` and pay nothing extra.

### Getting Started

#### 1. Try it free

1. [Sign up for Apify](https://console.apify.com/sign-up) — no credit card required
2. Open TheFork Scraper
3. Enter a city name or paste a TheFork URL
4. Click **Start** and inspect the results

#### 2. Configure

1. **Input** — Paste URLs or enter a search location
2. **Filters** — Set cuisine, price range, rating, promotions
3. **Limits** — Control restaurants, reviews, and photos per run
4. **Language** — Pick your target locale

#### 3. Scale

1. Use the API for programmatic access
2. Schedule recurring runs for fresh data
3. Set up webhooks for pipeline automation

### Legal Compliance

This scraper extracts publicly available data from TheFork listings. Users are responsible for complying with TheFork's terms of service and applicable data protection regulations (GDPR, CCPA). Use extracted data responsibly and in accordance with local laws.

**Contact data**: Phone numbers and email addresses are included when publicly listed. Comply with anti-spam regulations when using contact information.

### Support

- **Email**: max@mapa.slmail.me
- **Bugs**: Issues tab on the Actor page
- **Features**: Email or issues

***

[**Start Scraping TheFork Restaurants Now**](https://console.apify.com/actors/Jtb2nC8e8u4B0aXUv)

***

*Complete restaurant intelligence from Europe's largest dining platform.*

# Actor input Schema

## `startUrls` (type: `array`):

TheFork URLs to scrape. Supports restaurant pages, city pages, and search URLs with embedded filters. Mix types freely.

## `searchLocation` (type: `string`):

Alternative to URLs. City, neighborhood, or address. Typos and non-English names work fine (e.g. "Barclona", "Milano").<br><br>Ignored when URLs are provided above.

## `searchRadiusKm` (type: `integer`):

Geographic radius around <b>Search location</b>, in kilometers.<br><br>Only applies to small towns and villages where TheFork falls back to coordinate-based search (large cities use their own polygon and ignore this).<br><br>Default <code>10 km</code>. Increase (e.g. <code>50</code>) for wider coverage of rural areas, or decrease (e.g. <code>3</code>) for tighter scoping.

## `language` (type: `string`):

Controls the language of descriptions, cuisine names, tags, and reviews. Also determines the TheFork domain used.

## `reviewLanguage` (type: `string`):

Filter reviews by language. Pick <b>All languages</b> to keep every review regardless of language, or pick a specific language to filter.

## `sort` (type: `string`):

Sort order for search results. Only applies to location-based searches, not to URLs.

## `bestRated` (type: `boolean`):

Only return top-rated restaurants.

## `promotionsOnly` (type: `boolean`):

Only return restaurants with active promotions or deals.

## `minPrice` (type: `integer`):

Minimum average price per person in euros. Leave empty for no minimum.

## `maxPrice` (type: `integer`):

Maximum average price per person in euros. Leave empty for no maximum.

## `minRating` (type: `number`):

Minimum TheFork rating (1-10 scale). Leave empty for no minimum.

## `maxRating` (type: `number`):

Maximum TheFork rating (1-10 scale). Leave empty for no maximum.

## `cuisineTagIds` (type: `array`):

Filter by cuisine type. Select one or more. Leave empty for all cuisines.

## `maxRestaurants` (type: `integer`):

Maximum restaurants to scrape. Set to <code>0</code> for no limit. Applies to both search results and direct restaurant URLs.

## `maxReviews` (type: `integer`):

Reviews per restaurant, newest first. Set to <code>0</code> to skip reviews entirely.<br><br>For unlimited reviews from a single restaurant, use <a href="https://apify.com/clearpath/thefork-restaurant-reviews" target="_blank">TheFork Reviews</a> instead.

## `maxPhotos` (type: `integer`):

Customer photos per restaurant, paginated. Official restaurant photos (~19) are always included regardless of this setting. Set to <code>0</code> to skip customer photos entirely.

## Actor input object example

```json
{
  "startUrls": [
    "https://www.thefork.com/restaurants/paris-c415144"
  ],
  "searchRadiusKm": 10,
  "language": "en",
  "reviewLanguage": "all",
  "sort": "popularity",
  "bestRated": false,
  "promotionsOnly": false,
  "cuisineTagIds": [],
  "maxRestaurants": 20,
  "maxReviews": 20,
  "maxPhotos": 20
}
```

# 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 = {
    "startUrls": [
        "https://www.thefork.com/restaurants/paris-c415144"
    ],
    "searchRadiusKm": 10,
    "language": "en",
    "reviewLanguage": "all",
    "sort": "popularity",
    "maxRestaurants": 20,
    "maxReviews": 20,
    "maxPhotos": 20
};

// Run the Actor and wait for it to finish
const run = await client.actor("clearpath/thefork-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 = {
    "startUrls": ["https://www.thefork.com/restaurants/paris-c415144"],
    "searchRadiusKm": 10,
    "language": "en",
    "reviewLanguage": "all",
    "sort": "popularity",
    "maxRestaurants": 20,
    "maxReviews": 20,
    "maxPhotos": 20,
}

# Run the Actor and wait for it to finish
run = client.actor("clearpath/thefork-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 '{
  "startUrls": [
    "https://www.thefork.com/restaurants/paris-c415144"
  ],
  "searchRadiusKm": 10,
  "language": "en",
  "reviewLanguage": "all",
  "sort": "popularity",
  "maxRestaurants": 20,
  "maxReviews": 20,
  "maxPhotos": 20
}' |
apify call clearpath/thefork-scraper --silent --output-dataset

```

## MCP server setup

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

```

## OpenAPI specification

```json
{
    "openapi": "3.0.1",
    "info": {
        "title": "TheFork Scraper - Restaurants, Reviews & Menus",
        "description": "Extract restaurant data, reviews, menus with prices, and photos from TheFork. Get ratings, Michelin stars, TripAdvisor scores, contact details, booking availability, and 100+ fields. Supports 5 languages. Export as JSON, CSV, Excel.",
        "version": "0.0",
        "x-build-id": "DypI6Wip0oTR8aWHc"
    },
    "servers": [
        {
            "url": "https://api.apify.com/v2"
        }
    ],
    "paths": {
        "/acts/clearpath~thefork-scraper/run-sync-get-dataset-items": {
            "post": {
                "operationId": "run-sync-get-dataset-items-clearpath-thefork-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/clearpath~thefork-scraper/runs": {
            "post": {
                "operationId": "runs-sync-clearpath-thefork-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/clearpath~thefork-scraper/run-sync": {
            "post": {
                "operationId": "run-sync-clearpath-thefork-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",
                "properties": {
                    "startUrls": {
                        "title": "TheFork URLs",
                        "type": "array",
                        "description": "TheFork URLs to scrape. Supports restaurant pages, city pages, and search URLs with embedded filters. Mix types freely.",
                        "items": {
                            "type": "string"
                        }
                    },
                    "searchLocation": {
                        "title": "Search location",
                        "type": "string",
                        "description": "Alternative to URLs. City, neighborhood, or address. Typos and non-English names work fine (e.g. \"Barclona\", \"Milano\").<br><br>Ignored when URLs are provided above."
                    },
                    "searchRadiusKm": {
                        "title": "Search radius (km)",
                        "minimum": 1,
                        "type": "integer",
                        "description": "Geographic radius around <b>Search location</b>, in kilometers.<br><br>Only applies to small towns and villages where TheFork falls back to coordinate-based search (large cities use their own polygon and ignore this).<br><br>Default <code>10 km</code>. Increase (e.g. <code>50</code>) for wider coverage of rural areas, or decrease (e.g. <code>3</code>) for tighter scoping."
                    },
                    "language": {
                        "title": "Language",
                        "enum": [
                            "en",
                            "fr",
                            "de",
                            "it",
                            "es"
                        ],
                        "type": "string",
                        "description": "Controls the language of descriptions, cuisine names, tags, and reviews. Also determines the TheFork domain used.",
                        "default": "en"
                    },
                    "reviewLanguage": {
                        "title": "Review language",
                        "enum": [
                            "all",
                            "en",
                            "fr",
                            "de",
                            "it",
                            "es",
                            "nl",
                            "pt"
                        ],
                        "type": "string",
                        "description": "Filter reviews by language. Pick <b>All languages</b> to keep every review regardless of language, or pick a specific language to filter.",
                        "default": "all"
                    },
                    "sort": {
                        "title": "Sort by",
                        "enum": [
                            "popularity",
                            "avgRate",
                            "quality",
                            "promotion",
                            "newRestaurant",
                            "price",
                            "lastMonthAvg",
                            "lastMonthReservation"
                        ],
                        "type": "string",
                        "description": "Sort order for search results. Only applies to location-based searches, not to URLs.",
                        "default": "popularity"
                    },
                    "bestRated": {
                        "title": "Best rated only",
                        "type": "boolean",
                        "description": "Only return top-rated restaurants.",
                        "default": false
                    },
                    "promotionsOnly": {
                        "title": "Promotions only",
                        "type": "boolean",
                        "description": "Only return restaurants with active promotions or deals.",
                        "default": false
                    },
                    "minPrice": {
                        "title": "Min average price",
                        "minimum": 1,
                        "type": "integer",
                        "description": "Minimum average price per person in euros. Leave empty for no minimum."
                    },
                    "maxPrice": {
                        "title": "Max average price",
                        "minimum": 1,
                        "type": "integer",
                        "description": "Maximum average price per person in euros. Leave empty for no maximum."
                    },
                    "minRating": {
                        "title": "Min rating",
                        "minimum": 1,
                        "maximum": 10,
                        "type": "number",
                        "description": "Minimum TheFork rating (1-10 scale). Leave empty for no minimum."
                    },
                    "maxRating": {
                        "title": "Max rating",
                        "minimum": 1,
                        "maximum": 10,
                        "type": "number",
                        "description": "Maximum TheFork rating (1-10 scale). Leave empty for no maximum."
                    },
                    "cuisineTagIds": {
                        "title": "Cuisine types",
                        "type": "array",
                        "description": "Filter by cuisine type. Select one or more. Leave empty for all cuisines.",
                        "items": {
                            "type": "string",
                            "enum": [
                                "459",
                                "453",
                                "387",
                                "2143",
                                "431",
                                "430",
                                "406",
                                "389",
                                "2139",
                                "428",
                                "895",
                                "434",
                                "450",
                                "429",
                                "451",
                                "471",
                                "436",
                                "391",
                                "789",
                                "460",
                                "458",
                                "896",
                                "437",
                                "791",
                                "452",
                                "432",
                                "393",
                                "401",
                                "468",
                                "2375",
                                "485",
                                "394"
                            ],
                            "enumTitles": [
                                "American",
                                "Argentinian",
                                "Asian",
                                "Austrian",
                                "Belgian",
                                "British",
                                "Catalan",
                                "Chinese",
                                "Dutch",
                                "European",
                                "Franco-Belgian",
                                "French",
                                "Fusion",
                                "German",
                                "Indian",
                                "International",
                                "Italian",
                                "Japanese",
                                "Mediterranean",
                                "Middle Eastern",
                                "Peruvian",
                                "Pizzeria",
                                "Portuguese",
                                "Seafood",
                                "South American",
                                "Spanish",
                                "Thai",
                                "Traditional cuisine",
                                "Turkish",
                                "Vegan cuisine",
                                "Vegetarian",
                                "Vietnamese"
                            ]
                        },
                        "default": []
                    },
                    "maxRestaurants": {
                        "title": "Max restaurants (0 = unlimited)",
                        "minimum": 0,
                        "type": "integer",
                        "description": "Maximum restaurants to scrape. Set to <code>0</code> for no limit. Applies to both search results and direct restaurant URLs.",
                        "default": 100
                    },
                    "maxReviews": {
                        "title": "Max reviews per restaurant (0 = skip)",
                        "minimum": 0,
                        "type": "integer",
                        "description": "Reviews per restaurant, newest first. Set to <code>0</code> to skip reviews entirely.<br><br>For unlimited reviews from a single restaurant, use <a href=\"https://apify.com/clearpath/thefork-restaurant-reviews\" target=\"_blank\">TheFork Reviews</a> instead.",
                        "default": 100
                    },
                    "maxPhotos": {
                        "title": "Max customer photos per restaurant (0 = skip)",
                        "minimum": 0,
                        "type": "integer",
                        "description": "Customer photos per restaurant, paginated. Official restaurant photos (~19) are always included regardless of this setting. Set to <code>0</code> to skip customer photos entirely.",
                        "default": 20
                    }
                }
            },
            "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
                                    }
                                }
                            }
                        }
                    }
                }
            }
        }
    }
}
```
