# iFood Restaurant Scraper — CNPJ, Address & Hours (`memo23/ifood-scraper`) Actor

Turn iFood delivery URLs into one restaurant row each: name, rating, category, CNPJ, street address, phone, and weekday hours. Paste store links or merchant UUIDs. Built for Brazil marketplace research, dark-kitchen scouting, and store-level audits. No menus in this version.

- **URL**: https://apify.com/memo23/ifood-scraper.md
- **Developed by:** [Muhamed Didovic](https://apify.com/memo23) (community)
- **Categories:** E-commerce, Travel
- **Stats:** 2 total users, 1 monthly users, 66.7% runs succeeded, 0 bookmarks
- **User rating**: No ratings yet

## Pricing

from $15.00 / 1,000 restaurant scrapeds

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?

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

## iFood Scraper — Menus, Reviews, CNPJ & Address

Turn iFood delivery URLs — or a city + address search — into one restaurant row: name, rating, CNPJ, street address, phone, hours, menu items with prices when the catalog answers, and optional customer reviews.

Brazil marketplace records. One billed row per restaurant.

#### How it works

![How the iFood restaurant scraper works](https://raw.githubusercontent.com/muhamed-didovic/muhamed-didovic.github.io/main/assets/how-it-works-ifood.png)

### Why Use This Scraper?

- **CNPJ on the row.** Company tax id comes with the street address — useful for matching a store to a legal entity.
- **Hours and phone included.** Weekday opening windows and the store phone, not just the card rating.
- **Delivery URLs or raw UUIDs.** The same `{city}/{slug}/{uuid}` link you copy from ifood.com.br, or the merchant id alone.
- **One row per restaurant.** No menu-item explosion, no join keys. Name, geo, and documents sit on the same record.
- **Menus and reviews on the same row.** `includeMenu` / `includeReviews` match the other iFood Store actors. Check `menuSource` — catalog can come back empty when iFood blocks it.
- **City + address search.** Same `sao-paulo-sp` + `Av Paulista 1000` + `query` shape as the listing next door. Falls back to URL mode if search returns nothing.

### Overview

Built for researchers, dark-kitchen operators, and agencies that need the public merchant card plus extra (address, CNPJ, hours), optional reviews, and menu items when the catalog answers. Paste delivery URLs or search by city + address. Each restaurant becomes at most one dataset row.

### Supported Inputs

| Input | Example | Returns |
|---|---|---|
| **Delivery URL** | `https://www.ifood.com.br/delivery/sao-paulo-sp/bubblekill-patio-paulista-bela-vista/5024be82-d729-41b9-a64f-d44ba306f232` | That restaurant |
| **Merchant UUID** | `5024be82-d729-41b9-a64f-d44ba306f232` | Same restaurant, URL rebuilt from the slug |

**Search mode:** `city` (`sao-paulo-sp`) + optional `address` + `query`. Used only when `restaurantUrls` is empty.

**Not supported:** logged-in prices, downloading every menu photo to the Key-Value Store, or PedidosYa / Rappi.

### Use Cases

| You are a… | Use it to… |
|---|---|
| Market researcher | Build a store list with CNPJ + neighborhood for a city you already sampled |
| Competitor analyst | Track rating, min order, and hours on a fixed set of restaurants |
| Dark-kitchen operator | Confirm legal entity and address for nearby iFood stores |
| Agency / data team | Enrich a spreadsheet of iFood links before a client report |

### How It Works

1. **Resolve** restaurants from delivery URLs / UUIDs, or from `city` + `address` + `query` search.
2. **Fetch the merchant card** from iFood's public marketplace API (`/v1/merchants/{uuid}?channel=IFOOD`).
3. **Fetch the extra record** (address, CNPJ, phone, hours) when `includeExtra` is on.
4. **Fetch the catalog** when `includeMenu` is on. Empty catalogs land as `menuSource: unavailable`.
5. **Fetch evaluations** when `includeReviews` is on.
6. **Merge** into one restaurant row and push it. Base charge is per restaurant; extra / menu / reviews are billed only when those fields actually land.

### Input Configuration

| Field | Type | Description |
|---|---|---|
| `restaurantUrls` | array | Delivery URLs or merchant UUIDs. Skips search when filled. |
| `city` | string | City slug (`sao-paulo-sp`). Search mode only. |
| `address` | string | Delivery address for geocoding. Search mode only. |
| `query` | string | Cuisine / name filter (`pizza`). Search mode only. |
| `maxRestaurants` | integer | Cap on rows (and charges). Default `50`. |
| `includeMenu` | boolean | Menu items + prices. Billed only when `menu[]` is non-empty. Default `true`. |
| `menuMode` | string | `limited` or `all`. Default `limited`. |
| `maxMenuItems` | integer | Cap per restaurant in limited mode. Default `50`. |
| `includeReviews` | boolean | Customer evaluations. Billed once per restaurant, not per review. Default `false`. |
| `includeExtra` | boolean | Address, CNPJ, phone, hours. Billed when at least one of those lands. Default `true`. |
| `maxConcurrency` | integer | Parallel fetches, 1–8. Default `4`. |

**One restaurant**

```json
{
  "restaurantUrls": [
    "https://www.ifood.com.br/delivery/sao-paulo-sp/bubblekill-patio-paulista-bela-vista/5024be82-d729-41b9-a64f-d44ba306f232"
  ],
  "maxRestaurants": 1
}
```

**Several stores, card only**

```json
{
  "restaurantUrls": [
    "5024be82-d729-41b9-a64f-d44ba306f232",
    "bca94461-58e3-4a70-b142-8f8694133838"
  ],
  "includeExtra": false,
  "includeMenu": false,
  "maxRestaurants": 2
}
```

**Reviews + city search**

```json
{
  "city": "sao-paulo-sp",
  "address": "Av Paulista 1000",
  "query": "pizza",
  "includeReviews": true,
  "maxRestaurants": 10
}
```

### Output Overview

The dataset holds **one row per restaurant**. Identity, rating, category, and availability come from the merchant card. Street address, CNPJ, phone, and weekday hours come from the extra record. Menu items and reviews sit on the same row when those flags are on. Fields iFood does not publish stay `null` or `[]`.

### Output Samples

Delivery URL → Bubblekill Pátio Paulista (São Paulo):

```json
{
  "uuid": "5024be82-d729-41b9-a64f-d44ba306f232",
  "shortId": 2125042,
  "name": "Bubblekill Pátio Paulista",
  "slug": "sao-paulo-sp/bubblekill-patio-paulista-bela-vista",
  "url": "https://www.ifood.com.br/delivery/sao-paulo-sp/bubblekill-patio-paulista-bela-vista/5024be82-d729-41b9-a64f-d44ba306f232",
  "city": "sao-paulo-sp",
  "description": "Bubble Tea",
  "category": "Casa de Sucos",
  "priceRange": "CHEAPEST",
  "currency": "BRL",
  "rating": 5,
  "reviewsCount": 61,
  "available": true,
  "minimumOrderValue": 10,
  "address": "Rua Treze de Maio, 1947, Pátio Paulista - 3º Piso, Bela Vista, SAO PAULO - SP, 01327900",
  "street": "Rua Treze de Maio",
  "streetNumber": "1947",
  "district": "Bela Vista",
  "cityName": "SAO PAULO",
  "state": "SP",
  "zipCode": "01327900",
  "cnpj": "44918087000156",
  "phone": "+55 11 40032665",
  "openingHours": [
    { "dayOfWeek": "MONDAY", "start": "11:00:00", "durationMinutes": 600 }
  ],
  "menu": [],
  "menuItemCount": 0,
  "menuSource": "unavailable",
  "reviews": [
    {
      "customerName": "Ana",
      "rating": 5,
      "comment": "Pedido chegou quente.",
      "commentedAt": "2026-08-12T18:22:00.000Z"
    }
  ],
  "reviewAverages": [
    { "title": "Comida", "grade": 4.8, "count": 40 }
  ]
}
```

### Key Output Fields

**Identity:** `uuid`, `shortId`, `name`, `slug`, `url`, `city`, `description`, `category`, `logoUrl`, `coverUrl`

**Commerce:** `priceRange`, `currency`, `rating`, `reviewsCount`, `available`, `minimumOrderValue`, `deliveryFee`, `deliveryFeeOriginal`, `deliveryTime`, `distance`, `features`, `paymentCodes`

**Legal / location:** `cnpj`, `address`, `street`, `streetNumber`, `streetCompl`, `district`, `cityName`, `state`, `zipCode`, `country`, `latitude`, `longitude`

**Contact / hours:** `phone`, `areaCode`, `openingHours[]`

**Menu:** `menu[]`, `menuItemCount`, `menuSource`, `avgMenuPrice`, `cheapestPrice`, `mostExpensivePrice`, `cheapestItem`, `mostExpensiveItem`

**Reviews:** `reviews[]`, `reviewAverages[]`, `recentReviewsCount`

### FAQ

**Do I need an iFood account?** No. The actor reads public marketplace records.

**Can I search a city for pizza?** Yes — `city`, `address`, `query`. If iFood's search API is blocked that run, the actor fails with 0 rows unless you also passed `restaurantUrls`.

**Where is the menu?** `includeMenu: true` (default). When the catalog answers you get `menu[]` plus `avgMenuPrice` / cheapest / most expensive. When it is blocked, `menuSource` is `unavailable` and `menu` is `[]` — the restaurant row still bills.

**Are reviews billed one-by-one?** No. One `restaurant-reviews` event per restaurant when `reviews[]` is non-empty. Extra and menu work the same way — billed only when the data is on the row.

**What if a URL is dead?** That restaurant is skipped and not billed. A run with zero successful rows fails.

**Is CNPJ always present?** When `includeExtra` is true and iFood publishes documents for that merchant. Ghost kitchens sometimes omit it.

### Support

Open an issue on the [Apify Store listing](https://apify.com/memo23/ifood-scraper/issues) or email **contact@data-slayer.com**.

### Additional Services

Need a custom export, a scheduled city monitor once search is possible again, or a merge with another delivery marketplace? Email the same address with the store list and the fields you need.

### Explore More Scrapers

- [Uber Eats Full Menu & Reviews](https://apify.com/memo23/uber-eats-scraper)
- [Talabat — Restaurants, Menus, Prices](https://apify.com/memo23/talabat-scraper)
- [Swiggy — Restaurants, Ratings & Offers](https://apify.com/memo23/swiggy-scraper)
- [Zomato — Restaurants, Ratings & Reviews](https://apify.com/memo23/zomato-scraper)

### 🤖 For AI Agents & LLM Apps

Compact reference for agents calling this actor via the [Apify MCP server](https://mcp.apify.com) or the Apify API (`memo23/ifood-scraper`).

**Purpose:** Public iFood restaurant records in Brazil. URL mode or city/address search. One row per store, with CNPJ/address/hours, optional menu, optional reviews.

**Minimal input:**

```json
{
  "restaurantUrls": [
    "https://www.ifood.com.br/delivery/sao-paulo-sp/bubblekill-patio-paulista-bela-vista/5024be82-d729-41b9-a64f-d44ba306f232"
  ],
  "includeReviews": true,
  "maxRestaurants": 5
}
```

**Output:** one row per restaurant — `uuid`, `name`, `url`, `city`, `category`, `rating`, `reviewsCount`, `cnpj`, `address`, `phone`, `openingHours[]`, `menu[{id, name, details, section, price, originalPrice, imageUrl}]`, `menuSource`, `avgMenuPrice`, `reviews[{customerName, rating, comment, commentedAt}]`, `reviewAverages[]`, `scrapedAt`.

**Behaviors an agent should know:**

- Always set `maxRestaurants`. Each written row is billed ($0.015). Extra ($0.005), menu ($0.010), and reviews ($0.005) fire only when those fields are non-empty.
- `restaurantUrls` wins over `city` / `address` / `query`.
- `includeReviews` defaults false. `includeMenu` defaults true.
- `menuSource` is `catalog`, `catalog-search`, `empty`, or `unavailable`.
- Failed URLs are skipped and not billed. Zero successful rows fail the run.

### ⚠️ Disclaimer

This Actor is an independent tool and is not affiliated with, endorsed by, or sponsored by iFood.com Agência de Restaurantes Online S.A. or any of its subsidiaries. All trademarks mentioned are the property of their respective owners.

The scraper accesses only publicly available iFood marketplace records — no authenticated endpoints, paid features, or content behind the ifood.com.br login wall. Users are responsible for ensuring their use complies with ifood.com.br's Terms of Service, applicable data-protection law (LGPD, GDPR, CCPA, etc.), and any contractual obligations of their own organization.

***

### SEO Keywords

ifood scraper, ifood restaurant scraper, ifood menu scraper, ifood reviews, ifood cnpj, ifood address, ifood delivery url, brazilian restaurant data, ifood marketplace, dark kitchen research, ifood store hours, ifood phone, food delivery intelligence, sao paulo restaurant data, ifood merchant uuid, restaurant competitive intelligence, brazil food delivery

# Actor input Schema

## `restaurantUrls` (type: `array`):

iFood delivery pages or merchant UUIDs. Format: https://www.ifood.com.br/delivery/sao-paulo-sp/{slug}/{uuid}. When this list is filled, city/address search is skipped. One billed row per unique restaurant.

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

iFood city slug, e.g. sao-paulo-sp, rio-de-janeiro-rj, belo-horizonte-mg. Only used when restaurantUrls is empty.

## `address` (type: `string`):

Street address used to geocode the search point, e.g. Av Paulista 1000. Only used in search mode.

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

Cuisine or restaurant term sent to iFood search (pizza, sushi, hamburger). Empty falls back to 'restaurante'. Only used in search mode.

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

Hard cap on restaurants returned (and billed). Default 50.

## `includeMenu` (type: `boolean`):

Fetch menu items and prices when iFood's catalog answers. Billed once per restaurant only when menu\[] is non-empty. If the catalog is blocked, menuSource is unavailable and this event is not charged. Default true.

## `menuMode` (type: `string`):

limited = at most maxMenuItems per restaurant. all = no local cap (iFood pagination can still truncate). Default limited.

## `maxMenuItems` (type: `integer`):

Used when menuMode is limited. Default 50. Ignored when menuMode is all.

## `includeReviews` (type: `boolean`):

Fetch customer evaluations (name, rating, comment when published, criterion averages). Billed once per restaurant when at least one review is returned, not per review. Default false.

## `includeExtra` (type: `boolean`):

Merchant extra record: street address, CNPJ, phone, rating count, weekday hours. Billed once per restaurant when at least one of those fields lands. Default true.

## `maxConcurrency` (type: `integer`):

How many restaurants to fetch in parallel. Default 4, max 8.

## Actor input object example

```json
{
  "restaurantUrls": [
    "https://www.ifood.com.br/delivery/sao-paulo-sp/bubblekill-patio-paulista-bela-vista/5024be82-d729-41b9-a64f-d44ba306f232"
  ],
  "city": "sao-paulo-sp",
  "address": "Av Paulista 1000",
  "maxRestaurants": 50,
  "includeMenu": true,
  "menuMode": "limited",
  "maxMenuItems": 50,
  "includeReviews": false,
  "includeExtra": true,
  "maxConcurrency": 4
}
```

# Actor output Schema

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

One record per restaurant — name, rating, CNPJ, address, phone, hours, menu items when the catalog answers, reviews when requested.

# 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 = {
    "restaurantUrls": [
        "https://www.ifood.com.br/delivery/sao-paulo-sp/bubblekill-patio-paulista-bela-vista/5024be82-d729-41b9-a64f-d44ba306f232"
    ],
    "city": "sao-paulo-sp",
    "address": "Av Paulista 1000"
};

// Run the Actor and wait for it to finish
const run = await client.actor("memo23/ifood-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 = {
    "restaurantUrls": ["https://www.ifood.com.br/delivery/sao-paulo-sp/bubblekill-patio-paulista-bela-vista/5024be82-d729-41b9-a64f-d44ba306f232"],
    "city": "sao-paulo-sp",
    "address": "Av Paulista 1000",
}

# Run the Actor and wait for it to finish
run = client.actor("memo23/ifood-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 '{
  "restaurantUrls": [
    "https://www.ifood.com.br/delivery/sao-paulo-sp/bubblekill-patio-paulista-bela-vista/5024be82-d729-41b9-a64f-d44ba306f232"
  ],
  "city": "sao-paulo-sp",
  "address": "Av Paulista 1000"
}' |
apify call memo23/ifood-scraper --silent --output-dataset

```

## MCP server setup

```json
{
    "mcpServers": {
        "apify": {
            "type": "http",
            "url": "https://mcp.apify.com/?tools=fetch-actor-details,memo23/ifood-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/4Ei2ruT5W2KBlaXF6/builds/aediqKcrPAXA2HlSy/openapi.json
