# Home Depot & Lowe's Scraper - Price & Store Stock (`wrenfield-data/home-depot-lowes-scraper`) Actor

Scrape Home Depot and Lowe's products by keyword, category URL, product URL or item ID: price, was-price, UPC, model, SKU, local store price, in-store stock quantity, aisle/bay, pickup/delivery, specs, images, ratings and optional reviews.

- **URL**: https://apify.com/wrenfield-data/home-depot-lowes-scraper.md
- **Developed by:** [Wrenfield Data](https://apify.com/wrenfield-data) (community)
- **Categories:** E-commerce
- **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 with 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

## Home Depot & Lowe's Scraper - Prices, Store Stock, Aisle & Reviews

**Scrape Home Depot (homedepot.com) and Lowe's (lowes.com) products in one Actor** by search keyword, category or search URL, product URL or item ID. Get the **price, was-price, savings, local store price, in-store stock quantity, aisle and bay, pickup / delivery / ship-to-home availability, UPC, model number, SKU / item #, brand, specifications, description, images, category breadcrumb, rating and review count**. You can also get **customer reviews**.

Use it to compare Home Depot and Lowe's prices, monitor prices and MAP compliance, check local inventory before a store run, track clearance, research products and assortment, or enrich a catalog with UPCs and specs.

- ✅ **Both big-box home-improvement retailers in one run**: search a keyword on both sites, or mix Home Depot and Lowe's URLs and IDs. Every row has `retailer` and the same field names, so you can compare them directly.
- ✅ **Local store price and stock**: enter a ZIP code (or a store number) to get the nearest store's price, **in-store quantity, aisle and bay** for every product.
- ✅ **Gets past bot protection**: both sites use Akamai bot protection. The Actor opens a real browser only to earn a session, then reads the sites' own JSON data with that session. That is faster and cheaper than rendering every page.
- ✅ **Reviews**: get up to thousands of reviews per product, sorted by relevance or newest (Home Depot also: oldest, most helpful, highest or lowest rating).
- ✅ **You only pay for results**: retries, blocked requests, failed products and products that don't exist are free.

💸 **$4 per 1,000 products with details** (price, store stock, aisle, specs), **$2 per 1,000** listing-only products and **$0.50 per 1,000** reviews. Try it on Apify's free plan ($5 of monthly credit, no credit card).

#### Sample output

| Retailer | Product | Price | Rating | Reviews |
|---|---|---|---|---|
| homedepot | 16 oz. Fiberglass Claw Hammer | 14.97 | 4.71 | 609 |
| homedepot | 16 oz. Steel Rip Claw Hammer | 24.97 | 4.69 | 103 |
| homedepot | 20 oz. Hammer | 47.79 | 4.67 | 249 |

<sub>Real rows from the prefilled example run (Oct 19, 2026), 5 of 40+ fields shown. Export as JSON, CSV, Excel or HTML, or read them through the API.</sub>

### What data can you get?

| Field group | Fields |
|---|---|
| Identity | `retailer` (`homedepot` / `lowes`), `itemId`, `sku` (Home Depot store SKU / Lowe's item #), `modelNumber`, `upc`, `title`, `brand`, `url`, `image` |
| Price | `price`, `wasPrice`, `savingsAmount`, `savingsPercent`, `unitPrice`, `currency`; Home Depot also `promotion`, `specialBuy`, `clearancePrice`, `clearancePercentOff`, `priceMessage`; Lowe's also `priceType`, `displayType` |
| Local store | `store` (store ID, name, address, city, state, ZIP, phone), `storeStockQuantity`, `aisle`, `bay`, `storeLimitedStock` (Home Depot) |
| Availability | `availability` object: `online`, `shipToHome`, `delivery`, `pickup`, `shipToStore` / `sameDayDelivery`, `inStore`, `onlineQuantity`, `buyable`, `discontinued`, delivery dates; Home Depot also `storeStatus` (e.g. `ACTIVE`, `CLEARANCE`, `DELETED` = not carried at that store) |
| Ratings | `rating`, `reviewCount` |
| Catalog | `categories` (breadcrumb), `specifications` (group / name / value), `description`, `highlights`, `bullets`, `images` (all), `badges`, `isBundle` (Home Depot "sets") |
| Run info | `detailsScraped`, `source` (which keyword / URL / ID produced the row, page and position), `scrapedAt` |
| Reviews (`type: review`) | `reviewId`, `rating`, `reviewTitle`, `text`, `date`, `author`, `authorLocation`, `recommended`, `helpfulVotes`, `verifiedPurchase`, `incentivized`, `photos` |

### How to use

1. Add **search keywords** (e.g. `cordless drill`, `ceiling fan`) and choose whether to search **Home Depot, Lowe's or both**.
2. And/or add **URLs**: homedepot.com category (`/b/...N-5yc1v...`), search (`/s/...`) or product (`/p/...`) pages; lowes.com category (`/pl/...`), search (`/search?searchTerm=...`) or product (`/pd/...`) pages.
3. And/or add **product IDs**: `hd:205594063` (Home Depot internet # / OMSID), `lowes:1000379005` (Lowe's product ID from the URL) or `lowes:921987` (Lowe's item #).
4. Optional: enter a **ZIP code** for the nearest stores' price, stock and aisle, or a specific **Home Depot / Lowe's store ID**.
5. Optional: turn on **reviews**.
6. Set **Max products** and click **Start**. Download the results as JSON, CSV or Excel, or read them through the API.

### Input example

```json
{
    "searchKeywords": ["cordless drill"],
    "retailer": "both",
    "startUrls": [
        {"url": "https://www.homedepot.com/b/Tools-Hand-Tools-Hammers-Claw-Hammers/N-5yc1vZc98p"},
        {"url": "https://www.lowes.com/pl/power-tools/4294607842"}
    ],
    "productIds": ["hd:205594063", "lowes:1000379005", "https://www.lowes.com/pd/.../5013207487"],
    "maxItems": 100,
    "maxItemsPerQuery": 24,
    "zipCode": "30339",
    "includeDetails": true,
    "includeReviews": true,
    "maxReviewsPerProduct": 20,
    "reviewsSort": "newest"
}
```

- Both sites show 24 products per page. The Actor pages automatically. Home Depot allows about 700 products per search or category; split bigger categories into subcategories.
- **Include product details** (on by default) fetches each product's full data (UPC, specs, description, all images, store stock, aisle). Turn it off for a faster, cheaper **listing-only** scrape with the fields shown in the search grid (title, price, rating, availability, store stock on Lowe's).

### Output example

One Lowe's product row with a store (shortened):

```json
{
    "type": "product",
    "retailer": "lowes",
    "itemId": "5013207487",
    "sku": "4913878",
    "modelNumber": "KDD 2024A-03",
    "upc": "195532000342",
    "title": "Kobalt 24-volt 1/2-in Keyless Brushless Cordless Drill 1 -Batteries Included, and Charger Included",
    "brand": "Kobalt",
    "price": 99, "wasPrice": 159, "savingsAmount": 60, "savingsPercent": 37.7, "currency": "USD",
    "rating": 4.5, "reviewCount": 615,
    "availability": {"online": true, "shipToHome": true, "delivery": true, "pickup": true, "sameDayDelivery": true, "onlineQuantity": 802},
    "storeStockQuantity": 13, "aisle": "65", "bay": "8",
    "store": {"storeId": "1807", "name": "Sandy Springs Lowe's", "city": "Sandy Springs", "state": "GA", "zip": "30328"},
    "categories": ["HARDLINES", "POWER EQUIPMENT", "HANDHELD POWER TOOLS", "KOBALT 24V POWER TOOLS"],
    "specifications": [{"group": "General", "name": "Battery Voltage", "value": "24-volt"}],
    "url": "https://www.lowes.com/pd/.../5013207487",
    "detailsScraped": true,
    "source": {"type": "search", "retailer": "lowes", "input": "cordless drill", "page": 1, "position": 1}
}
```

One Home Depot product row with a store (shortened):

```json
{
    "type": "product",
    "retailer": "homedepot",
    "itemId": "315048673",
    "sku": "1004655426",
    "modelNumber": "N-A16SHK",
    "upc": "6940989322097",
    "title": "16 oz. Steel Rip Claw Hammer",
    "brand": "Husky",
    "price": 24.97, "wasPrice": null, "currency": "USD",
    "rating": 4.69, "reviewCount": 100,
    "availability": {"online": true, "shipToHome": true, "delivery": true, "pickup": true, "inStore": true, "onlineQuantity": 43, "storeStatus": "ACTIVE"},
    "storeStockQuantity": 10, "aisle": "14", "bay": "014",
    "store": {"storeId": "121", "name": "Cumberland", "city": "Atlanta", "state": "GA", "zip": "30339"},
    "categories": ["Tools", "Hand Tools", "Hammers", "Claw Hammers"],
    "url": "https://www.homedepot.com/p/16-oz-Steel-Rip-Claw-Hammer-N-A16SHK/315048673"
}
```

One review row:

```json
{"type": "review", "retailer": "lowes", "itemId": "5013915503", "reviewId": "272540226", "rating": 5, "reviewTitle": "Great tools", "text": "I am extremely happy with every Bosch tool I have purchased...", "date": "2026-10-02T22:09:01.000Z", "author": "Impressed", "recommended": true, "helpfulVotes": 0}
```

Each row has a `type`: `product`, `review` or `error`. Error rows tell you which input failed and why (for example "not found"); they are free. The dataset has the views **Products**, **Store stock** and **Reviews**. A run summary is saved to the key-value store as `SUMMARY`. It includes success rates per retailer, the stores your ZIP resolved to, and request statistics.

### Local prices and stock (ZIP code or store ID)

Both retailers show store-specific prices and stock. If you set `zipCode`, the Actor finds the **nearest Home Depot and the nearest Lowe's store** to that ZIP and uses them for every product. `homeDepotStoreId` / `lowesStoreId` pick an exact store instead (you can find the store number on the retailer's store page). Each row's `store` object shows which store the price and stock refer to. Without a ZIP or store, you get the online (national) price, and store fields are empty.

### Reliability - how it works

Home Depot and Lowe's both use Akamai Bot Manager. Plain HTTP scrapers and headless browsers get "Access Denied" pages or empty answers. This Actor:

1. **Earns a real session once, then reuses it.** A real browser (Chrome for Home Depot, Firefox for Lowe's search pages) opens one page through a US residential IP, so the bot check passes and sets its cookies. Many fast API requests then reuse that session. Images, fonts and third-party scripts are blocked to keep traffic low.
2. **Reads the sites' own data.** Home Depot data comes from the same GraphQL API the website uses. Lowe's data comes from its product JSON and the page state. There are no fragile HTML selectors.
3. **Picks the cheapest route that works.** Lowe's product data is tried on datacenter IPs first and moves to residential IPs and browser sessions only when needed. Routes that keep failing are switched off for the rest of the run, and blocked requests are retried with a new IP and session.
4. **Isolates errors per item.** A product that fails never stops the run. If a product's details can't be loaded, you still get its search-grid data (`detailsScraped: false`). Products that don't exist are reported as free `error` rows.

**Measured on the Apify platform (October 2026)** with default settings:

| Test | Result | Time |
|---|---|---|
| Volume: keyword "ceiling fan" on both sites, ZIP 98101 (nearest store), full details | **100/100 products** (50 Home Depot + 50 Lowe's), all with price, UPC and store stock | 137 s |
| Home Depot keyword + ZIP 30339 + 5 reviews per product | **20/20 products, 100 reviews**, store stock on all 20 | 32 s |
| Lowe's category URL + store 1845 | **20/20 products** with store stock, aisle and bay | 118 s |
| Mixed product URLs and IDs (Home Depot and Lowe's) + a search URL + store 121 | **10/10 existing products**; 2 fake IDs correctly reported as not found | 113 s |
| Listing-only, keyword "paint roller" on both sites | **49/49 products** | 74 s |
| Lowe's keyword + ZIP 30339 + 3 reviews per product | **9/9 products, 27 reviews** | 114 s |

### Pricing

This Actor uses **pay-per-event** pricing, so you pay only for results. See the **Pricing** tab for the current prices of these events:

| Event | When it is charged |
|---|---|
| `product-result` | Each product with full details |
| `listing-result` | Each listing-only product (details turned off, or the rare product whose details could not be loaded) |
| `review-result` | Each review |
| `actor-start` | Once per run |

Retries, blocked requests, failed products and products that don't exist are **free**. Proxy and compute costs are included. Set **Maximum cost per run** in the run options to cap your spend. The Actor stops cleanly at that limit and keeps everything it scraped so far. It also respects the **maximum number of paid results** you set.

### Related tools

Track the same products at Walmart and across Google Shopping sellers.

- [Walmart Scraper](https://apify.com/wrenfield-data/walmart-product-scraper): Walmart prices, stock, sellers and reviews
- [Google Shopping Price Comparison](https://apify.com/wrenfield-data/google-shopping-price-comparison): compare seller prices for any product or UPC
- [Shopify Store Scraper & Price Monitor](https://apify.com/wrenfield-data/shopify-store-scraper): full catalogs and price/stock change alerts for any Shopify store

All of these are maintained by the same developer and export flat JSON, CSV or Excel, so you can feed one tool's dataset into the next.

### FAQ

**Is there an official Home Depot or Lowe's API?**
Not for the public. Home Depot and Lowe's have APIs for suppliers and partners only. This Actor gives you the data any shopper sees on homedepot.com and lowes.com as structured JSON, CSV or Excel. You can use it through the Apify API, schedules, webhooks and integrations.

**How do I compare Home Depot and Lowe's prices for the same product?**
Search the same keyword on both retailers, then match rows by `upc` or `modelNumber`. Both fields are filled for most products when details are on.

**How do I check if a product is in stock at my local store?**
Enter your ZIP code (or the store number). Every row then has `storeStockQuantity`, `availability.pickup`, and `aisle` / `bay`.

**Can I monitor prices daily?**
Yes. Save your product IDs or category URLs as a task, schedule it, and compare `price`, `wasPrice`, `storeStockQuantity` and `availability` between runs.

**Where do I find a product ID?**
It's the number at the end of the product URL. For example, `homedepot.com/p/.../205594063` is `hd:205594063`, and `lowes.com/pd/.../1000379005` is `lowes:1000379005`. You can also paste the full URL. Lowe's "Item #" numbers shown on the page (for example `lowes:921987`) work too.

**Why are some prices empty?**
Some Home Depot bundles ("sets", `isBundle: true`) and products sold only in some regions don't have a single price. Products shown as "See price in cart" may also have no price. Store fields are empty when you don't set a ZIP or store.

**Why is the run slower at the start?**
The first request to each site opens a browser session to pass the bot check. That takes 10-40 seconds. After that, products load in parallel.

**Does it work for Home Depot Canada or Mexico?**
No. It supports homedepot.com and lowes.com (US) only.

**Can I use it from Python, Make, Zapier, n8n or an AI agent?**
Yes. Call the Actor through the Apify API, the Python or JavaScript client, the Apify MCP server or any Apify integration, then read the dataset items.

**Is scraping Home Depot and Lowe's legal?**
This Actor only collects public data that anyone can see without logging in. Review rows include the public nickname the reviewer chose. Both retailers' terms of use restrict automated access, and laws differ by country and use case. Make sure your use complies with them, and handle any personal data according to GDPR, CCPA and similar laws. If you're unsure, ask a lawyer.

# Actor input Schema

## `searchKeywords` (type: `array`):

Keywords to search, one per line (e.g. <code>cordless drill</code>, <code>claw hammer</code>). Each keyword is searched on the retailer(s) chosen below and returns up to <i>Max products per search/category</i> products from each.

## `retailer` (type: `string`):

Where to search the keywords. URLs and prefixed item IDs always go to the retailer they belong to.

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

homedepot.com category pages (<code>/b/...N-5yc1v...</code>), search pages (<code>/s/drill</code>) or product pages (<code>/p/...</code>); lowes.com category pages (<code>/pl/...</code>), search pages (<code>/search?searchTerm=...</code>) or product pages (<code>/pd/...</code>).

## `productIds` (type: `array`):

One per line: product URLs, or IDs with a prefix - <code>hd:205594063</code> (Home Depot internet # / OMSID), <code>lowes:1000379005</code> (Lowe's product ID from the URL) or <code>lowes:921987</code> (Lowe's item #). Bare 9-digit numbers are treated as Home Depot IDs, other numbers as Lowe's.

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

Maximum number of product rows for the whole run (reviews are not counted). Duplicates across inputs are skipped.

## `maxItemsPerQuery` (type: `integer`):

How many products to take from each keyword (per retailer) or category URL. Both sites show 24 products per page; Home Depot allows paging to about 700 products per search.

## `includeDetails` (type: `boolean`):

Fetch each product's detail data: UPC, model, specifications, description, all images, categories, fulfillment and aisle/bay. Turn off for a faster listing-only scrape (title, price, rating, stock from the search grid).

## `zipCode` (type: `string`):

Optional 5-digit US ZIP. The nearest Home Depot and Lowe's stores are used for local price, in-store stock quantity and aisle/bay. Leave empty for online (national) prices.

## `homeDepotStoreId` (type: `string`):

Optional Home Depot store number (e.g. <code>121</code>), overrides the ZIP lookup. Shown on homedepot.com store pages.

## `lowesStoreId` (type: `string`):

Optional Lowe's store number (e.g. <code>1807</code>), overrides the ZIP lookup. Recommended for Lowe's - faster and more reliable than a ZIP search.

## `includeReviews` (type: `boolean`):

Also output customer reviews for every product (one row per review, type = review).

## `maxReviewsPerProduct` (type: `integer`):

Reviews are fetched 10 per request.

## `reviewsSort` (type: `string`):

Lowe's supports only most relevant and newest; other options fall back to most relevant there.

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

Defaults to Apify Proxy: datacenter IPs where they work (Lowe's product data) and US residential IPs with real-browser sessions where they are required (Home Depot, Lowe's search pages).

## `residentialFallback` (type: `boolean`):

Use US residential IPs when datacenter IPs are blocked. Required for Home Depot.

## `useBrowserSessions` (type: `boolean`):

Open a real browser once per proxy session to pass the sites' bot protection, then reuse its cookies for fast API requests. Turning this off makes Home Depot and Lowe's search pages fail.

## `maxConcurrency` (type: `integer`):

Parallel requests.

## `maxRetries` (type: `integer`):

Blocked requests are retried with a new IP and session.

## Actor input object example

```json
{
  "retailer": "both",
  "startUrls": [
    {
      "url": "https://www.homedepot.com/b/Tools-Hand-Tools-Hammers-Claw-Hammers/N-5yc1vZc98p"
    }
  ],
  "productIds": [
    "hd:205594063",
    "lowes:1000379005"
  ],
  "maxItems": 4,
  "maxItemsPerQuery": 24,
  "includeDetails": true,
  "includeReviews": false,
  "maxReviewsPerProduct": 20,
  "reviewsSort": "relevance",
  "proxyConfiguration": {
    "useApifyProxy": true
  },
  "residentialFallback": true,
  "useBrowserSessions": true,
  "maxConcurrency": 8,
  "maxRetries": 8
}
```

# Actor output Schema

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

No description

## `reviews` (type: `string`):

No description

## `allRows` (type: `string`):

No description

## `summary` (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.homedepot.com/b/Tools-Hand-Tools-Hammers-Claw-Hammers/N-5yc1vZc98p"
        }
    ],
    "productIds": [
        "hd:205594063",
        "lowes:1000379005"
    ],
    "maxItems": 4,
    "proxyConfiguration": {
        "useApifyProxy": true
    }
};

// Run the Actor and wait for it to finish
const run = await client.actor("wrenfield-data/home-depot-lowes-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 = {
    "startUrls": [{ "url": "https://www.homedepot.com/b/Tools-Hand-Tools-Hammers-Claw-Hammers/N-5yc1vZc98p" }],
    "productIds": [
        "hd:205594063",
        "lowes:1000379005",
    ],
    "maxItems": 4,
    "proxyConfiguration": { "useApifyProxy": True },
}

# Run the Actor and wait for it to finish
run = client.actor("wrenfield-data/home-depot-lowes-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 '{
  "startUrls": [
    {
      "url": "https://www.homedepot.com/b/Tools-Hand-Tools-Hammers-Claw-Hammers/N-5yc1vZc98p"
    }
  ],
  "productIds": [
    "hd:205594063",
    "lowes:1000379005"
  ],
  "maxItems": 4,
  "proxyConfiguration": {
    "useApifyProxy": true
  }
}' |
apify call wrenfield-data/home-depot-lowes-scraper --silent --output-dataset

```

## MCP server setup

```json
{
    "mcpServers": {
        "apify": {
            "type": "http",
            "url": "https://mcp.apify.com/?tools=fetch-actor-details,wrenfield-data/home-depot-lowes-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/we1z2mLnpPDSfZvaM/builds/IUDBgagz63hsurtIw/openapi.json
