# Toolstation Scraper (`maximedupre/toolstation-scraper`) Actor

Scrape Toolstation products from search queries, category pages, or product URLs. Export product codes, names, brands, prices, availability, ratings, images, descriptions, EANs, categories, and specifications.

- **URL**: https://apify.com/maximedupre/toolstation-scraper.md
- **Developed by:** [Maxime Dupré](https://apify.com/maximedupre) (community)
- **Categories:** E-commerce, Business, Marketing
- **Stats:** 2 total users, 1 monthly users, 100.0% runs succeeded, 0 bookmarks
- **User rating**: No ratings yet

## Pricing

from $2.70 / 1,000 scraped products

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

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

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

### 🛒 Toolstation scraper for product data

Toolstation Scraper collects public product data from [Toolstation](https://www.toolstation.com/). Search by keyword, browse category pages, or fetch known product URLs, then export product codes, names, brands, prices, availability, ratings, images, descriptions, EANs, categories, and specifications.

Use this Toolstation scraper when you need repeatable UK trade and DIY product data without opening product pages by hand. It is useful for price checks, stock monitoring, catalogue research, assortment reports, and recurring ecommerce workflows. Each accepted product is saved as one dataset row, so the output is ready for CSV, JSON, Excel, the Apify API, schedules, webhooks, and other integrations.

For an easy first run, keep the prefilled `pliers` search and the default product limit. Review the dataset, then add your own Toolstation search terms, category URLs, or exact product URLs.

### ✅ What this Actor does

- Scrapes public Toolstation product data.
- Searches Toolstation products by keyword or brand term.
- Browses Toolstation category URLs such as `https://www.toolstation.com/hand-tools/pliers/c30`.
- Fetches known Toolstation product pages directly.
- Saves one row per scraped product.
- Extracts product codes, SKU values, names, brands, product URLs, image URLs, and descriptions.
- Extracts current prices, previous prices when shown, currency, discount percentages, availability, ratings, and review counts.
- Extracts EANs, category paths, and product specification name/value pairs when Toolstation exposes them.
- Lets you cap search and category runs from 1 to 500 products.
- Supports relevance, price low to high, price high to low, and Toolstation default ordering choices.
- Runs without a Toolstation login, cookies, or a user-provided API key.

The Actor focuses on public Toolstation product pages and product listings. It does not scrape checkout data, private account data, delivery slots, customer review text, historical prices, or non-Toolstation retailers.

### 📦 Data you can extract

Each dataset item is one Toolstation product. Fields can be `null` or empty when Toolstation does not show that value for a product.

- `productCode` - Toolstation product code.
- `sku` - Toolstation SKU, usually the same as the product code.
- `ean` - EAN when shown on the product page.
- `name` - product name.
- `brand` - product brand when available.
- `productUrl` - Toolstation product URL.
- `imageUrl` - primary product image URL when available.
- `description` - product description when available.
- `price.current`, `price.original`, `price.currency`, and `price.discountPercent` - price details in GBP.
- `availability.inStock` and `availability.text` - stock signals from Toolstation.
- `rating.value` and `rating.reviewCount` - review summary values when available.
- `categories` - Toolstation category path.
- `specifications` - product specification name/value pairs.

### 🧭 Common use cases

- Monitor Toolstation product prices for a keyword, category, or saved product list.
- Track visible stock status for important trade products.
- Build product catalog exports with images, categories, EANs, and specifications.
- Compare brands, prices, ratings, and product ranges in a Toolstation category.
- Feed Toolstation product data into spreadsheets, BI tools, dashboards, alerts, or internal APIs.
- Schedule repeat Apify runs for recurring price and assortment checks.

### 🚀 How to run

1. Fill exactly one target section: **Search queries**, **Category URLs**, or **Product URLs**.
2. Use **Search queries** for terms such as `pliers`, `dewalt 18v`, or `copper pipe`.
3. Use **Category URLs** when you want products from one or more Toolstation category pages.
4. Use **Product URLs** when you already know the exact product pages to collect.
5. Set **Maximum products** for search or category runs. Use a small value such as `25` for a quick first run.
6. Choose a sort order when needed.
7. Run the Actor and open the dataset.

For product URL runs, paste the product pages you want. For search and category runs, the Actor collects product URLs first, then enriches each product from its public product page.

### ⚙️ Input

| Field | What it does |
| --- | --- |
| `searchQueries` | Product keywords, brand names, or item terms to search on Toolstation. |
| `categoryUrls` | Toolstation category pages to browse for product rows. |
| `productUrls` | Known Toolstation product pages to fetch directly. |
| `maxItems` | Maximum products to return for search or category runs. Default is `75`; maximum is `500`. |
| `sortBy` | Sort order for search or category runs: relevance, price low to high, price high to low, or Toolstation default ordering. |

Example search input:

```json
{
  "searchQueries": ["pliers"],
  "maxItems": 25,
  "sortBy": "relevance"
}
````

Example category input:

```json
{
  "categoryUrls": [
    {
      "url": "https://www.toolstation.com/hand-tools/pliers/c30"
    }
  ],
  "maxItems": 25,
  "sortBy": "priceAsc"
}
```

Example product URL input:

```json
{
  "productUrls": [
    {
      "url": "https://www.toolstation.com/minotaur-hi-leverage-pliers-set/p40054"
    }
  ]
}
```

### 🧾 Output example

```json
{
  "productCode": "40054",
  "sku": "40054",
  "ean": "5059303003169",
  "name": "Minotaur Hi-Leverage Pliers Set",
  "brand": "Minotaur",
  "productUrl": "https://www.toolstation.com/minotaur-hi-leverage-pliers-set/p40054",
  "imageUrl": "https://cdn.aws.toolstation.com/images/141020-UK/250/40054.jpg",
  "description": "Get enhanced cutting performance with a pair of high-leverage pliers from this superior set.",
  "price": {
    "current": 14.98,
    "original": null,
    "currency": "GBP",
    "discountPercent": null
  },
  "availability": {
    "inStock": true,
    "text": "In stock"
  },
  "rating": {
    "value": 4.5909,
    "reviewCount": 66
  },
  "categories": ["Hand Tools", "Pliers & Cutters", "Pliers"],
  "specifications": [
    {
      "name": "Material",
      "value": "Chrome Vanadium Steel"
    }
  ]
}
```

### 💳 Pricing

This Actor uses pay-per-event pricing. You are charged for each successfully scraped product. Skipped products, invalid inputs, and source pages that do not produce a product row are not charged as scraped products.

### ⚠️ Limits and caveats

- Search and category runs are capped at `500` products per run.
- Product URL runs collect the product pages you provide.
- Some fields can be missing because Toolstation does not show every value on every product page.
- Availability text is based on the public product data Toolstation exposes at run time.
- The Actor skips a product if Toolstation does not respond in time, then continues with the rest of the run.
- The Actor does not collect customer review text, checkout data, private account data, delivery slot data, or historical price changes.

### ❓ FAQ

#### 🔐 Do I need a Toolstation account?

No. The Actor collects public Toolstation product data and does not need a Toolstation login, cookies, or a user-provided API key.

#### 🔗 Can I scrape exact Toolstation product pages?

Yes. Use the **Product URLs** input when you already know the exact product pages you want to collect.

#### 📂 Can I scrape a whole category?

Yes. Paste one or more Toolstation category URLs into **Category URLs** and set **Maximum products** for the run.

#### 🧩 Why are some fields empty?

Toolstation does not expose every value for every product. The Actor leaves unavailable values as `null` or empty arrays instead of guessing.

### 📝 Changelog

- 1.0: Initial release.

### 🆘 Support

For issues, questions, or feature requests, [file a ticket](https://console.apify.com/actors/maximedupre~toolstation-scraper/issues) and I'll fix or implement it in less than 24h 🫡

### 🔗 Other actors

- [John Lewis Product Scraper ↗](https://apify.com/maximedupre/john-lewis-product-scraper) - collect UK retail product prices, variants, availability, images, and specifications.
- [Allegro Scraper ↗](https://apify.com/maximedupre/allegro-scraper) - export marketplace listing prices, sellers, ratings, delivery text, and category data.
- [Mercado Libre Search Scraper ↗](https://apify.com/maximedupre/mercado-libre-search-scraper) - scrape marketplace search results, prices, sellers, ranks, and shipping text.
- [G2 Products Scraper ↗](https://apify.com/maximedupre/g2-products-scraper) - collect software product profiles, ratings, categories, alternatives, and review data.
- [Google Play Store Scraper ↗](https://apify.com/maximedupre/google-play-store-scraper) - extract app search, app detail, review, permission, and data safety rows.

**Made with ❤️ by Maxime Dupré**

# Actor input Schema

## `searchQueries` (type: `array`):

Product keywords, brand names, or item terms to search on Toolstation.

## `categoryUrls` (type: `array`):

Toolstation category pages to browse for product rows.

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

Known Toolstation product pages to fetch directly.

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

Maximum products to return for search or category runs.

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

Order for search or category runs when Toolstation supports it.

## Actor input object example

```json
{
  "searchQueries": [
    "pliers"
  ],
  "maxItems": 75,
  "sortBy": "relevance"
}
```

# Actor output Schema

## `results` (type: `string`):

Open the dataset with one row per scraped Toolstation product.

# 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 = {
    "searchQueries": [
        "pliers"
    ],
    "maxItems": 75,
    "sortBy": "relevance"
};

// Run the Actor and wait for it to finish
const run = await client.actor("maximedupre/toolstation-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 = {
    "searchQueries": ["pliers"],
    "maxItems": 75,
    "sortBy": "relevance",
}

# Run the Actor and wait for it to finish
run = client.actor("maximedupre/toolstation-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 '{
  "searchQueries": [
    "pliers"
  ],
  "maxItems": 75,
  "sortBy": "relevance"
}' |
apify call maximedupre/toolstation-scraper --silent --output-dataset

```

## MCP server setup

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

```

## OpenAPI specification

```json
{
    "openapi": "3.0.1",
    "info": {
        "title": "Toolstation Scraper",
        "description": "Scrape Toolstation products from search queries, category pages, or product URLs. Export product codes, names, brands, prices, availability, ratings, images, descriptions, EANs, categories, and specifications.",
        "version": "1.0",
        "x-build-id": "eOKkvHB0IDQtEq3uB"
    },
    "servers": [
        {
            "url": "https://api.apify.com/v2"
        }
    ],
    "paths": {
        "/acts/maximedupre~toolstation-scraper/run-sync-get-dataset-items": {
            "post": {
                "operationId": "run-sync-get-dataset-items-maximedupre-toolstation-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/maximedupre~toolstation-scraper/runs": {
            "post": {
                "operationId": "runs-sync-maximedupre-toolstation-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/maximedupre~toolstation-scraper/run-sync": {
            "post": {
                "operationId": "run-sync-maximedupre-toolstation-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": {
                    "searchQueries": {
                        "title": "Search queries",
                        "type": "array",
                        "description": "Product keywords, brand names, or item terms to search on Toolstation.",
                        "items": {
                            "type": "string"
                        }
                    },
                    "categoryUrls": {
                        "title": "Category URLs",
                        "type": "array",
                        "description": "Toolstation category pages to browse for product rows.",
                        "items": {
                            "type": "object",
                            "required": [
                                "url"
                            ],
                            "properties": {
                                "url": {
                                    "type": "string",
                                    "title": "URL",
                                    "description": "Toolstation category page URL."
                                }
                            }
                        }
                    },
                    "productUrls": {
                        "title": "Product URLs",
                        "type": "array",
                        "description": "Known Toolstation product pages to fetch directly.",
                        "items": {
                            "type": "object",
                            "required": [
                                "url"
                            ],
                            "properties": {
                                "url": {
                                    "type": "string",
                                    "title": "URL",
                                    "description": "Toolstation product page URL."
                                }
                            }
                        }
                    },
                    "maxItems": {
                        "title": "Maximum products",
                        "minimum": 1,
                        "maximum": 500,
                        "type": "integer",
                        "description": "Maximum products to return for search or category runs.",
                        "default": 75
                    },
                    "sortBy": {
                        "title": "Sort order",
                        "enum": [
                            "relevance",
                            "priceAsc",
                            "priceDesc",
                            "bestSeller"
                        ],
                        "type": "string",
                        "description": "Order for search or category runs when Toolstation supports it.",
                        "default": "relevance"
                    }
                }
            },
            "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
                                    }
                                }
                            }
                        }
                    }
                }
            }
        }
    }
}
```
