# John Lewis (`datasaurus/john-lewis`) Actor

Scrape John Lewis UK catalogue products, variants, specifications, availability, energy data, and optional reviews.

- **URL**: https://apify.com/datasaurus/john-lewis.md
- **Developed by:** [datasaurus](https://apify.com/datasaurus) (community)
- **Stats:** 2 total users, 1 monthly users, 100.0% runs succeeded, 0 bookmarks
- **User rating**: No ratings yet

## Pricing

from $4.00 / 1,000 product-details

This Actor is paid per event. You are not charged for the Apify platform usage, but only a fixed price for specific events.
Since this Actor supports Apify Store discounts, the price gets lower the higher subscription plan you have.

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

## What's an Apify Actor?

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

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

## How to integrate an Actor?

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

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

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

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

# README

## John Lewis Product and Reviews Scraper

Scrape John Lewis UK products, prices, availability, specifications, colour variants, and customer reviews into structured data with this Apify Actor. Start from category listings or individual product URLs to collect catalogue data for price monitoring, product research, competitor analysis, and AI workflows.

### Supported Sites

| Storefront | Domain | Category listings | Product details | Customer reviews |
|------------|--------|-------------------|-----------------|------------------|
| United Kingdom | `www.johnlewis.com` | Yes, with pagination | Yes, including variants | Yes, optional |

Results use the UK market (`GB`), English (`en-GB`), and prices in pounds sterling (`GBP`).

### Features

- **Category scraping** — collect products from John Lewis category and filtered listing URLs, following pagination automatically.
- **Product details** — collect descriptions, specifications, images, barcodes, and energy information where available.
- **Prices and availability** — capture the selected SKU's price, currency, colour, and online ordering status.
- **Product variants** — retain the returned colour variants, SKU IDs, prices, images, and variant specifications.
- **Customer reviews** — collect the newest reviews with ratings, text, reviewer details, and source-provided replies or comments with author details.
- **Readable specifications** — product and variant attributes are key-value objects; multiple values are joined with commas.
- **Consistent results** — listing and detail records use the same field names, with one row per unique product model.
- **Pay-per-event pricing** — charge for saved product results, with configurable product and review limits.

### Input

| Field | Type | Default | Description |
|-------|------|---------|-------------|
| `startUrls` | array | Required | Non-empty list of John Lewis category or product URLs, normally as objects containing `url`. |
| `scrapeProductDetails` | boolean | `true` | Fetch product pages for full descriptions, variants, and specifications. Set to `false` for faster listing-only results. |
| `maxProducts` | integer | `4` | Maximum unique product models across all start URLs. Range: **1–10,000**. Variants do not count as separate products. |
| `maxReviews` | integer | `0` | Maximum newest reviews per product. Range: **0–1,000**. `0` disables review requests; reviews can be collected in either scraping mode. |

#### Example Input: Kettle Category with Reviews

```json
{
  "startUrls": [
    {
      "url": "https://www.johnlewis.com/browse/electricals/kettles/cordless/_/N-ahtZlmug?fi=c"
    }
  ],
  "scrapeProductDetails": true,
  "maxProducts": 2,
  "maxReviews": 5
}
```

#### Example Start URLs

| URL type | Example |
|----------|---------|
| Category | `https://www.johnlewis.com/browse/electricals/kettles/_/N-aht` |
| Filtered category | `https://www.johnlewis.com/browse/electricals/kettles/cordless/_/N-ahtZlmug?fi=c` |
| Product | `https://www.johnlewis.com/smeg-klf03-electric-kettle-1-7l/p3310302` |
| Specific colour | `https://www.johnlewis.com/smeg-klf03-electric-kettle-1-7l/black/p3310302` |

Use a specific colour URL to request that variant. Category scraping uses the listing's default variant where available. Start with category or product URLs; whole-site discovery from the homepage is not supported.

### Output Fields

Each dataset row represents one unique product model identified by `productId`. Top-level SKU fields describe the selected variant; `variants` contains the returned variants for that model. Fields are included when available from the source.

| Data | Fields | Description |
|------|--------|-------------|
| Product identity | `productId`, `skuId`, `variantId`, `displayCode`, `name`, `brand`, `link` | Product model, selected SKU, and product URL. |
| Pricing | `price`, `minPrice`, `maxPrice`, `rrp`, `currency` | Selected price and source-provided ranges or reference prices. Equal minimum and maximum prices are omitted when redundant. |
| Availability | `availableToOrder`, `inStock`, `colour` | Online ordering signals and selected colour; not physical inventory counts. |
| Images | `imageUrl`, `images` | Main image and additional source images. |
| Catalogue | `description`, `productType`, `category`, `categoryUrls`, `breadcrumbs` | Product content and category context. |
| Specifications | `attributes`, `barcodes`, `energyRating`, `energyLabel`, `energyInformationSheet` | Readable specifications, identifiers, and energy documents when present. |
| Variants | `variants` | Returned SKU variants with their own prices, colours, availability, images, and attributes. |
| Ratings and reviews | `averageRating`, `reviewCount`, `reviewSummary`, `reviews` | Source ratings and optionally collected review items. |
| Market and provenance | `market`, `locale`, `sourceLanguage`, `retrievedAt`, `dataSource` | Storefront, retrieval timestamp, and `categoryListing` or `productDetail` source. |

Product and variant `attributes` use display names as keys, falling back to source keys. For example, `"Filter feature": "Removable, Washable"`. Attribute help text is omitted. Variant-specific values stay with their variant.

When enabled, `reviews.items` includes review IDs, ratings, titles, text, dates, reviewer usernames and locations, verification tags, helpfulness feedback, media, and other details returned by the API. Replies or comments retain their nested author information when provided. Missing reviewer or reply details are not invented. Reviews belong to the product model and may discuss a different colour from the selected SKU.

#### Example Output: Smeg KLF03 Kettle

This is a shortened excerpt of a saved kettle result, showing the selected black SKU, one variant, and one review. Other fields, variants, and reviews have been omitted for readability. Prices and availability reflect that saved result and can change. This example's reviews did not contain replies.

```json
{
  "productId": "3310302",
  "skuId": "237091061",
  "variantId": "6e880cc1-a7a1-5a3a-91da-dc5dcae4fa14",
  "displayCode": "85550406",
  "name": "Smeg KLF03 Electric Kettle, 1.7L",
  "link": "https://www.johnlewis.com/smeg-klf03-electric-kettle-1-7l/p3310302",
  "imageUrl": "https://media.johnlewiscontent.com/i/JohnLewis/237091061",
  "price": 159.95,
  "currency": "GBP",
  "availableToOrder": true,
  "inStock": true,
  "colour": "Black",
  "averageRating": 4.1,
  "productType": "Kettles",
  "category": "Kettles",
  "attributes": {
    "Guarantee": "2 year guarantee included",
    "Filter feature": "Removable, Washable",
    "Filter included": "Filter Included",
    "Brand": "Smeg",
    "Power": "3000.00W",
    "Variable temperature control": "No",
    "Corded or cordless": "Cordless",
    "Country of origin": "China",
    "Quiet mark": "Not Accredited",
    "Care instructions": "Wash with warm soapy water - no harsh chemicals",
    "Kettle type": "Electric",
    "Power supply": "Mains",
    "Cable length": "99cm"
  },
  "barcodes": {
    "ean13": [
      "8017709227821"
    ]
  },
  "variants": [
    {
      "variantId": "6e880cc1-a7a1-5a3a-91da-dc5dcae4fa14",
      "skuId": "237091061",
      "name": "Smeg KLF03 Electric Kettle, 1.7L, Black",
      "colour": "Black",
      "price": "159.95",
      "currency": "GBP",
      "availableToOrder": true,
      "attributes": {
        "Dimensions": "H248 x W171 x D226mm",
        "Weight": "1.50 kg",
        "Model name / number": "KLF03BLUK",
        "Capacity": "1.7L"
      }
    }
  ],
  "reviews": {
    "provider": "John Lewis ratings-reviews API",
    "productId": "3310302",
    "total": 751,
    "averageRating": 4.1,
    "ratingCount": 751,
    "items": [
      {
        "id": "585628310",
        "rating": {
          "value": 5,
          "label": "Excellent",
          "minValue": 1,
          "maxValue": 5
        },
        "title": "Extremely stylish and good quality Kettle",
        "reviewText": "Fantastic quality and looks extremely stylish, co-ordinating toaster also looks great too",
        "dateUnixMs": 1786949377912,
        "reviewer": {
          "userName": "RR Household",
          "location": "Lancashire"
        },
        "tags": [
          "isVerifiedBuyer",
          "isVerifiedReviewer"
        ],
        "feedback": {
          "positiveCount": 1,
          "negativeCount": 0
        }
      }
    ]
  },
  "market": "GB",
  "locale": "en-GB",
  "sourceLanguage": "en",
  "retrievedAt": "2026-10-02T10:11:15.689405+00:00",
  "dataSource": "productDetail"
}
```

### Pricing

| Event | Event name | Price |
|-------|------------|-------|
| product-detail | `product-detail` | **$5.00 / 1,000** |
| product-listing | `product-listing` | **$2.00 / 1,000** |
| review | `review` | **$0.50 / 1,000** |

Each product is charged once according to the data source: if the Actor scrapes that product's detail page, it is charged at the `product-detail` rate. If it only collects the product from a listing page without scraping the detail page, it is charged at the `product-listing` rate. When reviews are collected, the `review` event is charged with a quantity equal to the number of review items saved. For example, saving five reviews charges five `review` events.

### AI Agents and Integrations

Use the [Apify MCP server](https://docs.apify.com/integrations/mcp) to let compatible AI agents discover and run Actors and access their results. Supply explicit category or product URLs, choose a product limit, and enable reviews only when needed. The structured output supports product comparisons, specification extraction, price research, and review analysis.

Example task for an AI agent: “Collect two cordless kettles from this John Lewis category, include five reviews per product, and compare their prices, capacities, and customer feedback.”

### Scope and Limitations

- UK storefront only; no store or delivery postcode is selected.
- Listing-only mode omits detail fields that require a product page.
- Online availability is not a stock quantity or postcode-specific delivery promise.
- Requests use UK Apify Residential Proxy with a 20-second timeout and at most two attempts per URL, including blocked-session rotations. At most two requests run concurrently. The crawl stops if an initial URL fails before any products are saved, or after three consecutive exhausted requests, to limit proxy costs. Persistent blocks or source outages can still prevent results.

# Actor input Schema

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

John Lewis listing or product URLs.

## `maxProducts` (type: `integer`):

Global maximum number of unique product records.

## `scrapeProductDetails` (type: `boolean`):

Fetch each product page for variants and full details. Disable to output faster listing-only records with the same top-level field names.

## `maxReviews` (type: `integer`):

Newest reviews to include per product; 0 disables review requests.

## Actor input object example

```json
{
  "startUrls": [
    {
      "url": "https://www.johnlewis.com/browse/electricals/kettles/_/N-aht"
    }
  ],
  "maxProducts": 4,
  "scrapeProductDetails": true,
  "maxReviews": 0
}
```

# Actor output Schema

## `products` (type: `string`):

No description

# API

You can run this Actor programmatically using our API. Below are code examples in JavaScript, Python, and CLI, as well as the OpenAPI specification and MCP server setup.

## JavaScript example

```javascript
import { ApifyClient } from 'apify-client';

// Initialize the ApifyClient with your Apify API token
// Replace the '<YOUR_API_TOKEN>' with your token
const client = new ApifyClient({
    token: '<YOUR_API_TOKEN>',
});

// Prepare Actor input
const input = {
    "startUrls": [
        {
            "url": "https://www.johnlewis.com/browse/electricals/kettles/_/N-aht"
        }
    ]
};

// Run the Actor and wait for it to finish
const run = await client.actor("datasaurus/john-lewis").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 = { "startUrls": [{ "url": "https://www.johnlewis.com/browse/electricals/kettles/_/N-aht" }] }

# Run the Actor and wait for it to finish
run = client.actor("datasaurus/john-lewis").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 '{
  "startUrls": [
    {
      "url": "https://www.johnlewis.com/browse/electricals/kettles/_/N-aht"
    }
  ]
}' |
apify call datasaurus/john-lewis --silent --output-dataset

```

## MCP server setup

```json
{
    "mcpServers": {
        "apify": {
            "type": "http",
            "url": "https://mcp.apify.com/?tools=fetch-actor-details,datasaurus/john-lewis"
        }
    }
}
```

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/rghXBkk8rlFcAhLJk/builds/g70YFIjeydFqBAROR/openapi.json
