# John Lewis Electricals Scraper (`crawlerbros/john-lewis-electricals-scraper`) Actor

Scrape John Lewis & Partners - a leading UK department-store retailer's electronics catalog. Browse laptops, desktop PCs, TVs, tablets, headphones, and games consoles with live prices, brand, and product images.

- **URL**: https://apify.com/crawlerbros/john-lewis-electricals-scraper.md
- **Developed by:** [Crawler Bros](https://apify.com/crawlerbros) (community)
- **Categories:** E-commerce, Automation, Developer tools
- **Stats:** 2 total users, 1 monthly users, 100.0% runs succeeded, 0 bookmarks
- **User rating**: No ratings yet

## Pricing

from $3.00 / 1,000 results

This Actor is paid per event and usage. You are charged both the fixed price for specific events and for Apify platform usage.
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 web data automations that power AI and operations. They run on the Apify platform to scrape websites, process data, connect APIs, and automate workflows.
In Batch mode, an Actor accepts a well-defined JSON input, performs an action which can take anything from a few seconds to a few hours,
and optionally produces a well-defined JSON output, datasets with results, or files in key-value store.
In Standby mode, an Actor provides a web server which can be used as a website, API, or an MCP server.
Actors are written with capital "A".

## How to integrate an Actor?

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

- **AI agents and MCP clients** — the [Apify MCP server](https://docs.apify.com/integrations/mcp.md) at `https://mcp.apify.com` (remote, streamable HTTP, OAuth on first use).
- **Agentic workflows and local Actor development** — [Agent Skills](https://apify.com/.well-known/agent-skills/index.json) with the [Apify CLI](https://docs.apify.com/cli/docs.md): `npm install -g apify-cli`, then `apify login`.
- **JavaScript/TypeScript projects** — the official [JS/TS client](https://docs.apify.com/api/client/js/docs.md): `npm install apify-client`.
- **Python projects** — the official [Python client](https://docs.apify.com/api/client/python/docs.md): `pip install apify-client`.
- **Any other language** — the [REST API](https://docs.apify.com/api/v2.md).

For usage examples, see the [API](#api) section below.

For more details, see Apify documentation as [Markdown index](https://docs.apify.com/llms.txt) and [Markdown full-text](https://docs.apify.com/llms-full.txt).

# README

## John Lewis Electricals Scraper

Scrape [John Lewis & Partners](https://www.johnlewis.com) — one of the UK's best-known department-store retailers — for live electronics and appliance pricing. Browse laptops, desktop PCs, monitors, tablets, TVs, headphones, speakers, soundbars, games consoles, mobile phones, smart watches, printers, coffee machines, and kitchen appliances (ovens, hobs, fridges, freezers, washing machines, tumble dryers), or fetch specific product URLs directly with full detail-page data (rating, reviews, description, availability, colour, dimensions, and more). No login, no API key, no cookies required.

### What this actor does

- **Two modes:** `byCategory` (browse a category listing) and `byUrls` (fetch exact product URLs, always with full detail)
- **39 built-in categories:** Laptops & MacBooks, Desktop PCs, iPads & Tablets, Televisions, Headphones, Games Consoles, Built-in Ovens (Double/Single), Range Cookers, Electric/Induction Hobs, Fridges, Freezers, Washing Machines, Tumble Dryers, Monitors, Printers, Mobile Phones, Smart Watches, Coffee Machines, Soundbars, Speakers, Vacuum Cleaners, Microwaves, Cameras, Dishwashers, Air Conditioners, Air Purifiers, Dehumidifiers, Fans, Kettles, Irons & Steamers, Food Processors/Mixers/Blenders, Projectors, Smart Heating, Smart Lighting, Hi-Fi Systems & CD Players, Turntables, Radios
- **Optional full product-detail enrichment** (`fetchProductDetail`) — visits each listing's product page for description, availability, colour, weight, model number, MPN, guarantee, full technical specifications, delivery options, and extra images
- **Filters:** brand (contains match), min/max price (GBP — applied server-side on mode=byCategory via John Lewis's own price facet when both bounds are given, plus a post-filter safety net), minimum rating (always available, no detail fetch needed), in-stock only (server-side facet, mode=byCategory), New In only (server-side facet, mode=byCategory), on-sale only (was/now price post-filter), on-offer only (server-side facet, mode=byCategory, covers every active promotion type — not just price markdowns)
- **Live data:** everything scraped fresh on every run
- **Robots.txt compliant** — johnlewis.com's `robots.txt` disallows `/search*`; this actor only scrapes `/browse/.../_/N-*` category pages and individual product pages, both explicitly allowed
- **Empty fields are omitted** — every record only contains fields that were actually found on the page

### Output per product

Listing mode always includes: `productId`, `title`, `brand`, `price`, `currency` (`GBP`), `rating`, `reviewCount`, `productUrl`, `imageUrl`, `category`, `recordType: "product"`, `scrapedAt`. `rating`/`reviewCount` are scraped straight from the listing card and are omitted only for products with no reviews yet. When a product is currently marked down, the record also includes `wasPrice` (the pre-discount price), `onSale: true`, and `discountAmount` (the £ amount saved) — all scraped directly from the listing card's "was/now" price and "Save £X" badge, so they're available in every mode without needing `fetchProductDetail`.

With `fetchProductDetail` on (or always for mode=`byUrls`), records additionally include when available:

| Field | Description |
|---|---|
| `ratingPercentage` | Rating expressed as a percentage (detail page only) |
| `description` | Full product description (HTML stripped) |
| `availability` | `InStock` or `OutOfStock` |
| `color` | Product colour/finish |
| `weight` | Unpackaged product weight |
| `modelNumber` | Manufacturer model name/number |
| `mpn` | Manufacturer part number |
| `sku` | John Lewis SKU/stock code |
| `guarantee` | Included guarantee terms (e.g. "2 year guarantee included") |
| `imageUrls` | Up to 10 product images |
| `categoryPath` | Full breadcrumb category path |
| `specifications` | Full technical spec sheet as `[{name, value}]` (e.g. RAM, battery life, screen resolution) — varies per product, often 20-50+ rows |
| `deliveryOptions` | Every delivery/collection method offered for this product as `[{name, price}]` (e.g. Standard Delivery, Click & Collect, Next Day Delivery) |
| `eligibleForTradeIn` | Whether John Lewis currently accepts a trade-in device toward this product (mobile phones, some laptops) |
| `promotionalMessages` | Currently-active promo banner titles for this product (e.g. `"Save £100"`, `"2 year guarantee included"`) |
| `videoUrl` | Direct MP4 product video URL, when John Lewis has one for this product |
| `otherVariants` | Other colour/finish options of the same product as `[{name, productUrl}]`, excluding the variant already returned |

With `fetchReviews` on (any mode), records additionally include:

| Field | Description |
|---|---|
| `topReviews` | Up to 10 real customer reviews as `[{title, text, rating, author, location, date, isVerifiedBuyer}]`, pulled from johnlewis.com's own ratings-reviews service — not just the aggregate rating/reviewCount, but actual review text |

### Input

| Field | Type | Default | Description |
|---|---|---|---|
| `mode` | string | `byCategory` | `byCategory` or `byUrls` |
| `category` | string | `laptops-macbooks` | Category to browse (mode=byCategory; see list below) |
| `productUrls` | array | – | Exact product URLs (mode=byUrls) |
| `sortBy` | string | `relevance` | Listing sort order: `relevance`, `priceLow`, `priceHigh`, `new`, `popularity`, `discount` (mode=byCategory) |
| `fetchProductDetail` | boolean | `false` | Enrich each listing record with full product-page data (mode=byCategory) |
| `brand` | string | – | Only keep products whose brand contains this text |
| `minPrice` / `maxPrice` | integer | – | GBP price range. When BOTH are set on mode=byCategory, applied server-side via John Lewis's own price facet (narrows the source listing); a one-sided range (only `minPrice` or only `maxPrice`) is enforced as a post-filter only. Always enforced as a post-filter safety net regardless |
| `minRating` | integer | `0` | Minimum star rating (0-5); always enforceable, no detail fetch needed |
| `inStockOnly` | boolean | `false` | Only keep in-stock products; applied server-side on mode=byCategory via John Lewis's own "Show in stock items only" facet (no detail fetch needed), enforced from the live detail page on mode=byUrls |
| `newInOnly` | boolean | `false` | Only keep products flagged "New In"; applied server-side on mode=byCategory via John Lewis's own "New In" facet (not applicable to mode=byUrls) |
| `onSaleOnly` | boolean | `false` | Only keep products currently marked down; enforceable in every mode, no detail fetch needed. Not a server-side facet on mode=byCategory (johnlewis.com has no dedicated "on sale" URL facet), so it's applied as a post-filter against the fetched listing snapshot(s); the actor fetches up to 5 listing snapshots when this or `minRating`/`brand` is combined with a small category (John Lewis's own Akamai-fronted listing page returns a genuinely different card subset per fetch — a small number of on-sale items in a small category can occasionally still be missed under some `sortBy` values due to that upstream variance) |
| `onOfferOnly` | boolean | `false` | Only keep products in John Lewis's own "On Offer" promotion; applied server-side via John Lewis's own facet on mode=byCategory (covers price markdowns, bundled gifts, and finance offers — broader than `onSaleOnly`) |
| `fetchReviews` | boolean | `false` | Fetch up to 10 real customer reviews (text, rating, reviewer, date) per product; works in every mode, one extra request per product |
| `maxItems` | integer | `50` | Hard cap on emitted records |

#### Example: browse a category with full product detail

```json
{
  "mode": "byCategory",
  "category": "laptops-macbooks",
  "brand": "HP",
  "fetchProductDetail": true,
  "minRating": 4,
  "maxItems": 50
}
```

#### Example: fetch specific products by URL

```json
{
  "mode": "byUrls",
  "productUrls": ["https://www.johnlewis.com/hp-14-ep0021na-laptop-intel-core-i7-processor-8gb-ram-512gb-ssd-14-full-hd-natural-silver/p115160491"]
}
```

#### Example: find on-sale washing machines with reviews

```json
{
  "mode": "byCategory",
  "category": "washing-machines",
  "onSaleOnly": true,
  "fetchReviews": true,
  "maxItems": 30
}
```

#### Example: in-stock, highly rated televisions under £800

```json
{
  "mode": "byCategory",
  "category": "televisions",
  "maxPrice": 800,
  "minRating": 4,
  "inStockOnly": true,
  "maxItems": 40
}
```

### Use cases

- **Price monitoring** — track live prices, discounts, and stock status for electronics/appliance SKUs across runs.
- **Competitive intelligence** — compare brand mix, pricing, and promotions against other UK electronics retailers.
- **Deal aggregation** — surface currently on-sale or on-offer products across categories for a deals site or newsletter.
- **Product research** — pull full specifications, reviews, and delivery options before purchasing decisions.
- **Catalog enrichment** — merge John Lewis pricing/availability/specs into an existing product database by URL.

### Categories available

- Laptops & MacBooks (`laptops-macbooks`)
- Desktop PCs (`desktop-pcs`)
- iPads & Tablets (`ipad-tablets`)
- Televisions (`televisions`)
- Headphones (`headphones`)
- Games Consoles (`games-consoles`)
- Built-in Ovens, Double (`built-in-ovens-double`)
- Built-in Ovens, Single (`built-in-ovens-single`)
- Range Cookers (`range-cookers`)
- Electric Hobs (`electric-hobs`)
- Induction Hobs (`induction-hobs`)
- Fridges (`fridges`)
- Freezers (`freezers`)
- Washing Machines (`washing-machines`)
- Tumble Dryers (`tumble-dryers`)
- Monitors (`monitors`)
- Printers (`printers`)
- Mobile Phones (`mobile-phones`)
- Smart Watches (`smart-watches`)
- Coffee Machines (`coffee-machines`)
- Soundbars (`soundbars`)
- Speakers (`speakers`)
- Vacuum Cleaners (`vacuum-cleaners`)
- Microwaves (`microwaves`)
- Cameras (`cameras`)
- Dishwashers (`dishwashers`)
- Air Conditioners (`air-conditioners`)
- Air Purifiers (`air-purifiers`)
- Dehumidifiers (`dehumidifiers`)
- Fans (`fans`)
- Kettles (`kettles`)
- Irons & Steamers (`irons`)
- Food Processors, Mixers & Blenders (`food-processors-blenders`)
- Projectors (`projectors`)
- Smart Heating (`smart-heating`)
- Smart Lighting (`smart-lighting`)
- Hi-Fi Systems & CD Players (`hi-fi-systems`)
- Turntables (`turntables`)
- Radios (`radios`)

### Notes

- Each category page is scraped as it renders on the site (no deep pagination); category "view all" pages typically return 20-73 products in a single page load. johnlewis.com's CDN occasionally serves a smaller snapshot of the same category page on a given request (observed varying between ~40-60 cards for the same category+sort combination); the actor automatically re-fetches the listing through a fresh proxy session up to twice more and merges in any additional products found, converging toward the fuller catalog rather than a partial one, though exact counts can still vary slightly run to run for high-traffic categories.
- Prices are shown in GBP as listed on johnlewis.com.
- If a page fails to load, the actor automatically retries with backoff and, as a last resort, falls back to the free Apify datacenter proxy (AUTO group) — no residential proxy or paid add-ons required.

### FAQs

**Do I need an account or API key?**
No. This actor scrapes publicly available category listing and product-detail pages.

**Why is there no free-text search mode?**
johnlewis.com's `robots.txt` disallows crawling `/search*`. This actor respects that and only scrapes the explicitly allowed `/browse/.../_/N-*` category pages and individual product pages instead.

**Why are some fields missing on some products?**
Only fields that were actually present on the page are included in each record. Turn on `fetchProductDetail` for the fullest set of fields per record.

**Does `inStockOnly` narrow my results in `byCategory` mode?**
Yes — it's applied server-side via John Lewis's own "Show in stock items only" facet, so it narrows the source listing directly and doesn't require `fetchProductDetail`. `minRating` similarly works in every mode — rating and review count are scraped directly from the listing card.

**Why does a plain `curl`/script request to a `productUrl` hang or time out, even though it opens fine in a browser?**
`productUrl` values are real, valid links. johnlewis.com runs Akamai Bot Manager, which silently stalls (rather than rejects) plain scripted requests from datacenter IPs that lack a full browser TLS/JA3 fingerprint — this is johnlewis.com's own anti-bot behavior, not a broken link. The actor itself uses Chrome TLS impersonation to get through; `imageUrl` links (served from a separate CDN) are unaffected and load normally with any client.

# Actor input Schema

## `mode` (type: `string`):

byCategory: browse a category listing page. byUrls: fetch specific product URLs directly (with full detail-page data).

## `category` (type: `string`):

Electronics/appliance category to browse. Required for mode=byCategory.

## `productUrls` (type: `array`):

Full johnlewis.com/.../pNNNNNN product URLs to fetch directly. Required for mode=byUrls.

## `sortBy` (type: `string`):

Order in which the category listing returns products. Only affects which items are captured first when `maxItems` is below the category total. Not applicable to mode=byUrls.

## `fetchProductDetail` (type: `boolean`):

Also visit each product's detail page for rating, review count, description, availability, colour, weight, model number, MPN, guarantee and extra images. Roughly doubles requests and run time. Always on for mode=byUrls.

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

Only keep products whose brand contains this text (case-insensitive), e.g. `HP`, `Samsung`, `Apple`.

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

Drop products cheaper than this (GBP). When both minPrice and maxPrice are set (mode=byCategory), applied server-side via John Lewis's own price facet, narrowing the source listing; a one-sided range is a post-filter only. Always enforced as a post-filter too.

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

Drop products pricier than this (GBP). When both minPrice and maxPrice are set (mode=byCategory), applied server-side via John Lewis's own price facet, narrowing the source listing; a one-sided range is a post-filter only. Always enforced as a post-filter too.

## `minRating` (type: `integer`):

Only keep products rated at least this (0-5 stars). Rating is scraped directly from the listing card, so this works in every mode without needing `fetchProductDetail`. Products with no reviews yet are excluded, since their rating cannot be verified against the threshold.

## `inStockOnly` (type: `boolean`):

Only keep products currently available to order. In mode=byCategory this is applied server-side via John Lewis's own "Show in stock items only" facet (narrows the source listing, works without `fetchProductDetail`); in mode=byUrls it's enforced from the fetched detail page's live availability.

## `newInOnly` (type: `boolean`):

Only keep products currently flagged "New In" by John Lewis. Applied server-side via John Lewis's own "New In" facet, so it narrows the source listing (not just a post-filter). Not applicable to mode=byUrls.

## `onSaleOnly` (type: `boolean`):

Only keep products currently marked down from a previous price. Detected directly from the listing card's "was/now" price and "Save £X" badge, so this works in every mode without needing `fetchProductDetail`.

## `onOfferOnly` (type: `boolean`):

Only keep products currently in John Lewis's own "On Offer" promotion. Applied server-side via John Lewis's own facet, so it narrows the source listing (not just a post-filter). Broader than `onSaleOnly`: covers every active promotion type (price markdowns, bundled gifts, finance offers), not just was/now price cuts. Not applicable to mode=byUrls.

## `fetchReviews` (type: `boolean`):

Also fetch up to 10 real customer reviews per product (title, review text, star rating, reviewer name/location, date, verified-buyer flag) from johnlewis.com's own ratings-reviews service. Works in every mode (uses the product ID already present on every listing card; does not require `fetchProductDetail`). Adds one extra request per product.

## `maxItems` (type: `integer`):

Hard cap on emitted records.

## Actor input object example

```json
{
  "mode": "byCategory",
  "category": "laptops-macbooks",
  "productUrls": [],
  "sortBy": "relevance",
  "fetchProductDetail": false,
  "minRating": 0,
  "inStockOnly": false,
  "newInOnly": false,
  "onSaleOnly": false,
  "onOfferOnly": false,
  "fetchReviews": false,
  "maxItems": 50
}
```

# Actor output Schema

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

Dataset containing all scraped John Lewis products.

# 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 = {
    "mode": "byCategory",
    "category": "laptops-macbooks",
    "productUrls": [],
    "sortBy": "relevance",
    "fetchProductDetail": false,
    "minRating": 0,
    "inStockOnly": false,
    "newInOnly": false,
    "onSaleOnly": false,
    "onOfferOnly": false,
    "fetchReviews": false,
    "maxItems": 50
};

// Run the Actor and wait for it to finish
const run = await client.actor("crawlerbros/john-lewis-electricals-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 = {
    "mode": "byCategory",
    "category": "laptops-macbooks",
    "productUrls": [],
    "sortBy": "relevance",
    "fetchProductDetail": False,
    "minRating": 0,
    "inStockOnly": False,
    "newInOnly": False,
    "onSaleOnly": False,
    "onOfferOnly": False,
    "fetchReviews": False,
    "maxItems": 50,
}

# Run the Actor and wait for it to finish
run = client.actor("crawlerbros/john-lewis-electricals-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 '{
  "mode": "byCategory",
  "category": "laptops-macbooks",
  "productUrls": [],
  "sortBy": "relevance",
  "fetchProductDetail": false,
  "minRating": 0,
  "inStockOnly": false,
  "newInOnly": false,
  "onSaleOnly": false,
  "onOfferOnly": false,
  "fetchReviews": false,
  "maxItems": 50
}' |
apify call crawlerbros/john-lewis-electricals-scraper --silent --output-dataset

```

## MCP server setup

```json
{
    "mcpServers": {
        "apify": {
            "type": "http",
            "url": "https://mcp.apify.com/?tools=fetch-actor-details,crawlerbros/john-lewis-electricals-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/zVOK9zC1sBSo2u4G1/builds/HYzHpbudeGxpNuJSg/openapi.json
