# Tesco Product Scraper (`sian.agency/tesco-product-scraper`) Actor

Scrape Tesco groceries — price, unit price, Clubcard offers, nutrition, ingredients & allergens. Keyword or aisle search, detail enrichment, clean JSON/CSV, no code.

- **URL**: https://apify.com/sian.agency/tesco-product-scraper.md
- **Developed by:** [SIÁN OÜ](https://apify.com/sian.agency) (community)
- **Categories:** E-commerce, Business
- **Stats:** 3 total users, 2 monthly users, 100.0% runs succeeded, 0 bookmarks
- **User rating**: No ratings yet

## Pricing

from $2.60 / 1,000 overview product extracteds

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/docs.md):

```bash
npm install apify-client
```

In Python projects, use official [Python client library](https://docs.apify.com/api/client/python/docs.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/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

## Tesco Product Scraper — Prices, Clubcard, Nutrition & Allergens to JSON/CSV 🚀

[![SIÁN Agency Store](https://img.shields.io/badge/Store-SI%C3%81N%20Agency-1AE392)](https://apify.com/sian.agency?fpr=sian) [![Walmart Data Scraper](https://img.shields.io/badge/Store-Walmart%20Data%20Scraper-0071CE)](https://apify.com/sian.agency/walmart-data-scraper?fpr=sian) [![Amazon Product Scraper](https://img.shields.io/badge/Store-Amazon%20Product%20Scraper-FF9900)](https://apify.com/sian.agency/amazon-product-scraper?fpr=sian) [![Google Shopping Price Scraper](https://img.shields.io/badge/Store-Google%20Shopping%20Price%20Scraper-4285F4)](https://apify.com/sian.agency/google-shopping-price-scraper?fpr=sian)

#### 🎉 Turn any Tesco search, aisle, or product page into a clean dataset — prices, Clubcard offers, unit prices, ratings, and full nutrition, ingredients & allergens in a single run.
##### Perfect for grocery price analysts, comparison sites, nutrition-app builders, and range researchers who need reliable Tesco data without lifting a finger.

---

### 📋 Overview

**The Tesco Product Scraper turns tesco.com/groceries into structured data in seconds.** Search by keyword, browse an aisle, or paste Tesco product URLs, and get a clean JSON/CSV dataset with one row per product — prices, Clubcard offers, unit prices, ratings, availability, and complete nutrition, ingredients, and allergens.

No account, no API key, no setup. Just enter what you want, click Run, and download export-ready data for grocery price monitoring, nutrition feeds, and range research.

**Why professionals choose us:**
- ✅ **Zero Setup**: No Tesco account or API key — enter keywords and go
- ⚡ **Fast Overview Mode**: Pull search and aisle results at scale — id, title, price, unit price, Clubcard price, rating, and availability
- 🏷️ **Clubcard & Unit Price Built In**: Capture Clubcard/offer prices, promotion text, and unit prices (£/kg, £/litre, £/100g) for true like-for-like comparison
- 🥗 **Deep Detail Mode**: Enrich every product with full nutrition tables, ingredients, allergens, storage, pack size, brand, and the complete image gallery
- 💰 **Pay-Per-Result Pricing**: Only pay for products you actually extract — plus a free tier to test risk-free
- 💎 **One Clean Record Per Product**: Overview and detail are merged into a single row — no stitching, no duplicates
- ✨ **NEW: Dietary Filters**: Filter by Vegan, No gluten, Organic, Vegetarian, Halal, and Kosher to build focused catalogs

---

### ✨ Features

- 🔍 **Keyword & Aisle Search**: Find products by free-text search or by Tesco aisle/browse paths
- 🔗 **Paste Tesco URLs**: Drop in any tesco.com/groceries search, aisle, or product URL and scrape it directly
- ⚡ **Overview Mode**: Fast results extraction — product id, title, price, unit price, Clubcard price, promotion text, image, availability, and taxonomy (super-department → department → aisle → shelf)
- 🥗 **Detail Mode**: Full nutrition table, ingredients, allergens, storage instructions, pack size, brand, manufacturer, dietary icons, and complete image gallery
- 🏷️ **Clubcard & Promotions**: Clubcard/offer price, promotion text, and on-offer flag for every product
- 📏 **Unit Price Comparison**: £/kg, £/litre, £/100g and unit of measure for true value-for-money analysis
- ⭐ **Ratings & Reviews**: Star rating and total review count for every product
- 📦 **Availability Intelligence**: In-stock status and availability for stock and range checks
- 🥦 **Dietary Filters**: Vegan, No gluten, Organic, Vegetarian, Halal, and Kosher filtering
- 🎚️ **Sorting & Filters**: Relevance, Price low→high, Price high→low — plus brand, min/max price, on-offer, and new-products filters
- 💾 **Clean JSON & CSV**: Export-ready dataset with one row per product, priced in GBP (£)

---

### 🎬 Quick Start

Enter keywords, aisle paths, or Tesco URLs, pick a mode, and click Run. Results land in your dataset ready to export.

```bash
## Run via API - one line
curl -X POST https://api.apify.com/v2/acts/sian.agency~tesco-product-scraper/runs?token=[YOUR_TOKEN] \
-d '{"queries": ["milk"], "scrapeMode": "overview"}'
````

***

### 🚀 Getting Started (3 Simple Steps)

#### Step 1: Tell It What to Scrape

Enter search keywords (e.g. `milk`, `coffee`, `pasta`), add Tesco aisle/browse paths, or paste tesco.com/groceries URLs. Mix and match as needed.

#### Step 2: Choose Mode & Filters

Pick **Overview** (fast search and aisle data) or **Detail** (enriched with nutrition, ingredients, and allergens). Optionally set a sort order, brand, min/max price, on-offer, new-products, or dietary filters (Vegan, No gluten, Organic, Vegetarian, Halal, Kosher).

#### Step 3: Run & Download

Click Run and download clean, structured data as JSON, CSV, or Excel — ready for spreadsheets, databases, and analytics tools.

**That's it! In minutes, you'll have:**

- Live prices, Clubcard/offer prices, promotion text, and unit prices (£/kg, £/litre)
- Ratings, review counts, images, and availability for every product
- Full nutrition tables, ingredients, allergens, storage, and pack size (detail mode)
- Clean export-ready data priced in GBP, one row per product

***

### 📥 Input Configuration

| Field | Type | Required | Description |
|-------|------|----------|-------------|
| queries | array | No | Free-text Tesco searches (e.g. `"milk"`, `"coffee"`) |
| browsePaths | array | No | Tesco aisle / browse paths to scrape (e.g. `"drinks/coffee"`) |
| urls | array | No | Tesco search, aisle, or product URLs to scrape directly |
| scrapeMode | string | No | `overview` (fast) or `detail` (nutrition, ingredients, allergens) |
| sort | string | No | Relevance, Price low→high, Price high→low |
| brand | string | No | Limit results to a single brand |
| dietary | string | No | A single Tesco dietary facet — Vegan, No gluten, Organic, Vegetarian, Halal, or Kosher |
| minPrice | number | No | Minimum price band (GBP) |
| maxPrice | number | No | Maximum price band (GBP) |
| onOffer | boolean | No | Only return products on offer / with a Clubcard price |
| newProducts | boolean | No | Only return newly added products |
| maxResults | integer | No | Maximum number of products to return |

**Example — keyword search, detail mode:**

```json
{
  "queries": ["coffee"],
  "scrapeMode": "detail",
  "sort": "price_low",
  "dietary": "Vegan",
  "minPrice": 2,
  "maxPrice": 8,
  "onOffer": true,
  "maxResults": 100
}
```

**Example — scrape aisle paths and URLs:**

```json
{
  "browsePaths": ["fresh-food/fresh-milk"],
  "urls": [
    "https://www.tesco.com/groceries/en-GB/search?query=oat%20milk"
  ],
  "scrapeMode": "overview"
}
```

***

### 📤 Output

Results are saved to the Apify dataset with **30+ fields per product**, one clean row each. In detail mode, the overview row is enriched in place with nutrition, ingredients, allergens, and the full gallery — no separate records to merge.

| Field | Type | Description |
|-------|------|-------------|
| tpnc | string | Tesco product number (unique product ID) |
| productTitle | string | Full product name |
| brand | string | Brand name |
| price | number | Current price (GBP) |
| unit\_price | number | Price per unit of measure (e.g. £/kg, £/litre, £/100g) |
| unit\_of\_measure | string | Unit the unit price is based on (kg, litre, 100g, each) |
| clubcard\_price | number | Clubcard / offer price (GBP) |
| promotion\_text | string | Promotion / offer description |
| rating | number | Average star rating |
| review\_count | number | Total number of reviews |
| in\_stock | boolean | Whether the product is currently in stock |
| pack\_size | string | Pack / product size (e.g. `200g`, `4 pints`) |
| nutrition | array | Nutrition rows — each `{ name, values[] }` (energy, fat, carbs, protein, salt…) (detail) |
| ingredients | array | Full ingredients list (detail) |
| allergens | array | Declared allergens (detail) |
| dietary\_icons | array | Dietary / food icons (Vegan, Red Tractor, etc.) (detail) |
| images | array | Full product image gallery (detail) |

**Full example (detail mode):**

```json
{
  "thumbnail": "https://digitalcontent.api.tesco.com/v2/media/ghs/image.jpg",
  "tpnc": "254656242",
  "tpnb": "81496284",
  "productTitle": "Nescafe Gold Blend Instant Coffee 200G",
  "url": "https://www.tesco.com/groceries/en-GB/products/254656242",
  "source": "detail",
  "brand": "Nescafe",
  "manufacturer": "Nestlé UK Ltd, Haxby Road, York, YO91 1XY",
  "price": 6.00,
  "unit_price": 3.00,
  "unit_of_measure": "100g",
  "currency": "GBP",
  "clubcard_price": 5.00,
  "promotion_text": "Clubcard Price £5.00 until 21 Jul",
  "on_offer": true,
  "rating": 4.6,
  "review_count": 1893,
  "in_stock": true,
  "availability": "AvailableForSale",
  "pack_size": "200g",
  "super_department": "Drinks",
  "department": "Coffee",
  "aisle": "Instant Coffee",
  "shelf": "Instant Coffee Granules",
  "dietary_icons": ["Vegetarian"],
  "nutrition": [
    { "name": "Typical Values", "values": ["Per 100g"] },
    { "name": "Energy", "values": ["1470kJ/346kcal"] },
    { "name": "Fat", "values": ["0.5g"] },
    { "name": "Carbohydrate", "values": ["10.0g"] },
    { "name": "Protein", "values": ["14.0g"] },
    { "name": "Salt", "values": ["0.10g"] }
  ],
  "ingredients": ["Coffee", "Decaffeinated using a water process"],
  "allergens": ["May contain: Milk"],
  "storage": ["Store in a cool, dry place. Reseal after use."],
  "images": [
    "https://digitalcontent.api.tesco.com/v2/media/ghs/1.jpg",
    "https://digitalcontent.api.tesco.com/v2/media/ghs/2.jpg"
  ],
  "metadata": { "scrapedAt": "2026-07-14T10:30:00.000Z" }
}
```

***

### 💼 Use Cases & Examples

#### 1. Grocery Price & Clubcard Monitoring

**Retail and pricing teams tracking Tesco prices, Clubcard offers, and promotions over time.**

**Input:** Keywords or aisle paths for your product lines
**Output:** Current price, Clubcard/offer price, promotion text, and on-offer flag
**Use:** Detect price drops and Clubcard deals the moment they go live and react faster.

#### 2. Unit-Price & Value Comparison

**Comparison sites and analysts benchmarking value across brands and pack sizes.**

**Input:** Keywords or aisle paths for a category (e.g. `coffee`, `washing powder`)
**Output:** Unit price (£/kg, £/litre, £/100g), unit of measure, and pack size per product
**Use:** Rank products by true value-for-money regardless of pack size.

#### 3. Product & Assortment Research

**Category managers mapping what Tesco carries in a niche.**

**Input:** Aisle/browse paths or URLs, overview mode
**Output:** Full product lists with id, brand, price, rating, and taxonomy (super-department → shelf)
**Use:** Understand range breadth, brand mix, and price distribution at a glance.

#### 4. Nutrition & Allergen Data Extraction

**App, feed, and health-tech teams building nutrition and allergen databases.**

**Input:** Product URLs or keywords, detail mode
**Output:** Full nutrition tables, ingredients, allergens, storage, and pack size
**Use:** Populate nutrition apps, meal planners, and food databases with accurate label data.

#### 5. Dietary Catalog Building

**Teams building Vegan, gluten-free, or organic product catalogs.**

**Input:** Keywords or aisle paths with dietary filters (Vegan, No gluten, Organic, Vegetarian, Halal, Kosher)
**Output:** Filtered product lists with dietary icons, ingredients, and allergens
**Use:** Build focused specialty-diet catalogs and product feeds without manual curation.

#### 6. Stock & Availability Checks

**Resellers, meal-kit, and delivery teams monitoring what's available.**

**Input:** Keywords or URLs for the products you source
**Output:** In-stock status and availability for every product
**Use:** Only list what's actually available and avoid disappointing customers.

***

### 🔗 Integration Examples

#### JavaScript/Node.js

```javascript
import { ApifyClient } from 'apify-client';
const client = new ApifyClient({ token: 'YOUR_TOKEN' });

const run = await client.actor('sian.agency/tesco-product-scraper').call({
  queries: ['coffee'],
  scrapeMode: 'detail',
  maxResults: 100
});

const { items } = await client.dataset(run.defaultDatasetId).listItems();
console.log(items[0]);
```

#### Python

```python
from apify_client import ApifyClient
client = ApifyClient('YOUR_TOKEN')

run = client.actor('sian.agency/tesco-product-scraper').call(
    run_input={'queries': ['coffee'], 'scrapeMode': 'detail'}
)

for item in client.dataset(run['defaultDatasetId']).iterate_items():
    print(item)
```

#### cURL

```bash
curl -X POST 'https://api.apify.com/v2/acts/sian.agency~tesco-product-scraper/runs?token=YOUR_TOKEN' \
-H 'Content-Type: application/json' \
-d '{"queries": ["coffee"], "scrapeMode": "detail"}'
```

#### Automation Workflows (N8N / Zapier / Make)

1. **Trigger**: Schedule or webhook
2. **HTTP Request**: Call the actor API
3. **Process**: Handle the JSON product results
4. **Action**: Save to a database, update a pricing sheet, or send an alert

***

### 📊 Performance & Pricing

#### FREE Tier (Try It Now)

- **Up to 25 products** per run — full feature access, same data quality
- No credit card required
- Perfect for testing keywords, aisles, and detail mode

#### PAID Tier (Production Ready)

- **Unlimited** products per run
- Faster, at-scale extraction with no caps
- **Pay-per-result**: you're only charged for products that are successfully extracted

💰 **Fair, transparent pricing** — pay for the products you get, nothing more.

🔗 [View current pricing](https://apify.com/sian.agency/tesco-product-scraper?fpr=sian)

***

### ❓ Frequently Asked Questions

**Q: How many products can I scrape?**
A: FREE tier: up to 25 products per run. PAID tier: unlimited.

**Q: Do I need a Tesco account or API key?**
A: No. There's nothing to sign up for or configure — just enter keywords, aisle paths, or URLs and run.

**Q: What's the difference between Overview and Detail mode?**
A: Overview is the fast path — search and aisle data like product id, title, price, unit price, Clubcard price, promotion text, rating, and availability. Detail enriches each product with the full nutrition table, ingredients, allergens, storage instructions, pack size, brand, manufacturer, dietary icons, and complete image gallery.

**Q: Do you capture Clubcard prices and unit prices?**
A: Yes — every product includes the Clubcard/offer price, promotion text, and the unit price (£/kg, £/litre, £/100g) alongside the standard price.

**Q: Can I filter and sort results?**
A: Yes — sort by Relevance, Price low→high, or Price high→low, and filter by brand, min/max price, on-offer, new products, and dietary (Vegan, No gluten, Organic, Vegetarian, Halal, Kosher).

**Q: What output formats are available?**
A: JSON, CSV, and Excel — export directly from the Apify dataset.

**Q: Which region and currency does it cover?**
A: The UK storefront (tesco.com/groceries), with prices in GBP (£).

**Q: Is this legal?**
A: Yes — the actor accesses only publicly available data. See the [legal section](#-is-it-legal-to-scrape-data) below.

***

### 🐛 Troubleshooting

**No results returned**

- Check keyword spelling and try broader terms (e.g. `coffee` instead of an exact product)
- Remove or widen filters (brand, min/max price, on-offer, dietary)
- Verify any Tesco URLs open correctly in a browser

**Nutrition, ingredients, or allergens are missing**

- Switch `scrapeMode` to `detail` — full nutrition tables, ingredients, allergens, and galleries are only extracted in detail mode

**Fewer products than expected**

- FREE tier is capped at 25 products per run — upgrade to PAID for unlimited results
- Some aisles or filtered searches simply contain fewer products

**Prices look different from what I expect**

- Results reflect the UK storefront (tesco.com/groceries) in GBP; Clubcard prices require the promotion to be live, and prices may differ from in-store

***

### ⚖️ Is it legal to scrape data?

Our actors are ethical and do not extract any private user data, such as email addresses, gender, or location. They only extract what is publicly available. We therefore believe that our actors, when used for ethical purposes by Apify users, are safe.

However, you should be aware that your results could contain personal data (for example, reviewer names). Personal data is protected by the **GDPR** in the European Union and by other regulations around the world. You should not scrape personal data unless you have a legitimate reason to do so. If you're unsure whether your reason is legitimate, consult your lawyers.

You can also read Apify's blog post on the [legality of web scraping](https://blog.apify.com/is-web-scraping-legal/).

**Trademark & affiliation disclaimer:** SIÁN Agency is an independent provider and is **not affiliated with, endorsed by, or sponsored by Tesco**. "Tesco", "Clubcard" and related names, marks, and logos are trademarks of their respective owner. This actor is not an official Tesco product or service and accesses only publicly available data.

***

### 🤝 Support

[![Telegram Support](https://img.shields.io/badge/Telegram-Support%20Group-0088cc?logo=telegram)](https://t.me/+vyh1sRE08sAxMGRi)

**Join our active support community**

- For issues or questions, open an issue in the actor's repository
- Check the [SIÁN Agency Store](https://apify.com/sian.agency?fpr=sian) for more automation tools
- ✉️ <apify@sian-agency.online>

***

**Built by [SIÁN Agency](https://www.sian-agency.online)** | **[More Tools](https://apify.com/sian.agency?fpr=sian)**

# Actor input Schema

## `queries` (type: `array`):

🔍 **KEYWORD SEARCH:** Free-text Tesco grocery searches — exactly what you'd type into the tesco.com/groceries search bar.

📝 **EXAMPLES:** `milk` · `bread` · `coffee` · `cheddar cheese` · `bananas`

💡 **TIP:** Add one search per line — each runs as its own search and all results land in the same dataset.

🖊️ **BULK EDIT:** Click "Bulk edit" to paste many searches at once (one per line).

✅ **IMPORTANT:** Provide either searches, aisle paths, OR Tesco URLs (at least one is needed to have something to scrape).

## `scrapeMode` (type: `string`):

⚙️ **SCRAPE DEPTH:** Choose how much data to pull per product.

⚡ **Overview (fast):** Search / aisle cards only — tpnc, title, price, unit price, Clubcard price, image, availability, taxonomy and rating. Fastest and cheapest path.

🔬 **Detail (nutrition + ingredients + allergens):** Everything in Overview PLUS nutrition tables, ingredients, allergen statements, storage instructions, pack size, the full image gallery, brand, manufacturer and dietary icons scraped from each product page.

💡 **TIP:** Start with Overview to scope your catalog, then switch to Detail when you need the full nutrition and ingredient data for feeds or compliance.

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

🔃 **RESULT ORDERING:** Order search results using Tesco's own native sort options — so you get the same ranking real shoppers see.

⭐ **Relevance** surfaces the best-matching products first · 💲 **Price** sorts ascending or descending.

## `brand` (type: `string`):

™️ **BRAND FILTER:** Restrict results to a single brand (e.g. `Arla`, `Cravendale`, `Tesco`, `Yeo Valley`). Uses Tesco's own brand facet, so it mirrors the site's brand filter.

💡 **TIP:** Leave blank to include every brand.

## `dietary` (type: `string`):

🥗 **LIFESTYLE & DIETARY FILTER:** Restrict results to Tesco's "Lifestyle & Dietary" facet — e.g. `Vegan`, `No gluten`, `Organic`, `Vegetarian`, `Halal`, `Kosher`.

💡 **TIP:** Leave blank to include everything.

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

💵 **MINIMUM PRICE:** Only return products at or above this price (GBP). Leave blank for no lower bound.

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

💰 **MAXIMUM PRICE:** Only return products at or below this price (GBP). Leave blank for no upper bound.

## `onOffer` (type: `boolean`):

🔥 **ON OFFER ONLY:** When on, limits results to products currently on a promotion or Clubcard Price.

## `newProducts` (type: `boolean`):

🆕 **NEW PRODUCTS ONLY:** When on, limits results to products Tesco flags as new.

## `browsePaths` (type: `array`):

🧭 **AISLE BROWSING (Advanced):** Scrape a whole Tesco aisle instead of a keyword search.

🔧 **HOW TO GET IT:** Open any Tesco groceries aisle page and copy the taxonomy tail from the URL (e.g. `fresh-food/milk-butter-and-eggs/milk/all`).

💡 **TIP:** Leave this empty if you're only using searches — it's purely an advanced alternative for aisle-level harvesting.

🖊️ **BULK EDIT:** Add one aisle path per line to sweep multiple aisles in a single run.

## `urls` (type: `array`):

🔗 **PASTE RESULT-PAGE URLs:** Paste full Tesco search or aisle result-page URLs to scrape them verbatim — filters and sorting you already set in the URL are preserved.

📝 **EXAMPLE:** `https://www.tesco.com/groceries/en-GB/search?query=milk`

🖊️ **BULK EDIT:** Add one URL per line to sweep several pages in a single run.

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

🔢 **RESULT CAP:** Maximum number of products to return across all searches, aisle paths and URLs combined.

🎁 **TIER-BASED LIMITS:**

- **FREE users:** Up to 25 products per run
- **PAID users:** Unlimited — scrape entire catalogs in a single run

💡 **TIP:** Keep this low while you dial in your searches, then raise it once the output looks right.

## Actor input object example

```json
{
  "queries": [
    "milk"
  ],
  "scrapeMode": "overview",
  "sort": "relevance",
  "onOffer": false,
  "newProducts": false,
  "maxResults": 100
}
```

# Actor output Schema

## `tescoProducts` (type: `string`):

Scraped Tesco grocery products with prices, Clubcard offers, unit prices, ratings, images, nutrition and availability.

# 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 = {
    "queries": [
        "milk"
    ]
};

// Run the Actor and wait for it to finish
const run = await client.actor("sian.agency/tesco-product-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 = { "queries": ["milk"] }

# Run the Actor and wait for it to finish
run = client.actor("sian.agency/tesco-product-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 '{
  "queries": [
    "milk"
  ]
}' |
apify call sian.agency/tesco-product-scraper --silent --output-dataset

```

## MCP server setup

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

```

## OpenAPI specification

```json
{
    "openapi": "3.0.1",
    "info": {
        "title": "Tesco Product Scraper",
        "description": "Scrape Tesco groceries — price, unit price, Clubcard offers, nutrition, ingredients & allergens. Keyword or aisle search, detail enrichment, clean JSON/CSV, no code.",
        "version": "1.0",
        "x-build-id": "lfZbINmbX1TdgR3GV"
    },
    "servers": [
        {
            "url": "https://api.apify.com/v2"
        }
    ],
    "paths": {
        "/acts/sian.agency~tesco-product-scraper/run-sync-get-dataset-items": {
            "post": {
                "operationId": "run-sync-get-dataset-items-sian.agency-tesco-product-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/sian.agency~tesco-product-scraper/runs": {
            "post": {
                "operationId": "runs-sync-sian.agency-tesco-product-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/sian.agency~tesco-product-scraper/run-sync": {
            "post": {
                "operationId": "run-sync-sian.agency-tesco-product-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": {
                    "queries": {
                        "title": "🔍 Search Queries",
                        "type": "array",
                        "description": "🔍 **KEYWORD SEARCH:** Free-text Tesco grocery searches — exactly what you'd type into the tesco.com/groceries search bar.\n\n📝 **EXAMPLES:** `milk` · `bread` · `coffee` · `cheddar cheese` · `bananas`\n\n💡 **TIP:** Add one search per line — each runs as its own search and all results land in the same dataset.\n\n🖊️ **BULK EDIT:** Click \"Bulk edit\" to paste many searches at once (one per line).\n\n✅ **IMPORTANT:** Provide either searches, aisle paths, OR Tesco URLs (at least one is needed to have something to scrape).",
                        "default": [
                            "milk"
                        ],
                        "items": {
                            "type": "string"
                        }
                    },
                    "scrapeMode": {
                        "title": "⚙️ Scrape Mode",
                        "enum": [
                            "overview",
                            "detail"
                        ],
                        "type": "string",
                        "description": "⚙️ **SCRAPE DEPTH:** Choose how much data to pull per product.\n\n⚡ **Overview (fast):** Search / aisle cards only — tpnc, title, price, unit price, Clubcard price, image, availability, taxonomy and rating. Fastest and cheapest path.\n\n🔬 **Detail (nutrition + ingredients + allergens):** Everything in Overview PLUS nutrition tables, ingredients, allergen statements, storage instructions, pack size, the full image gallery, brand, manufacturer and dietary icons scraped from each product page.\n\n💡 **TIP:** Start with Overview to scope your catalog, then switch to Detail when you need the full nutrition and ingredient data for feeds or compliance.",
                        "default": "overview"
                    },
                    "sort": {
                        "title": "🔃 Sort Order",
                        "enum": [
                            "relevance",
                            "price_low",
                            "price_high"
                        ],
                        "type": "string",
                        "description": "🔃 **RESULT ORDERING:** Order search results using Tesco's own native sort options — so you get the same ranking real shoppers see.\n\n⭐ **Relevance** surfaces the best-matching products first · 💲 **Price** sorts ascending or descending.",
                        "default": "relevance"
                    },
                    "brand": {
                        "title": "™️ Brand Filter",
                        "type": "string",
                        "description": "™️ **BRAND FILTER:** Restrict results to a single brand (e.g. `Arla`, `Cravendale`, `Tesco`, `Yeo Valley`). Uses Tesco's own brand facet, so it mirrors the site's brand filter.\n\n💡 **TIP:** Leave blank to include every brand."
                    },
                    "dietary": {
                        "title": "🥗 Lifestyle & Dietary Filter",
                        "type": "string",
                        "description": "🥗 **LIFESTYLE & DIETARY FILTER:** Restrict results to Tesco's \"Lifestyle & Dietary\" facet — e.g. `Vegan`, `No gluten`, `Organic`, `Vegetarian`, `Halal`, `Kosher`.\n\n💡 **TIP:** Leave blank to include everything."
                    },
                    "minPrice": {
                        "title": "💵 Min Price (GBP)",
                        "minimum": 0,
                        "type": "integer",
                        "description": "💵 **MINIMUM PRICE:** Only return products at or above this price (GBP). Leave blank for no lower bound."
                    },
                    "maxPrice": {
                        "title": "💰 Max Price (GBP)",
                        "minimum": 0,
                        "type": "integer",
                        "description": "💰 **MAXIMUM PRICE:** Only return products at or below this price (GBP). Leave blank for no upper bound."
                    },
                    "onOffer": {
                        "title": "🔥 On Offer Only",
                        "type": "boolean",
                        "description": "🔥 **ON OFFER ONLY:** When on, limits results to products currently on a promotion or Clubcard Price.",
                        "default": false
                    },
                    "newProducts": {
                        "title": "🆕 New Products Only",
                        "type": "boolean",
                        "description": "🆕 **NEW PRODUCTS ONLY:** When on, limits results to products Tesco flags as new.",
                        "default": false
                    },
                    "browsePaths": {
                        "title": "🧭 Aisle Paths (Advanced)",
                        "type": "array",
                        "description": "🧭 **AISLE BROWSING (Advanced):** Scrape a whole Tesco aisle instead of a keyword search.\n\n🔧 **HOW TO GET IT:** Open any Tesco groceries aisle page and copy the taxonomy tail from the URL (e.g. `fresh-food/milk-butter-and-eggs/milk/all`).\n\n💡 **TIP:** Leave this empty if you're only using searches — it's purely an advanced alternative for aisle-level harvesting.\n\n🖊️ **BULK EDIT:** Add one aisle path per line to sweep multiple aisles in a single run.",
                        "items": {
                            "type": "string"
                        }
                    },
                    "urls": {
                        "title": "🔗 Tesco URLs (Advanced)",
                        "type": "array",
                        "description": "🔗 **PASTE RESULT-PAGE URLs:** Paste full Tesco search or aisle result-page URLs to scrape them verbatim — filters and sorting you already set in the URL are preserved.\n\n📝 **EXAMPLE:** `https://www.tesco.com/groceries/en-GB/search?query=milk`\n\n🖊️ **BULK EDIT:** Add one URL per line to sweep several pages in a single run.",
                        "items": {
                            "type": "string"
                        }
                    },
                    "maxResults": {
                        "title": "🔢 Max Results",
                        "minimum": 1,
                        "type": "integer",
                        "description": "🔢 **RESULT CAP:** Maximum number of products to return across all searches, aisle paths and URLs combined.\n\n🎁 **TIER-BASED LIMITS:**\n- **FREE users:** Up to 25 products per run\n- **PAID users:** Unlimited — scrape entire catalogs in a single run\n\n💡 **TIP:** Keep this low while you dial in your searches, then raise it once the output looks right.",
                        "default": 100
                    }
                }
            },
            "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
                                    }
                                }
                            }
                        }
                    }
                }
            }
        }
    }
}
```
