# Tool Nut Scraper (`crawlerbros/toolnut-scraper`) Actor

Scrape Tool Nut's power-tool and hardware catalog. Search by keyword, browse categories, browse the full catalog, or look up products by handle/URL. Get pricing, brand, stock status, images, and specifications.

- **URL**: https://apify.com/crawlerbros/toolnut-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

## Tool Nut Scraper

Scrape [Tool Nut](https://www.toolnut.com)'s power-tool, hand-tool, and hardware catalog. Search by keyword, browse a category, browse the entire catalog, or look products up directly by handle/URL. Get real brand, price, stock status, images, and specifications for every product. HTTP-only via Tool Nut's public storefront endpoints. No auth, no cookies, no proxy required.

### What this actor does

- **Five modes:** `search`, `browseCollection`, `browseAll`, `byProductHandles`, `listCollections`
- **Filters:** brand/vendor, product type, price range, in-stock only
- **Category discovery:** enumerate every category (collection) Tool Nut publishes, with product counts
- **Empty fields are omitted**

### Output per product

- `productId`, `handle`, `title`, `url`
- `vendor` — brand (e.g. `Milwaukee`, `DeWALT`, `Bosch`, `Makita`)
- `productType`, `tags[]`
- `description` — plain-text (HTML stripped)
- `priceMin`, `priceMax`, `currency`
- `inStock`, `sku`, `variantsCount`
- `imageUrl`, `images[]`
- `createdAt`, `updatedAt`
- `sourceCollection` (when found via `browseCollection`), `matchedQuery` (when found via `search`)
- `recordType: "product"`, `scrapedAt`

### Output per category (mode=listCollections)

- `collectionId`, `handle`, `title`, `url`
- `description`, `productsCount`, `imageUrl`, `updatedAt`
- `recordType: "collection"`, `scrapedAt`

### Input

| Field | Type | Default | Description |
|---|---|---|---|
| `mode` | string | `search` | `search` / `browseCollection` / `browseAll` / `byProductHandles` / `listCollections` |
| `searchQuery` | string | `cordless drill` | Free-text query (mode=search) |
| `collectionHandle` | select | `hand-tools` | Curated category (mode=browseCollection) |
| `customCollectionHandle` | string | – | Override with any category handle/URL |
| `productHandles` | array | – | Product handles or URLs (mode=byProductHandles) |
| `vendor` | string | – | Filter to an exact brand name |
| `productType` | string | – | Filter to product types containing this text |
| `priceMin` | number | – | Drop products priced below this |
| `priceMax` | number | – | Drop products priced above this |
| `inStockOnly` | bool | `false` | Only emit in-stock products |
| `maxItems` | int | `25` | Hard cap (1–500) |

#### Example: search with brand + price filter

```json
{
  "mode": "search",
  "searchQuery": "impact driver",
  "vendor": "Milwaukee",
  "priceMax": 300,
  "maxItems": 40
}
```

#### Example: browse a category

```json
{
  "mode": "browseCollection",
  "collectionHandle": "circular-saw-blades",
  "inStockOnly": true,
  "maxItems": 100
}
```

#### Example: lookup specific products

```json
{
  "mode": "byProductHandles",
  "productHandles": [
    "milwaukee-2505-22-m12-fuel-brushless-installation-4-in-1-drill-driver-2-0ah-kit",
    "https://www.toolnut.com/products/bosch-11335k-jack-35-lb-breaker-hammer"
  ]
}
```

#### Example: discover categories

```json
{
  "mode": "listCollections",
  "maxItems": 200
}
```

### Use cases

- **Price monitoring** — track power-tool pricing across brands over time
- **Assortment analysis** — see how many SKUs a category/brand carries and their stock status
- **Competitive research** — compare a supplier's catalog against Tool Nut's listings
- **Procurement** — bulk-pull SKUs and specs for a shopping list of product handles
- **Content/affiliate sites** — pull real product images, descriptions, and prices for tool roundups

### FAQ

**What's Tool Nut?**  An online retailer of power tools, hand tools, saw blades, and shop consumables from brands like Milwaukee, DeWALT, Bosch, Makita, Festool, and Klein. See [toolnut.com](https://www.toolnut.com).

**Is there a rate limit?**  No documented hard cap for normal use; the actor paces requests with small delays and bounded concurrency to stay polite.

**Why is `search` capped at ~10 results per query?**  `search` mode uses Tool Nut's predictive-search JSON endpoint, which Shopify hard-caps at 10 matches regardless of the requested limit — but it returns full product data (brand, type, price, stock, description) in a single reliable request. For more than 10 results on a topic, use `browseCollection` (pick the closest matching category) or `browseAll` with a `productType`/`vendor` filter instead.

**What's the difference between `collectionHandle` and `customCollectionHandle`?**  `collectionHandle` is a curated dropdown of common categories. `customCollectionHandle` accepts any category handle or full URL — useful for the 400+ categories not in the dropdown (pick `other` in the dropdown and set this field).

**Are prices per-variant or per-product?**  `priceMin`/`priceMax` reflect the lowest/highest priced variant on the product (most products have one variant; some tool kits offer multiple bundle options).

**How fresh is the data?**  Real-time — every request hits Tool Nut's live storefront, so prices and stock status reflect the current catalog.

# Actor input Schema

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

What to fetch.

## `searchQuery` (type: `string`):

Free-text query (mode=search), e.g. brand + product name or a tool type.

## `collectionHandle` (type: `string`):

A curated list of common Tool Nut categories. Pick 'Other (use custom handle below)' plus `customCollectionHandle` for any category not listed.

## `customCollectionHandle` (type: `string`):

Override `collectionHandle` with any Tool Nut category handle or full category URL, e.g. `bessey-clamps` or `https://www.toolnut.com/collections/bessey-clamps`.

## `productHandles` (type: `array`):

Product handles or full product URLs, e.g. `milwaukee-2505-22-m12-fuel-brushless-installation-4-in-1-drill-driver-2-0ah-kit` or the full `https://www.toolnut.com/products/...` URL.

## `vendor` (type: `string`):

Only keep products from this exact brand/vendor name, e.g. `Milwaukee`, `DeWALT`, `Bosch`, `Makita`.

## `productType` (type: `string`):

Only keep products whose product type contains this text (case-insensitive), e.g. `Drill`, `Saw Blade`, `Wrench`.

## `priceMin` (type: `number`):

Drop products priced below this amount.

## `priceMax` (type: `number`):

Drop products priced above this amount.

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

Only emit products with at least one purchasable variant.

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

Hard cap on emitted records.

## `proxyConfiguration` (type: `object`):

Tool Nut rate-limits repeated requests from one IP. The free Apify AUTO datacenter proxy group rotates the exit IP per request and is used by default at no extra cost.

## Actor input object example

```json
{
  "mode": "search",
  "searchQuery": "cordless drill",
  "collectionHandle": "hand-tools",
  "productHandles": [],
  "inStockOnly": false,
  "maxItems": 25,
  "proxyConfiguration": {
    "useApifyProxy": true
  }
}
```

# Actor output Schema

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

Dataset containing all scraped Tool Nut records.

# 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": "search",
    "searchQuery": "cordless drill",
    "collectionHandle": "hand-tools",
    "productHandles": [],
    "inStockOnly": false,
    "maxItems": 25,
    "proxyConfiguration": {
        "useApifyProxy": true
    }
};

// Run the Actor and wait for it to finish
const run = await client.actor("crawlerbros/toolnut-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": "search",
    "searchQuery": "cordless drill",
    "collectionHandle": "hand-tools",
    "productHandles": [],
    "inStockOnly": False,
    "maxItems": 25,
    "proxyConfiguration": { "useApifyProxy": True },
}

# Run the Actor and wait for it to finish
run = client.actor("crawlerbros/toolnut-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": "search",
  "searchQuery": "cordless drill",
  "collectionHandle": "hand-tools",
  "productHandles": [],
  "inStockOnly": false,
  "maxItems": 25,
  "proxyConfiguration": {
    "useApifyProxy": true
  }
}' |
apify call crawlerbros/toolnut-scraper --silent --output-dataset

```

## MCP server setup

```json
{
    "mcpServers": {
        "apify": {
            "type": "http",
            "url": "https://mcp.apify.com/?tools=fetch-actor-details,crawlerbros/toolnut-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/4dhwLQU9SEHqvbHCb/builds/CfjVNIMIkxOK6ULbC/openapi.json
