# Deliveroo Food Delivery Scraper — UK Restaurants & Menus (`studio-amba/deliveroo-scraper`) Actor

Scrape Deliveroo.co.uk food delivery restaurant listings by UK postcode: name, rating, distance, delivery fee, minimum order, address, and per-restaurant menu items with prices. No login required.

- **URL**: https://apify.com/studio-amba/deliveroo-scraper.md
- **Developed by:** [Studio Amba](https://apify.com/studio-amba) (community)
- **Categories:** Other
- **Features:** Limited permissions
- **Stats:** 9 total users, 2 monthly users, 100.0% runs succeeded, 0 bookmarks
- **User rating**: No ratings yet

## Pricing

from $1.20 / 1,000 result 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?

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

## Deliveroo Food Delivery Scraper — UK Restaurant Listings & Menus

Extract restaurant listings from **Deliveroo.co.uk** by UK postcode — restaurant name, star rating, review count, distance, estimated delivery time, delivery fee, minimum order value, full address, and a sample of menu items with real prices for every restaurant delivering to that postcode. No login, no app, no session cookies.

### Why use this actor?

Deliveroo covers thousands of UK restaurants and takeaways, but there's no public API for it — every price, rating, and menu is only visible one restaurant at a time inside the app or the web checkout flow. Food delivery aggregators, market researchers tracking delivery fees and pricing by postcode, franchise groups monitoring their own listings against competitors, and anyone building a "which postcode has the best food coverage" dataset all need this at scale instead of clicking through Deliveroo restaurant-by-restaurant. This actor turns a single UK postcode into a clean, structured dataset of every restaurant Deliveroo will deliver to that address, plus a real menu sample for each one.

### How to scrape Deliveroo data

Deliveroo.co.uk runs on Next.js and server-renders its restaurant listing pages with a full `__NEXT_DATA__` JSON payload embedded in the HTML — no headless browser is needed to read it. The site sits behind Cloudflare, which sets an `x-roo-cf-rl` rate-limit header on responses, but as of this actor's build that rule runs in simulate/log-only mode rather than actively blocking, and the listing page returns HTTP 200 with a real restaurant list for a plain, well-paced request.

The key discovery this actor relies on: Deliveroo's location resolution runs entirely off the `postcode` query parameter. The `/restaurants/{city}/{neighborhood}` path segments in the URL are cosmetic — hitting `/restaurants/london/soho?postcode=M1 1AE` resolves to Manchester results, not London. That means this actor needs no hardcoded city or neighborhood slug map (unlike scrapers for sites with internal, non-derivable city IDs): it builds one neutral listing URL per postcode and lets Deliveroo's own backend do the geocoding.

The listing page's embedded feed is a component tree of "RooBlocks" (Deliveroo's internal UI framework), not a flat restaurant array — this actor walks that tree to pull out each restaurant card's name, rating, review count, distance, and estimated delivery time, plus its restaurant/menu page URL. One response carries the full restaurant list for the postcode — typically 100-200 restaurants in a city postcode — split across many small list blocks, so no pagination is needed. The actor reads the main list in page order (deduplicated by restaurant ID) and appends the few restaurants that only appear in promotional carousels after it. When menu details are enabled (the default), the actor then visits each restaurant's own page, which carries the same `__NEXT_DATA__` pattern with the restaurant's full address, delivery fee, minimum order threshold, and the complete menu (items, descriptions, prices, and menu-section categories) in structured form.

Requests are paced with a randomized delay between each one to stay well clear of the site's rate-limit threshold, and every request uses a real browser `Accept`/`Accept-Language` header set.

### Input

| Field | Type | Required | Description |
|-------|------|----------|--------------|
| `postcode` | String | No | UK postcode to search (default: `W1F 0DN`, Soho, London). Examples: `M1 1AE` (Manchester), `EH1 1BB` (Edinburgh), `B1 1AA` (Birmingham). |
| `maxResults` | Integer | No | Maximum restaurants to return (default: 20, max: 500). One page load carries the full restaurant list for the postcode — typically 100-200 restaurants in a city postcode — so set this to 500 to get everything. |
| `includeMenuDetails` | Boolean | No | Fetch each restaurant's own page for address, delivery fee, minimum order, and menu items (default: `true`). One extra request per restaurant. Turn off for a faster, listing-only run. |
| `maxMenuItemsPerRestaurant` | Integer | No | Cap on menu items returned per restaurant (default: 15). Restaurants can list 100-900+ items; this returns a sample from the top menu section. |
| `proxyConfiguration` | Object | No | Apify Proxy settings. UK residential proxies recommended (default). |

### Output

Each result is one restaurant:

| Field | Type | Example |
|-------|------|---------|
| `restaurantId` | String | `"14250"` |
| `name` | String | `"Sushi Shop"` |
| `rating` | Number | `4.8` |
| `reviewCount` | Number | `500` — Deliveroo displays "(500+)" for anything above 500, so `500` means "at least 500" |
| `distanceMiles` | Number | `0.9` |
| `estimatedDeliveryMinutes` | Number | `20` |
| `promotionalOffer` | String | `"Spend £15, get 20% off"` |
| `address` | String | `"67-69 Weymouth Street, London, W1G8NY"` — detail-only: `null` in listing-only mode |
| `postcode` | String | `"W1G8NY"` — the restaurant's own postcode, parsed from its address. In listing-only mode this is the SEARCH postcode instead |
| `neighborhood` | String | `"Marylebone"` — detail-only: `null` in listing-only mode |
| `city` | String | `"london"` — detail-only: `null` in listing-only mode |
| `country` | String | `"GB"` |
| `currency` | String | `"GBP"` |
| `deliveryFee` | Number | `1.29` — detail-only: `null` in listing-only mode |
| `minimumOrder` | Number | `8` — detail-only: `null` in listing-only mode |
| `menuItemCount` | Number | `286` — detail-only: `0` in listing-only mode |
| `menuItemsSample` | Array | Sample menu items with name, description, category, and price — detail-only: empty in listing-only mode |
| `imageUrl` | String | Restaurant cover photo URL |
| `url` | String | Full Deliveroo restaurant/menu URL |
| `scrapedAt` | String | ISO 8601 timestamp |

"Listing-only mode" means `includeMenuDetails: false`. The detail-only fields come from each restaurant's own page, which that mode skips.

You can download the dataset in JSON, CSV, Excel, HTML, or XML directly from the Apify Console or API.

### Example output

```json
{
    "restaurantId": "14250",
    "name": "Sushi Shop",
    "rating": 4.8,
    "reviewCount": 500,
    "distanceMiles": 0.9,
    "estimatedDeliveryMinutes": 20,
    "promotionalOffer": "Spend £15, get 20% off",
    "address": "67-69 Weymouth Street, London, W1G8NY",
    "postcode": "W1G8NY",
    "neighborhood": "Marylebone",
    "city": "london",
    "country": "GB",
    "currency": "GBP",
    "deliveryFee": 1.29,
    "minimumOrder": 8,
    "menuItemCount": 286,
    "menuItemsSample": [
        {
            "id": "2701184666",
            "name": "🥇 Salmon Lovers Box (18 pcs) - For 1 person",
            "description": "Our No.1 bestseller - salmon sushi, rolls and springs.",
            "category": "MOST POPULAR",
            "price": 21.70,
            "priceFormatted": "£21.70",
            "popular": false,
            "available": true
        }
    ],
    "imageUrl": "https://rs-menus-api.roocdn.com/images/abbd8e63-1b3d-48f0-be4a-a2e062a8cb39/image.jpeg",
    "url": "https://deliveroo.co.uk/menu/london/marylebone/sushi-shop-marylebone",
    "scrapedAt": "2026-07-24T21:15:00.000Z"
}
```

### Cost estimate

With menu details on (the default), this actor makes one listing request plus one detail request per restaurant — roughly **2 requests per restaurant returned**. At standard Apify pricing, expect approximately **$0.20-$0.40 per 100 restaurants** including menu samples. Turning `includeMenuDetails` off cuts this to one request total for the whole run.

### Limitations

- Coverage per postcode matches what Deliveroo itself shows for that address: one response carries the full list — typically 100-200 restaurants in a city postcode. Deliveroo's "restaurants near you" count on the page can be higher (it counts a wider radius); the list is what actually delivers to the postcode. Run multiple postcodes to cover a wider area.
- Cuisine type is not returned. Deliveroo's UK web listing (as of this actor's build) doesn't carry a cuisine tag on restaurant cards or restaurant pages — the `menuItemsSample[].category` field (menu section names like "MOST POPULAR" or "Sharing menus") is the closest available signal, but it isn't a cuisine taxonomy. If you need cuisine tags for continental Europe food delivery, see the related Lieferando/Takeaway scraper below, which does expose them.
- `menuItemsSample` is a sample (default 15 items) from the restaurant's top menu section, not the full menu — some restaurants list 800+ items. Use `menuItemCount` to see the true total, and raise `maxMenuItemsPerRestaurant` if you need more.
- Delivery fee and minimum order reflect Deliveroo's current promotional state at scrape time (e.g. spend-based free delivery offers) and can change without notice.
- Respect Deliveroo's terms of service and use responsibly.

### Frequently asked questions

**Does this require a Deliveroo account or login?**
No. The actor reads Deliveroo's public, server-rendered listing and menu pages, which don't require authentication.

**Can I search by city name instead of postcode?**
Not directly — Deliveroo's own location resolution runs off the postcode, not city or area names, so this actor takes a postcode as input. Use any postcode within the city or area you're targeting.

**How many restaurants does one run return?**
The full list Deliveroo shows for that postcode — typically 100-200 restaurants in a city postcode, all from a single page load (no pagination involved). Set `maxResults` to 500 to get everything, and query several postcodes across an area for broader coverage.

**How fresh is the data?**
Every run scrapes live pages at request time, so ratings, review counts, promotional offers, delivery fees, and menu prices reflect Deliveroo's current listings.

### Related scrapers

- [TheFork Scraper](https://apify.com/studio-amba/thefork-scraper) — European restaurant listings, ratings, and offers from TheFork/TripAdvisor's reservation platform.
- [Lieferando & Takeaway Scraper](https://apify.com/studio-amba/takeaway-scraper) — Restaurant delivery listings, cuisines, ratings, and menus for five Just Eat Takeaway brands across continental Europe.
- [Tesco Groceries Scraper](https://apify.com/studio-amba/tesco-scraper) — UK grocery products and prices from Tesco.
- [Waitrose Scraper](https://apify.com/studio-amba/waitrose-scraper) — UK grocery products and prices from Waitrose.
- [UK Grocery Price Matrix](https://apify.com/studio-amba/uk-grocery-price-matrix) — Compare grocery prices across UK supermarkets by EAN.

# Actor input Schema

## `postcode` (type: `string`):

UK postcode to search for delivery. Example: 'W1F 0DN' (Soho, London), 'M1 1AE' (Manchester), 'EH1 1BB' (Edinburgh). Defaults to a busy London postcode if left empty.

## `maxResults` (type: `integer`):

Maximum number of restaurants to return. One page load carries the full restaurant list for the postcode — typically 100-200 restaurants in a city postcode. Set this to 500 to get everything.

## `includeMenuDetails` (type: `boolean`):

Fetch each restaurant's own page for address, delivery fee, minimum order, and a sample of menu items with prices (one extra request per restaurant). Turn off for a faster, listing-only run.

## `maxMenuItemsPerRestaurant` (type: `integer`):

Maximum number of menu items to include per restaurant (only used when 'Include Menu Details' is on). Restaurants can have 100s of items; this caps the sample to the top menu section.

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

Proxy settings. UK residential proxies recommended — Deliveroo runs Cloudflare with a rate-limit rule on this path.

## Actor input object example

```json
{
  "postcode": "W1F 0DN",
  "maxResults": 20,
  "includeMenuDetails": true,
  "maxMenuItemsPerRestaurant": 15,
  "proxyConfiguration": {
    "useApifyProxy": true,
    "apifyProxyGroups": [
      "RESIDENTIAL"
    ],
    "apifyProxyCountry": "GB"
  }
}
```

# 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 = {
    "postcode": "W1F 0DN",
    "maxResults": 20,
    "includeMenuDetails": true,
    "maxMenuItemsPerRestaurant": 15,
    "proxyConfiguration": {
        "useApifyProxy": true,
        "apifyProxyGroups": [
            "RESIDENTIAL"
        ],
        "apifyProxyCountry": "GB"
    }
};

// Run the Actor and wait for it to finish
const run = await client.actor("studio-amba/deliveroo-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 = {
    "postcode": "W1F 0DN",
    "maxResults": 20,
    "includeMenuDetails": True,
    "maxMenuItemsPerRestaurant": 15,
    "proxyConfiguration": {
        "useApifyProxy": True,
        "apifyProxyGroups": ["RESIDENTIAL"],
        "apifyProxyCountry": "GB",
    },
}

# Run the Actor and wait for it to finish
run = client.actor("studio-amba/deliveroo-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 '{
  "postcode": "W1F 0DN",
  "maxResults": 20,
  "includeMenuDetails": true,
  "maxMenuItemsPerRestaurant": 15,
  "proxyConfiguration": {
    "useApifyProxy": true,
    "apifyProxyGroups": [
      "RESIDENTIAL"
    ],
    "apifyProxyCountry": "GB"
  }
}' |
apify call studio-amba/deliveroo-scraper --silent --output-dataset

```

## MCP server setup

```json
{
    "mcpServers": {
        "apify": {
            "type": "http",
            "url": "https://mcp.apify.com/?tools=fetch-actor-details,studio-amba/deliveroo-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/PPskySbV6cakm17ng/builds/kiRkidwnPk9aZBIyW/openapi.json
