# Glovo Scraper – Stores, Restaurants & Menus (`badr_xba/glovo-scraper`) Actor

Scrape Glovo stores and restaurants with their full menus: dish and product names, prices, options, photos, categories, ratings, delivery fees and opening status. Works in every Glovo country and city.

- **URL**: https://apify.com/badr\_xba/glovo-scraper.md
- **Developed by:** [Badr Bouargan](https://apify.com/badr_xba) (community)
- **Categories:** E-commerce
- **Stats:** 2 total users, 1 monthly users, 0.0% runs succeeded, 0 bookmarks
- **User rating**: No ratings yet

## Pricing

from $0.03 / actor start

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

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

## What's an Apify Actor?

An Actor is a serverless cloud program that runs on the Apify platform. It has two run modes.
In Batch mode, an Actor accepts a well-defined JSON input, performs an action which can take anything from a few seconds to a few hours,
and optionally produces a well-defined JSON output, datasets with results, or files in key-value store.
In Standby mode, an Actor provides a web server which can be used as a website, API, or an MCP server.

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

## How to integrate an Actor?

If asked about integration, you help developers integrate Actors into their projects.
You adapt to their stack and deliver integrations that are safe, well-documented, and production-ready.

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

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

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

# README

## Glovo Scraper – Stores, Restaurants & Menus

Extract **Glovo stores, restaurants and their full menus** in any Glovo city: dish and product names, prices, options and extras, photos, menu sections, store ratings, delivery fees, ETA and open/closed status.

### 🌍 21 countries, 233 cities built in

Armenia · Bulgaria · Côte d'Ivoire · Croatia · Georgia · Italy · Kazakhstan · Kenya · Kyrgyzstan · Moldova · Montenegro · Morocco · Nigeria · Poland · Portugal · Romania · Serbia · Spain · Tunisia · Uganda · Ukraine

Pick countries from a list — the Actor knows their cities and the right language. Or set **All Glovo countries** and a **max cities per country** limit.

### ✨ What you get

- **All store categories of a city** (restaurants, groceries, pharmacies, shops…) discovered automatically.
- **One row per product** with its store: perfect for Excel, price monitoring or market research.
- **Menu sections** (e.g. *Burgers & Wraps*, *Boissons*) and **options/extras** with their extra price.
- **Store data**: rating, votes, tags, delivery fee, free-delivery flag, ETA, distance, open status, service fee.
- **Stores-only mode** (`scrapeMenus: false`) for a fast city-wide store list.
- **Filters**: price range, dish name keywords, excluded words, menu section or store type.
- **Price tracking between runs** (`trackPriceChanges`): previous price, change in value and %, new dishes — plus optional **e-mail alerts** on price drops, sent to your Apify account address.
- **Respectful crawling**: identified bot (`GlovoCatalogBot/1.0 (+contact)`), rate limit, public pages only — Glovo's robots.txt allows crawling.

### 🚀 How to use

1. Set **Country** (`ma`, `es`, `it`, `pt`, `pl`, `ro`, `ke`, `ci`…) and **Language** (`fr`, `en`, `es`…).
2. Add one or more **Cities** exactly as they appear in Glovo URLs (`casablanca`, `rabat`, `marrakech`).
3. Optionally add **Start URLs** (a category or a single store) and limits.
4. Click **Start**, then export as Excel, CSV or JSON.

### 📦 Output example

```json
{
    "storeName": "Sumo Sushis",
    "storeUrl": "https://glovoapp.com/fr/ma/casablanca/stores/sumo-sushis",
    "storeTags": ["Sushi"],
    "storeRating": "94%",
    "isOpen": true,
    "eta": "30-40 min",
    "deliveryFeeText": "Gratuit",
    "menuSection": "Makis",
    "name": "California Saumon Avocat",
    "price": 65,
    "currency": "MAD",
    "priceText": "65,00 MAD",
    "imageUrl": "https://…/product.png",
    "options": [{ "name": "Suppléments", "min": 0, "max": 3, "choices": [{ "name": "Sauce soja", "extraPrice": 5 }] }],
    "city": "casablanca",
    "country": "ma"
}
```

### 🛒 Restaurants **and** supermarkets

- **Restaurants and food stores**: the whole menu is read from the page — every dish, price, section and option.
- **Supermarkets, pharmacies and shops**: the Actor walks the store **aisles** (Promotions, Frozen food, Drinks…) through Glovo's own content service and returns the individual products, with their aisle name. Depth is configurable (`maxAisleDepth`), and `maxProductsPerStore` caps huge catalogues.

Tested: 500 products each from Carrefour Market and Marjane Hyper (Casablanca) and Carrefour (Madrid), across ~20 aisles per store.

### ⚠️ Coverage

Glovo shows **50 stores per category page** and loads the rest through an internal API that is not publicly documented. The Actor therefore visits every category **and its sub-filters** (pizza, burgers, sushi…), which typically covers **60–70 % of the stores of a large category** and nearly all stores in small ones. To be exhaustive, add the missing stores as **Start URLs**.

### 💰 Cost

Very low: no proxy is needed and one request returns a full store menu (often 100+ products). A city with 50 stores and their menus costs a few cents on Apify.

### ⚖️ Legal

Glovo's `robots.txt` allows crawling (only a few internal pages are disallowed) and the Terms of Use contain no anti-crawling clause, but the content remains Glovo's and the merchants' property: use the data for analysis, not for republishing menus as your own. No personal data is collected.

# Actor input Schema

## `countries` (type: `array`):

Pays Glovo à parcourir. Les villes principales de chaque pays sont utilisées automatiquement.

## `allCountries` (type: `boolean`):

Parcourt les 21 pays où Glovo est actif (233 villes). Très volumineux : limitez le nombre de villes par pays ET activez le proxy RESIDENTIAL, sinon Glovo bloquera les requêtes (erreur 403).

## `maxCitiesPerCountry` (type: `integer`):

0 = toutes les villes connues du pays. Les villes sont classées par importance.

## `cities` (type: `array`):

Facultatif : villes précises (ex. casablanca, rabat). Si rempli, remplace les villes automatiques des pays choisis.

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

URLs Glovo précises : ville, catégorie (…/categories/restaurants\_1) ou magasin (…/stores/mcdonalds-cas). Utile pour compléter la liste des magasins d'une ville.

## `useCountryCities` (type: `boolean`):

Décochez pour ne traiter que les « URLs de départ » (utile pour cibler quelques magasins précis).

## `languageCode` (type: `string`):

Facultatif : force la langue des pages (fr, en, es…). Par défaut, la langue principale du pays.

## `scrapeMenus` (type: `boolean`):

Ouvre chaque magasin pour récupérer ses plats avec prix et options. Fonctionne pour les restaurants et la nourriture ; les boutiques et supermarchés rangent leurs produits dans des rayons chargés dynamiquement, seule leur fiche magasin est alors enregistrée. Décochez pour n'obtenir que la liste des magasins (beaucoup plus rapide).

## `scrapeShopAisles` (type: `boolean`):

Pour les magasins qui n'affichent pas leur catalogue directement (supermarchés, parapharmacies, boutiques), l'Actor parcourt les rayons pour récupérer tous les produits. Plus complet, mais plus de requêtes.

## `maxAisleDepth` (type: `integer`):

Nombre de niveaux de rayons explorés (rayon, sous-rayon, etc.).

## `maxStoresPerCity` (type: `integer`):

0 = tous les magasins trouvés. Attention : une ville entière avec tous ses produits peut demander plus d'une heure.

## `maxProductsPerStore` (type: `integer`):

0 = tout le catalogue du magasin. Les supermarchés peuvent contenir plus de 10 000 produits.

## `includeClosedStores` (type: `boolean`):

Les magasins fermés au moment du run restent inclus (leur menu est visible).

## `storeNameContains` (type: `string`):

Ne garder que les magasins dont le nom contient ce texte (ex. pizza, mcdonald).

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

Ne garder que les produits à ce prix ou plus.

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

Ne garder que les produits à ce prix ou moins.

## `nameKeywords` (type: `array`):

Garder les produits dont le nom contient un de ces mots (ex. pizza, tacos).

## `excludeKeywords` (type: `array`):

Exclure les produits dont le nom contient un de ces mots.

## `categoryKeywords` (type: `array`):

Garder les produits dont la rubrique de menu ou le type de magasin contient un de ces mots (ex. burgers, sushi).

## `trackPriceChanges` (type: `boolean`):

Mémorise le prix de chaque plat pour le comparer au run suivant : ancien prix, variation, nouveautés.

## `onlyChangedProducts` (type: `boolean`):

N'enregistrer que les nouveaux plats et ceux dont le prix a changé depuis le dernier run.

## `sendEmailAlerts` (type: `boolean`):

Envoie à la fin du run un récapitulatif des baisses de prix à l'adresse de votre compte Apify.

## `alertMinPriceDropPercent` (type: `integer`):

Seuil de déclenchement des alertes.

## `maxRequestsPerMinute` (type: `integer`):

Vitesse maximale. Au-delà d'environ 60 requêtes/minute, l'API de Glovo renvoie des erreurs 429 (trop rapide) : 45 est un bon compromis.

## `botContact` (type: `string`):

E-mail ou URL de contact ajouté au User-Agent du robot (recommandé). Vide = adresse de l'Actor sur Apify.

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

Aucun proxy par défaut : pour 1 à 3 villes, Glovo répond sans problème. Au-delà (plusieurs pays, ou « Tous les pays Glovo »), activez le proxy Apify RESIDENTIAL : sinon Glovo bloque l'adresse IP avec des erreurs 403 et le run ne ramène rien.

## Actor input object example

```json
{
  "countries": [
    "ma"
  ],
  "allCountries": false,
  "maxCitiesPerCountry": 1,
  "useCountryCities": true,
  "scrapeMenus": true,
  "scrapeShopAisles": true,
  "maxAisleDepth": 2,
  "maxStoresPerCity": 25,
  "maxProductsPerStore": 250,
  "includeClosedStores": true,
  "trackPriceChanges": false,
  "onlyChangedProducts": false,
  "sendEmailAlerts": false,
  "alertMinPriceDropPercent": 10,
  "maxRequestsPerMinute": 45,
  "proxyConfiguration": {
    "useApifyProxy": false
  }
}
```

# Actor output Schema

## `overview` (type: `string`):

Tableau : magasin, rubrique, produit, prix, ville et lien.

## `allFields` (type: `string`):

Données complètes, options des produits comprises.

## `runStats` (type: `string`):

Nombre de magasins et de produits collectés.

# 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 = {
    "countries": [
        "ma"
    ],
    "maxCitiesPerCountry": 1,
    "maxStoresPerCity": 25,
    "maxProductsPerStore": 250,
    "proxyConfiguration": {
        "useApifyProxy": false
    }
};

// Run the Actor and wait for it to finish
const run = await client.actor("badr_xba/glovo-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 = {
    "countries": ["ma"],
    "maxCitiesPerCountry": 1,
    "maxStoresPerCity": 25,
    "maxProductsPerStore": 250,
    "proxyConfiguration": { "useApifyProxy": False },
}

# Run the Actor and wait for it to finish
run = client.actor("badr_xba/glovo-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 '{
  "countries": [
    "ma"
  ],
  "maxCitiesPerCountry": 1,
  "maxStoresPerCity": 25,
  "maxProductsPerStore": 250,
  "proxyConfiguration": {
    "useApifyProxy": false
  }
}' |
apify call badr_xba/glovo-scraper --silent --output-dataset

```

## MCP server setup

```json
{
    "mcpServers": {
        "apify": {
            "type": "http",
            "url": "https://mcp.apify.com/?tools=fetch-actor-details,badr_xba/glovo-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/l8B0LhFopWg7wyy85/builds/v43DPXGYWfNR8kiLc/openapi.json
