Carrefour Spain Scraper - Products, Prices, Nutrition avatar

Carrefour Spain Scraper - Products, Prices, Nutrition

Pricing

from $1.50 / 1,000 product results

Go to Apify Store
Carrefour Spain Scraper - Products, Prices, Nutrition

Carrefour Spain Scraper - Products, Prices, Nutrition

Scrape Carrefour Spain (carrefour.es) products. Search by keyword, browse a category, or paste product/category links. Returns name, brand, price, unit price, promotion, stock, category, image, and, with details, the barcode (EAN), ingredients, allergens, nutrition, extra images and rating.

Pricing

from $1.50 / 1,000 product results

Rating

0.0

(0)

Developer

Abot API

Abot API

Maintained by Community

Actor stats

1

Bookmarked

12

Total users

7

Monthly active users

3 days ago

Last modified

Share

Carrefour Spain Scraper: Products, Prices, Nutrition and Stock

Carrefour Scraper turns the Carrefour Spain (carrefour.es) supermarket catalog into structured product data. Search by keyword, browse a category, or paste product and category links, and get back price and category for every product; category browsing and category links add unit price, promotion and stock; and switching on detail adds barcode (EAN), ingredients, allergens, the full nutrition panel, extra images, the aggregate rating and the most recent customer reviews. Filter by price, rating, promotion or stock (promotion and stock filters work in every mode: search, category and URL; when the listing card itself doesn't already carry that status in search mode, the product page is read to resolve it, and that product is then billed as detail-enriched), then export to JSON, CSV or Excel, or pull results straight into your app through the API.

Why This Scraper?

  • Three ways to find products. Search by keyword, browse a category page, or paste product links, bare product ids and category links in one mixed list.
  • Full product detail on demand. Add barcode (EAN), ingredients, allergens, the complete nutrition panel, extra images, the aggregate rating and up to 20 recent customer reviews per product (adjustable), or turn detail off for a lighter, listing-only run.
  • Built-in filters and sorting. Price range, brand, minimum rating, promotion-only and in-stock-only, and eight sort orders (including top rated and promotions first), applied without writing any code.
  • Built for schedules. Incremental mode returns only new and changed products on repeat runs against the same search, and unchanged products are never billed unless you explicitly ask for them.
  • Resume without duplicate charges. Continue one interrupted run from its run or dataset id, or let the actor recover on its own after a platform restart, with no products re-collected or re-billed.
  • Send results into your apps. Pipe a condensed summary of every product into Notion, Linear or Airtable through MCP connectors, no extra code required.
  • Built for a residential connection. The actor reaches the storefront through a Spanish residential connection by default and automatically retries with a different connection when one is refused. See Plan Requirement for what to expect on a free plan.

Use Cases

  • Grocery price monitoring: track price, promotion and unit price changes across a shopping basket over time.
  • Catalog and range research: build a structured view of Carrefour Spain's assortment by category for pricing or assortment analysis.
  • Nutrition and ingredient research: collect ingredients, allergens and the full nutrition panel for dietary, labeling or compliance projects.
  • Deal and promotion tracking: filter to promoted or in-stock products only, and get notified of new deals on a recurring schedule.
  • Wine and specialty catalog research: pull tasting notes and wine-specific detail fields alongside standard product data.

Data You Get

Sample shape: values are illustrative placeholders, not from a live record.

FieldExample
productId"520661336"
name"Leche semidesnatada marca ejemplo brik 1 L"
brand"Marca Ejemplo"
ean"8400000000000"
sku"1895370000"
price0.99
regularPrice1.19
discountPercentage17
onPromotiontrue
currency"EUR"
unitPrice / unitPriceMeasure0.99 / "l"
stock / inStock240 / true
sellPackUnit1
categoryId"cat00000"
image"https://static.carrefour.es/example/000000.jpg"
imageslist of extra image URLs (when details are fetched)
ingredients"Leche de vaca semidesnatada."
allergens["Leche"]
nutritionnutrition panel values (when details are fetched)
rating / reviewCount4.5 / 12
reviews / reviewsFetchedup to 20 most recent customer reviews, each {"reviewId", "rating", "title", "text", "date", "reviewerName"}, and how many were returned (with details on)
urllink to the product page on carrefour.es
searchMode / source"search", "category", or "product", how this record was found (a pasted search-result link in url mode also reports "search")
scrapedAt"2026-01-01T00:00:00Z"

Any product returned with details also carries the label data printed on the pack where the store publishes it (legalName, manufacturer, manufacturerAddress, netContent, packagingFormat, healthRegistrationNumber, alcoholByVolume for drinks, countryOfOrigin, storageInstructions, nutriScore), an additional info block (moreInfo) and a raw offer block (offer) alongside the fields above; wine products additionally carry tasting notes and wine details (tastingNote, wineInfo). When incrementalMode is on, every returned record also carries changeType (NEW, UPDATED, UNCHANGED, REAPPEARED, or EXPIRED), changedFields (populated only for UPDATED), firstSeenAt and lastSeenAt.

How to Use

  1. Pick a mode: search (by keyword), category (a Carrefour category link OR a plain category name like leche), or url (paste product links, bare product ids, category links, promotions links and search-result links).
  2. Fill in the field for that mode, then narrow the results with the price, rating, promotion or stock filters, and pick a sort order if you want one.
  3. Turn Fetch product details on or off, and set Max products and Max pages to control run size and cost.
  4. Click Start, then download the dataset as JSON, CSV or Excel, or read it through the API.

Search by keyword:

{
"mode": "search",
"queries": ["leche"],
"maxItems": 30
}

Browse a category, promotions only:

{
"mode": "category",
"categories": ["https://www.carrefour.es/supermercado/lacteos-huevos/leche/cat20093/c"],
"onPromotionOnly": true,
"maxItems": 100
}

Paste a product link and a category link together:

{
"mode": "url",
"urls": [
"https://www.carrefour.es/supermercado/R-521007071/p",
"https://www.carrefour.es/supermercado/lacteos-huevos/leche/cat20093/c"
]
}

Every entry in urls is routed automatically, so you can mix shapes freely in one list.

ShapeExampleRouted as
Product linkhttps://www.carrefour.es/supermercado/<any-slug>/R-521007071/pProduct, full detail. The slug text next to the id is ignored: Carrefour resolves by the R-<id> segment, never by a slug text search (confirmed live, #2802), so a wrong or outdated slug still lands on the right product.
Marketplace / non-food product linkhttps://www.carrefour.es/glorioso-blanco-2025-vino-blanco-espana-rioja-doca-75-cl-120/8410351213004/p (barcode form) or https://www.carrefour.es/extractor-portatil-de-leche-kikkaboo/VC4A-27082334/p (catalogue-code form)Product, full detail, including the seller (sellerName, isMarketplace). These pages have no /supermercado/.../R-<id>/p form, so the pasted link itself is read.
Bare product id521007071 or R-521007071 (incl. marketplace ids like VC4AECOMM-700248)Product, full detail
Category linkhttps://www.carrefour.es/supermercado/.../cat20093/cCategory, all result pages. Same ID-not-slug resolution as product links.
"Ofertas" promotions linkhttps://www.carrefour.es/supermercado/bebidas-promocion/F-1086Z13rjo/cCategory, all result pages (/F-<token>/c carries a real product grid, same as a catNNNNN/c page)
Search-result linkhttps://www.carrefour.es/?q=leche or https://www.carrefour.es/#!q=lecheThe same search as typing leche into Search keywords, with your filters applied
Tracking-param variantany of the above with ?utm_source=..., ?gclid=..., etc. appendedUnaffected; tracking params are ignored, not matched against
&amp;-escaped linka link copied out of rendered HTML/email with &amp; instead of &Decoded automatically before parsing
m.carrefour.es linkhttps://m.carrefour.es/supermercado/R-521007071/pNormalized to www.carrefour.es and routed as above. No separate mobile site exists live today (probed 2026-10-06), but a stale bookmark/app-share link is still handled.
Non-food categoryany category shape above under a non-food department (Mascotas, Parafarmacia, Cuidado personal e Higiene, ...)Same routing as a grocery category
Anything else (e.g. a bare marketplace barcode or VC4A- code without its product link, or a /tecno/ link)n/aReported with a loud per-run-log warning naming the exact URL, never a silent empty result

Default behavior: the urls field ships with one live-verified example of every shape above (product, bare id, barcode-form and catalogue-code marketplace product, category, promotions category, ?q= and #!q= search links). If you run url mode and leave the field untouched, the actor now scrapes those examples instead of failing on an empty list; clear or replace the list to scrape your own links.

A category NAME in categories (or a bare name typed where a link is expected) is resolved the same way, against Carrefour's own category names, not a raw id. A name that doesn't match anything is reported in the run log; paste the category's own link instead.

Daily monitoring of the same search:

{
"mode": "search",
"queries": ["leche"],
"incrementalMode": true
}

Run it from your code

Python:

from apify_client import ApifyClient
client = ApifyClient("<YOUR_APIFY_TOKEN>")
run = client.actor("abotapi/carrefour-es-scraper").call(run_input={"mode": "search", "queries": ["leche"]})
for product in client.dataset(run["defaultDatasetId"]).iterate_items():
print(product["name"], product["price"])

JavaScript:

import { ApifyClient } from 'apify-client';
const client = new ApifyClient({ token: '<YOUR_APIFY_TOKEN>' });
const run = await client.actor('abotapi/carrefour-es-scraper').call({ mode: 'search', queries: ['leche'] });
const { items } = await client.dataset(run.defaultDatasetId).listItems();

Or connect it to Make, Zapier, n8n, Google Sheets or webhooks from the Integrations tab.

Resume and recurring updates

  • Resume (resumeFromRunId) continues one specific interrupted or previous run: paste its run id or dataset id, and this run skips products already collected there, returning only the remaining new products. An automatic checkpoint also protects a long run against a platform restart, with no input needed.
  • Incremental mode (incrementalMode) is for scheduling the same search again and again, for example daily. The actor remembers the previous run of that search by itself, so no id needs to be pasted. The first run returns everything as NEW. Later runs return NEW and UPDATED (with changedFields listing what changed); unchanged products are suppressed and not billed unless emitUnchanged is on. Turn on emitExpired to also mark, once a run fully scans the tracked search (not capped by Max products and not a resume), products that vanished as EXPIRED; a product only comes back as REAPPEARED after it was previously marked EXPIRED this way, so with emitExpired left off (the default) REAPPEARED never occurs. Use stateKey to name a monitoring campaign or deliberately share state; leave it empty to let the actor derive one automatically from the search and detail settings.
  • Ignore fields when detecting changes (ignoreFieldsForChanges, incremental mode only) excludes field names from the UPDATED/changedFields decision without ever removing them from the row itself: they're still returned, they just can't flip a product to UPDATED on their own. Two fields are excluded by default, measured on a live double-scrape of the same category ~11 minutes apart: stock (the live inventory count) and the nested offer.units_in_stock (the same number, duplicated inside the raw offer block) both moved on an otherwise-unchanged product, a counter that ticks within minutes rather than a real product change. Nothing else is excluded: images, the offer block's price keys (offer.price, offer.app_price, offer.price_per_unit) and rating/reviewCount were byte-identical across the same double-scrape, so a genuine price or rating change still reports UPDATED. If your own monitored products turn out noisy in some other way, add entries yourself, for example a plain name for a top-level field ("stock", already excluded by default), "parent.child" for one field nested inside another ("offer.price"), "parent.*" for every field nested inside another, or "field[]" for a list field ("images[]"). If you do exclude a stock-type field, inStock (true/false) keeps tracking real stock-outs and restocks for you, since it is a separate field you'd have to exclude on its own.
  • A product page that could not be read. If a scheduled incremental run cannot load a tracked product's page (a connection problem), the product is compared using its listing data plus the page details from the previous run, so it is not reported as UPDATED just because its details went missing. Such a row, when returned, is marked detailCarriedForward: true and is not billed for detail enrichment. A product the store has delisted (its page now redirects) is still reported as changed.
  • Reviews in incremental mode. The nested reviews list (and reviewsFetched) is never compared between runs, because its length follows your Max reviews per product setting: changing that setting must not flag every product as UPDATED. A new customer review still shows up, as a change in reviewCount and usually rating.

Send results into your apps (MCP connectors)

Optionally pipe the scraped products into the apps you already use, via Model Context Protocol (MCP) connectors. This is an extra delivery step after the scrape: the Apify dataset is never changed.

What gets written to the connector: a condensed, human-readable summary of each product, not the full JSON. Each item becomes one entry with a title and its key fields flattened to plain text. The complete record always stays in the Apify dataset.

  1. Authorize a connector once under Apify, Settings, Integrations (Notion, Linear, Airtable, or Apify).
  2. Select it in the "Pipe results into your apps" input field. (If the picker is empty, you haven't authorized a connector yet.)
  3. For Notion, also set notionParentPageUrl to the page where item pages should be created.

The connection is mediated by Apify's MCP proxy, so this actor never sees your third-party credentials. Leave the field empty to skip.

Input Parameters

ParameterTypeDefaultDescription
modestringsearchsearch, category, or url. (product is a hidden legacy alias of url mode, kept only so a Task saved before 2026-07-17 keeps running; new tasks should use url.)
queriesarraynone (prefill: ["leche"])Keywords to search, search mode only. Each is searched separately.
categoriesarraynone (prefill: a category link and a plain name)Carrefour category page links OR plain category names (e.g. leche, Vinos) to browse, category mode only.
urlsarrayone example of every supported shape (same as the prefill)Carrefour Spain product links, bare product ids, category links, promotions links and search-result links to scrape directly, url mode only; see the shapes table above.
productsarraynone (prefill: one example link)Legacy alias, only used when mode = product (a hidden field kept so a Task saved before 2026-07-17 keeps running).
sortBystringrelevanceOrder applied over the collected products: relevance, price low-high/high-low, unit price low-high/high-low, name, top rated first, or promotions first (the last two order the products the run collects, after their product pages are read).
minRatingstring0Keep only products rated at least this many stars. Automatically fetches product details for filtered products.
onPromotionOnlybooleanfalseKeep only products currently on promotion.
inStockOnlybooleanfalseKeep only products currently in stock.
minPriceintegernoneKeep only products priced at or above this amount, in EUR. Never filters out a pasted product link.
maxPriceintegernoneKeep only products priced at or below this amount, in EUR. Never filters out a pasted product link.
brandsarraynoneKeep only products of these brands (exact brand name, not case-sensitive). Never filters out a pasted product link.
fetchDetailsbooleantrueFetch barcode, ingredients, allergens, nutrition, extra images, rating and customer reviews. Off returns listing-level fields only, except pasted product links, which always fetch full detail.
maxReviewsinteger20With details on, the most recent customer reviews nested in each product's reviews list (never separate rows). 0 skips review reads; products without reviews cost no extra request.
maxItemsinteger20Maximum products returned across the whole run. 0 means unlimited.
maxPagesinteger0Maximum result pages walked per keyword, category or link. 0 means unlimited.
resumeFromRunIdstringnoneContinue one specific interrupted run or dataset id, skipping products already collected there.
incrementalModebooleanfalseReturn only new and changed products on repeat runs against the same search.
stateKeystringnoneName or share an incremental-mode monitoring campaign. Derived automatically when left empty.
emitUnchangedbooleanfalseIncremental mode only. Also return, and bill, products unchanged since the last run.
emitExpiredbooleanfalseIncremental mode only. Also return, and bill, products no longer found, once a run has fully scanned the tracked search.
ignoreFieldsForChangesarray[] (empty)Incremental mode only. Field names/paths ("stock", "offer.price", "offer.*", "images[]") excluded from the UPDATED/changedFields decision; the fields themselves are still returned.
proxyobjectSpanish residential ({"useApifyProxy": true, "apifyProxyGroups": ["RESIDENTIAL"], "apifyProxyCountry": "ES"})Connection settings.
mcpConnectorsarraynoneOptional: send a summary of each product to apps you authorized under Integrations.
notionParentPageUrlstringnoneNotion connector only: page under which item pages are created.
maxNotifyListingsinteger50Cap on items written to each connector per run.
searchQuerystringnoneHidden alternative name for queries (one keyword).
searchQueriesarraynoneHidden alternative name for queries.
categoryUrlstringnoneHidden alternative name for categories (one link).
categoryUrlsarraynoneHidden alternative name for categories.
startUrlsarraynoneHidden alternative name for urls.
productUrlsarraynoneHidden alternative name for urls.
maxResultsintegernoneHidden alternative name for maxItems.
maxResultsPerScrapeintegernoneHidden alternative name for maxItems.
promotionsOnlybooleannoneHidden alternative name for onPromotionOnly.
proxyConfigurationobjectnoneHidden alternative name for proxy.

Dataset views

The dataset has an overview view (the key fields at a glance), a full-detail view (every field including nutrition, label data and reviews) and, for incremental runs, a changes view (changeType, changedFields, timestamps).

Output Example

Sample shape: values are illustrative placeholders, not from a live record.

{
"productId": "520661336",
"name": "Leche semidesnatada marca ejemplo brik 1 L",
"brand": "Marca Ejemplo",
"ean": "8400000000000",
"sku": "1895370000",
"price": 0.99,
"regularPrice": 1.19,
"discountPercentage": 17,
"onPromotion": true,
"currency": "EUR",
"unitPrice": 0.99,
"unitPriceMeasure": "l",
"stock": 240,
"inStock": true,
"ingredients": "Leche de vaca semidesnatada.",
"allergens": ["Leche"],
"nutrition": { "main_nutritional_values": [{ "nombre": "ProteΓ­nas (g)", "valor": "3 g" }] },
"rating": 4.5,
"reviewCount": 12,
"reviewsFetched": 1,
"reviews": [
{
"reviewId": "example-review-1",
"rating": 5,
"title": "Muy buena",
"text": "Texto de ejemplo de una opiniΓ³n.",
"date": "2026-01-01T10:00:00.000+01:00",
"reviewerName": "Cliente Ejemplo"
}
],
"image": "https://static.carrefour.es/example/000000.jpg",
"images": ["https://static.carrefour.es/example/000000.jpg"],
"url": "https://www.carrefour.es/supermercado/example/R-520661336/p",
"searchMode": "category",
"source": "category",
"scrapedAt": "2026-01-01T00:00:00Z"
}

Plan Requirement

Carrefour Spain's storefront is protected by an aggressive bot wall that refuses most connections, so this is not a "works with no action needed" actor. It is set up to use a Spanish residential connection by default, and that setting is the best available, but residential access does not guarantee a page: a refused connection is simply retried on a fresh one, and the actor can still end a run with no data when the site refuses every attempt. Datacenter connections are refused outright, so a plan without residential proxy access gets noticeably worse results.

If your Apify plan does not include residential proxy access (free plans), the log shows this once per run:

The selected connection is unavailable to this run. Apify free plans do not include residential proxies. Continuing on a backup connection; some pages may still be unavailable. For residential access, upgrade at https://apify.com/pricing or supply your own proxy URLs.

and, when the backup connection then serves data, an info line: "Served over the backup connection (the default connection was unavailable)." For the most reliable results use a plan with residential proxy access (pricing) or supply your own proxy URLs.

FAQ

How much does it cost?

Pay per event. On the Free tier: $0.0025 per product returned, plus $0.001 per product where full detail was fetched and returned (detail is on by default, so about $3.50 per 1,000 products with details, $2.50 per 1,000 card-only), plus a one-time actor start of $0.02. Paid Apify plans get lower per-event rates (down to $0.0015 and $0.0006). Customer reviews have no separate charge (set Max reviews per product to 0 to skip reading them). The Pricing tab always shows the current rates. Use Max products to cap the cost of any run.

This actor collects only publicly available product data. You are responsible for how you use it: follow Carrefour's terms and the laws that apply to you, and get legal advice if you plan commercial redistribution. Prices and product facts are generally not protected, but product photos and descriptions may be subject to third-party rights.

Can I get only new or changed products on a schedule?

Yes. Schedule the actor from the Schedules tab and turn on Incremental mode. Each run then returns only new and updated products, and unchanged ones are not billed. Products only ever come back marked REAPPEARED if emitExpired was previously turned on and a full scan had already marked them EXPIRED; with emitExpired off, expect only NEW and UPDATED.

What's the difference between Resume and Incremental mode?

Resume (resumeFromRunId) continues one specific interrupted or earlier run, so you paste an id and get the remaining new products from that same crawl. Incremental mode is for scheduling the same search repeatedly and getting only what changed since last time, with the actor tracking state on its own. Use Resume for a one-off continuation; use Incremental mode for recurring monitoring.

Why did my run fail instead of returning an empty dataset?

The run ends FAILED only when no usable page could be loaded at all, because reporting that as an empty dataset would hide a genuine connection problem behind what looks like "no matches." The status message tells you which case you hit:

  • "The proxy connection was refused for this account, so no page could be read. Your Apify plan does not include proxy access; a paid plan is required...": every connection was refused at the proxy itself. Check your plan, or your own proxy URLs if you supplied any.
  • "No results: residential proxies are unavailable on this run (Apify free plans do not include them), and the backup connection could not load the requested Carrefour.es pages...": a free-plan run whose backup connection could not get past the storefront. Upgrade or supply your own proxy URLs.
  • "Could not load any results page (the requests failed), so nothing was collected. This is a connection problem, not an empty search. Please try again later.": the storefront refused every connection this run tried. Retrying later usually works.

Missing residential access by itself does not fail the run (see Plan Requirement); a single product page that could not be read quietly falls back to listing-level fields, while pasted product links that cannot be read are dropped. The run also fails outright for an unreadable resumeFromRunId, for an empty input, or when Incremental mode is combined with Resume on a search that already has saved state. A run that legitimately found no matching products (a narrow keyword, tight filters, or an incremental run with nothing changed) completes normally with a status message explaining why the dataset is empty.

Can I use it with AI agents or MCP?

Yes. Call it from any Apify integration or MCP client, and use the connector field to push results into Notion, Linear or Airtable.

πŸ”— Want more grocery data?

Pair this actor with these related scrapers from the same team:

πŸ₯¦ Mercadona Scraper
Scrape Mercadona products by delivery-area postal code. Search by keyword or category, or...
πŸ₯¦ Woolworths AU Scraper
Scrape Woolworths Australia (woolworths.com.au) grocery products and reviews. Search by...
πŸ₯¦ Coles AU Scraper
Scrape Coles.com.au grocery products and customer reviews. Search by keyword, browse...
πŸ₯¦ Lidl.es Products, Weekly Offers, Prices & Reviews Scraper
Scrape Lidl.es grocery and non-food products across weekly offers, tools, home, garden...
πŸ₯¦ E.Leclerc Scraper
Scrape E.Leclerc France (e.leclerc) grocery and retail products. Search by keyword or...
πŸ₯¦ FoodHero Scraper
Scrape FoodHero surplus grocery deals across Canada by area, store or offer ID. Extract...

πŸ‘‰ Browse all abotapi scrapers

πŸ’¬ Support & custom scrapers

  • 🐞 Found a bug or a missing field? Open a ticket on the Issues tab. We usually reply within hours.
  • πŸ› οΈ Need another site, extra fields or a private build? Email contact@abotapi.com or message Telegram @abotapi.
  • ⭐ Enjoying it? A quick review on the actor page helps other users find it.