# Home Depot Scraper — Products, Prices & Reviews (`tortuga/home-depot-scraper`) Actor

Scrape Home Depot products from homedepot.com by keyword, category or product URL: title, brand, model, price, sale price, rating, review count, stock, images, specifications and reviews.

- **URL**: https://apify.com/tortuga/home-depot-scraper.md
- **Developed by:** [Trevor Ortega](https://apify.com/tortuga) (community)
- **Categories:** E-commerce
- **Security:** Limited permissions
- **Stats:** 2 total users, 1 monthly users, 100.0% runs succeeded, 0 bookmarks
- **User rating**: No ratings yet

## Pricing

from $4.00 / 1,000 products

This Actor is paid per event and usage. You are charged both the fixed price for specific events and for Apify platform usage.

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 Scraper: Products, Prices & Reviews

Scrape Home Depot products from homedepot.com by keyword, category or product URL: title, brand, model, price, sale price, rating, review count, stock, images, specifications and reviews. Every product comes with its strike-through price and savings, price per unit (flooring, lumber), promotion label and sale dates, store pickup / ship-to-home / express delivery availability with quantities, badges (Best Seller, Top Rated, Exclusive, New), category path, variants, rank on the page and sponsored flag. Turn on product details for the description, highlights, the full specification table, every image, videos, manuals, UPC / GTIN, dimensions and the 1-5 star breakdown; set a number of reviews per product for the review texts.

No headless browser and no login on your side: the Actor reads the JSON state that homedepot.com embeds in its own pages, so one request returns a whole results page. Download the results as JSON, CSV or Excel, or pull them through the API into your own app, Google Sheets or an LLM pipeline. You pay per item you get.

See also the companion [Lowe's Scraper](https://apify.com/tortuga/lowes-scraper) and [Walmart Scraper](https://apify.com/tortuga/walmart-scraper), built the same way.

### What data does Home Depot Scraper extract?

Every product from a search or category page (the `result` event):

| Field | Description |
|---|---|
| `type` | `"product"` |
| `itemId`, `storeSku`, `modelNumber`, `parentId` | Home Depot's product id (the number at the end of `/p/.../322138372`, also called OMSID), the store SKU (`1008373177`), the manufacturer model (`DCD794D1`) and the parent id of products with options |
| `title`, `brand`, `url` | Product title as shown on the tile (brand + name), brand, canonical product URL |
| `imageUrl`, `images` | Main image and all images Home Depot lists for the tile, in the largest size (1000 px) |
| `price`, `originalPrice`, `savingsAmount`, `savingsPercent`, `currency` | Current price, strike-through price when the product is on sale, the difference and the percentage, `USD` |
| `unitOfMeasure`, `pricePerUnit` | `each` or `case`, and `{price, originalPrice, unit, unitsPerCase}` when Home Depot shows a per-unit price (`2.98 / sq. ft.`, `20.1 sq. ft. per case`) |
| `priceMessage` | `"see final price in cart"` for products whose price Home Depot hides on the page (MAP pricing); `price` is `null` for them |
| `clearancePrice`, `promotionLabel`, `promotionType` | Clearance price when there is one; the promotion Home Depot shows (`Special Buys`, `New Lower Prices`), its type (`DISCOUNT`) |
| `saleStartDate`, `saleEndDate` | When the sale price starts and ends (`2027-01-31`); on search tiles usually with product details only |
| `rating`, `reviewCount` | Average rating (0-5) and number of ratings |
| `availability`, `inStock` | `IN_STOCK` / `OUT_OF_STOCK` / `DISCONTINUED` / `UNKNOWN` and a boolean; `UNKNOWN` when the page carried no stock data (see "How reliable is it") |
| `availabilityType`, `discontinued`, `backordered`, `freeShipping` | Home Depot's own type (`Shared`, `Online`, `Browse Only`), flags, free ship-to-home |
| `deliveryOptions` | One row per fulfillment service: `{method: pickup \| delivery, service: bopis \| boss \| sth \| express delivery, serviceName, inStock, quantity, limitedQuantity, location, locationId, freeShipping, deliveryTimeline, deliveryDate, charge}` (store pickup with the store's quantity, ship to store, ship to home with the network quantity, express delivery) |
| `badges` | `Best Seller`, `Top Rated`, `Exclusive`, `New`, `Tool Savings`, ... |
| `isSponsored` | `true` for sponsored tiles (2-3 per page) |
| `categories`, `category` | Category path (`["Tools", "Power Tools", "Drills", "Power Drills"]`) and the leaf category |
| `collection` | The collection / family the product belongs to (`{id, name, url}`) |
| `variantCount`, `variants` | Number of colors / sizes / options and the color swatches the tile lists (`{itemId, name, url, imageUrl, isSelected}`; each variant is its own product page) |
| `isBundle`, `productType` | `true` for configurable bundles (`/p/sets/...`); `MERCHANDISE` or `CONFIGURABLE_BUNDLE` |
| `returnable`, `quantityLimit` | Return window (`90-Day`), purchase limit |
| `store` | The Home Depot store the page was priced for: `{storeId, storeName, zipCode}` (see "Which store do the prices come from?"). With the **Store number** input also `requestedStoreId` and `locationApplied` |
| `position`, `page`, `searchTerm`, `sourceUrl`, `scrapedAt`, `lightData` | Rank among the tiles of the page (ads included), page number, provenance, and whether the page came without stock and badge data |

With **Include product details** on, or for product URLs (the extra `detail` event), each product also gets:

| Field | Description |
|---|---|
| `description`, `highlights`, `bullets` | Full description as plain text, the 3 highlight lines, the feature bullets |
| `specifications`, `specificationGroups`, `keyFeatures` | The complete specification table as a dict (`{"Chuck Size (In.)": "1/2 In.", ...}`), grouped the way the page shows it (`Details`, `Dimensions`, `Warranty / Certifications`), and the key features |
| `images`, `videos`, `documents` | All product images; videos (`{title, url, thumbnailUrl}`); manuals, warranties, SDS and other PDFs (`{name, url}`) |
| `upc`, `gtin`, `brandUrl`, `color`, `dimensions` | Barcodes, the brand's page, color, `{depth, height, width, weight}` as Home Depot states them (`"12 in"`, `"4.95 lb"`) |
| `pageTitle`, `seoDescription`, `prop65Warning` | The product page title, meta description, California Prop 65 flag |
| `ratingCounts`, `recommendedCount`, `notRecommendedCount`, `questionCount` | 1-5 star breakdown (`{"5": 10304, "4": 1342, ...}`), recommendation counts, number of customer questions |
| `price`, `originalPrice`, `saleStartDate`, `saleEndDate`, `badges` | The product page's own price and sale dates; badges with their labels |

With **Max reviews per product** above 0, or for review-page URLs (the `review` event), one item per review:

| Field | Description |
|---|---|
| `type` | `"review"` |
| `itemId`, `productName`, `productUrl` | Product the review belongs to |
| `reviewId`, `rating`, `title`, `text`, `submittedAt` | Review id, stars (1-5), title, text, ISO date-time |
| `reviewerName`, `reviewerLocation` | Reviewer nickname and location as Home Depot shows them above the review (`"BennieBeeker"`, `"Austin, TX"`; `"HomeDepotCustomer"` for anonymous ones) |
| `recommended`, `verifiedPurchase`, `badges` | "Would recommend" flag; verified-purchase flag (currently `null`: Home Depot's page data does not carry it per review, only in the totals); badge names |
| `positiveFeedback`, `negativeFeedback` | Helpful / not helpful votes |
| `photosCount`, `photos`, `videos` | Customer photos and videos |
| `secondaryRatings`, `pros`, `cons` | Secondary ratings (`{"Quality": 4, "Value": 5}`), pros / cons tags |
| `sellerResponse`, `sellerResponseDate`, `sellerResponseBy` | Brand reply when present (`"DewaltProductExpert"`) |
| `syndicated`, `syndicatedFrom` | Reviews syndicated from the brand's site or Home Depot Canada (`"dewalt.com"`, `"homedepot.ca"`) |

Reviewer avatars are not collected, and neither is the internal author id that Home Depot's review data carries but never shows.

### How to scrape Home Depot products

1. Type one or more **Search terms** (one per line) and/or paste **Start URLs**: search pages, category pages, product pages or review pages.
2. Set **Max items** to cap the run (and the cost). Products and reviews both count.
3. Set **Max pages per search** (24 products per search page, 12 per category page).
4. Turn on **Include product details** and/or set **Max reviews per product** only if you need them: each costs extra requests and events (see below).
5. Click **Start**. Results appear in the **Dataset** tab; export from there or use the API.

### Which Home Depot URLs work

| URL | What you get |
|---|---|
| `https://www.homedepot.com/s/air%20fryer` | Search results, 24 products per page. Home Depot answers some terms with one of its category pages instead (`cordless drill` opens "Cordless Drills"); those have 12 products per page |
| `https://www.homedepot.com/b/Tools-Power-Tools-Drills/N-5yc1vZc27f` | Category page, including any filters (`/Cordless/N-5yc1vZc27fZ1z140i3`) and sort parameters you set on the site |
| `https://www.homedepot.com/p/DEWALT-Atomic-20V-.../322138372` | One product with full details (`/p/<id>` without the slug works too) |
| `https://www.homedepot.com/p/reviews/DEWALT-Atomic-20V-.../322138372/1` | Reviews only, from that page on (30 per page) |

Department landing pages (`/c/...`) and collection pages have no product list and are skipped with an error. A mistyped category URL gets Home Depot's "We're fixing it" page, which is reported as an error too.

### Input example

```json
{
  "searchTerms": ["air fryer"],
  "startUrls": [
    { "url": "https://www.homedepot.com/p/DEWALT-Atomic-20V-Lithium-Ion-Cordless-Compact-1-2-in-Drill-Driver-Kit-with-2-0Ah-Battery-and-Charger-DCD794D1/322138372" }
  ],
  "maxItems": 100,
  "maxPagesPerSearch": 3,
  "includeSponsored": true,
  "includeDetails": false,
  "maxReviewsPerProduct": 0,
  "proxyConfiguration": { "useApifyProxy": true, "apifyProxyGroups": ["UNBLOCKER"], "apifyProxyCountry": "US" }
}
```

### Output example

A product from a search page:

```json
{
  "type": "product",
  "itemId": "329550753",
  "storeSku": "1011175376",
  "modelNumber": "AF141",
  "parentId": "329550753",
  "productType": "MERCHANDISE",
  "isBundle": false,
  "title": "NINJA 5 qt. Black Stainless Steel Air Fryer Pro with Air Fry Roast Reheat and Dehydrate",
  "brand": "NINJA",
  "url": "https://www.homedepot.com/p/NINJA-5-qt-Black-Stainless-Steel-Air-Fryer-Pro-with-Air-Fry-Roast-Reheat-and-Dehydrate-AF141/329550753",
  "imageUrl": "https://images.thdstatic.com/productImages/0291fec2-bebd-4dfe-b564-3d96bbdcc4e6/svn/black-ninja-air-fryers-af141-64_1000.jpg",
  "images": ["https://images.thdstatic.com/productImages/0291fec2-bebd-4dfe-b564-3d96bbdcc4e6/svn/black-ninja-air-fryers-af141-64_1000.jpg"],
  "price": 89.99,
  "originalPrice": 129.99,
  "savingsAmount": 40.0,
  "savingsPercent": 31,
  "currency": "USD",
  "unitOfMeasure": "each",
  "pricePerUnit": null,
  "priceMessage": null,
  "clearancePrice": null,
  "promotionLabel": "Special Buys",
  "promotionType": null,
  "saleStartDate": null,
  "saleEndDate": null,
  "rating": 4.78,
  "reviewCount": 133,
  "availability": "IN_STOCK",
  "inStock": true,
  "availabilityType": "Shared",
  "discontinued": false,
  "backordered": false,
  "freeShipping": true,
  "deliveryOptions": [
    { "method": "pickup", "service": "boss", "serviceName": "Ship to store", "inStock": true, "quantity": 66, "limitedQuantity": false, "location": "Tuscaloosa", "locationId": "877", "freeShipping": false, "deliveryTimeline": null, "deliveryDate": null, "charge": null },
    { "method": "delivery", "service": "sth", "serviceName": "Ship to home", "inStock": true, "quantity": 66, "limitedQuantity": false, "location": "online", "locationId": "8119", "freeShipping": true, "deliveryTimeline": "later", "deliveryDate": "2026-11-03", "charge": 0 }
  ],
  "badges": ["Best Seller"],
  "isSponsored": false,
  "categories": ["Appliances", "Small Kitchen Appliances", "Air Fryers"],
  "category": "Air Fryers",
  "collection": null,
  "variantCount": null,
  "variants": [],
  "returnable": "90-Day",
  "quantityLimit": null,
  "lightData": false,
  "position": 1,
  "page": 1,
  "store": { "storeId": "877", "storeName": "Tuscaloosa", "zipCode": "35404" },
  "searchTerm": "air fryer",
  "sourceUrl": null,
  "scrapedAt": "2026-11-01T18:49:10+00:00"
}
```

With `includeDetails: true` a product additionally carries, for example:

```json
{
  "description": "Unlock power in a compact size with the ATOMIC COMPACT SERIES 20V MAX 1/2 in. Drill/Driver. Get up to 16% more power for a variety of drilling applications in tight spaces ...",
  "highlights": ["Lightweight 2.75 lbs. and Compact at 5.88in Front to Back Design", "Includes (1) 20V. 2.0Ah Battery and Charger", "Compatible w/ All (200+) DEWALT 20V MAX Batteries & Chargers"],
  "bullets": ["OUR SHORTEST 20V MAX DRILL/DRIVER at 5.88 in. (tool head length only) to access hard to reach areas", "GET UP TO 16% MORE POWER for a variety of drilling applications", "..."],
  "specifications": { "Battery Amp Hours": "2 Ah", "Battery Voltage (V)": "20V", "Chuck Size (In.)": "1/2 In.", "Chuck Type": "Keyless", "Motor Type": "Brushless", "Maximum Torque (in-lbs)": "404", "Product Weight (lb.)": "2.75 lb", "Manufacturer Warranty": "3 Year Limited Warranty" },
  "specificationGroups": { "Details": { "Battery Amp Hours": "2 Ah" }, "Warranty / Certifications": { "Manufacturer Warranty": "3 Year Limited Warranty" }, "Dimensions": { "Product Depth (in.)": "12 in", "Product Height (in.)": "9 in", "Product Width (in.)": "3.25 in" } },
  "keyFeatures": { "Battery Voltage (V)": "20V", "Chuck Size (In.)": "1/2 In.", "Cordless/Corded": "Cordless", "Motor Type": "Brushless" },
  "documents": [{ "name": "Use and Care Manual", "url": "https://images.thdstatic.com/catalog/pdfImages/9f/9f36dc1a-2313-4520-8348-d76761b531f5.pdf" }, { "name": "Warranty", "url": "https://images.thdstatic.com/catalog/pdfImages/6e/6e0f6c41-7815-4235-91b9-73e9ab91053d.pdf" }],
  "videos": [{ "title": "Atomic Phase 2", "url": "https://fastly-signed-us-east-1-prod.brightcovecdn.com/media/v1/pmp4/static/clear/66036796001/.../main.mp4", "thumbnailUrl": "https://cf-images.us-east-1.prod.boltdns.net/v1/static/66036796001/.../image.jpg" }],
  "images": ["https://images.thdstatic.com/productImages/043ec0c7-5003-4f12-ac48-2456c1cea28c/svn/dewalt-power-drills-dcd794d1-64_1000.jpg", "..."],
  "upc": "885911904810",
  "gtin": "0885911904810",
  "brandUrl": "https://www.homedepot.com/b/DEWALT/N-5yc1vZ4j2",
  "dimensions": { "depth": "12 in", "height": "9 in", "width": "3.25 in", "weight": "4.95 lb" },
  "pageTitle": "DEWALT Atomic 20V Lithium-Ion Cordless Compact 1/2 in. Drill/Driver Kit with 2.0Ah Battery and Charger DCD794D1",
  "saleStartDate": "2026-10-26",
  "saleEndDate": "2027-01-31",
  "ratingCounts": { "5": 10304, "4": 1342, "3": 237, "2": 167, "1": 342 },
  "recommendedCount": 2211,
  "notRecommendedCount": 244,
  "questionCount": 428
}
```

A review:

```json
{
  "type": "review",
  "itemId": "322138372",
  "reviewId": "305172414",
  "rating": 4,
  "title": "Lots of power in a compact package",
  "text": "Can't beat this little fella. My DeWalt 7.6v died after 10's of 1000's of screws. ... I knocked off I've star because I feel like the highest torque setting (15) isn't high enough.",
  "submittedAt": "2026-08-03T02:47:40+00:00",
  "reviewerName": "BennieBeeker",
  "reviewerLocation": "Austin, TX",
  "recommended": true,
  "verifiedPurchase": null,
  "badges": [],
  "positiveFeedback": 0,
  "negativeFeedback": 0,
  "photosCount": 1,
  "photos": ["https://photos-us.bazaarvoice.com/photo/2/cGhvdG86aG9tZWRlcG90/c11acf0c-3b6a-531f-bdc9-2c5c3bcdecec"],
  "videos": [],
  "secondaryRatings": { "Quality": 4, "Value": 5 },
  "pros": null,
  "cons": null,
  "sellerResponse": null,
  "sellerResponseDate": null,
  "sellerResponseBy": null,
  "syndicated": false,
  "syndicatedFrom": null,
  "productName": "Atomic 20V Lithium-Ion Cordless Compact 1/2 in. Drill/Driver Kit with 2.0Ah Battery and Charger",
  "productUrl": "https://www.homedepot.com/p/DEWALT-Atomic-20V-Lithium-Ion-Cordless-Compact-1-2-in-Drill-Driver-Kit-with-2-0Ah-Battery-and-Charger-DCD794D1/322138372",
  "scrapedAt": "2026-11-01T18:49:10+00:00"
}
```

### Proxy note

homedepot.com answers datacenter and residential proxy traffic with an Akamai error page, so this Actor uses **Apify's Unblocker proxy** (group `UNBLOCKER`, US) by default. The Unblocker is billed to your Apify account per request: 10 Unblocker units, about **$0.0015 on the free plan** and less on paid plans, for every attempt the Actor makes, including the occasional one the proxy cannot complete (HTTP 502, retried automatically up to two times). One request returns a results page (24 products, 12 on category pages), one product page, or 30 reviews. The proxy renders the pages in a browser, which takes 7-75 seconds per page.

The Actor is built around that price: it requests a further result page only when **Max items** still needs it, opens product pages and review pages only when you ask for them, and reads the 10 reviews a product page already embeds before requesting a reviews page. The `SUMMARY` record in the run's key-value store reports `successfulRequests`, so you can check the proxy cost of every run. You can switch to another proxy group in the input; the Actor then retries block pages on fresh IPs and reports them as `blockedPages`.

### How much does it cost

Pay per event, no subscription: **$0.004 per product**, **+ $0.012 per product page opened** (details), **$0.001 per review**, plus the proxy requests above and a few cents of platform usage per thousand items. Worked example for 100 products from one search, on the free plan:

| Run | Requests (proxy cost) | Events | Total |
|---|---|---|---|
| 100 products, search data only | 5 search pages ($0.0075) | 100 x $0.004 = $0.40 | about $0.41 |
| + product details | + 100 product pages ($0.15) | + 100 x $0.012 = $1.20 | about $1.76 |
| + 10 reviews per product (set Max items to 1,100) | no extra request: the product page embeds them | + 1,000 x $0.001 = $1.00 | about $2.76 |
| + 30 reviews per product (set Max items to 3,100) | + 100 review pages ($0.15) | + 3,000 x $0.001 = $3.00 | about $4.91 |

Search data alone is by far the cheapest per product: one $0.0015 request brings 24 products with prices, ratings, stock and delivery options. Turn details and reviews on only for the products you need them for, for example by running a second pass on product URLs you selected from the first dataset. Listings that are not delivered (a blocked page, a timed-out request) are not charged. Measured on our test runs: the default input (one search page, 10 products) used 10 Unblocker units and $0.002 of platform usage; 3 products with details (4 requests) used 40 units and $0.008.

### How reliable is it

Home Depot sits behind Akamai Bot Manager and blocks some requests even through the Unblocker: in our tests 2 of 18 requests came back as HTTP 502 after 30-50 seconds (each attempt is billed by the proxy) and succeeded on the retry. The Actor retries such answers (two more attempts) and reports what happened in the `SUMMARY` record (`http.statuses`, `blockedPages`, `pagesWithoutData`, `successfulRequests`). A search page takes 7-75 seconds through the proxy (usually 15-40), a product page 12-55 seconds, a reviews page about 8 seconds; a run with one search page finished in 16-22 seconds in our test runs, one with details for 3 products in 2 minutes. Items that are not delivered are not charged.

Two things to know about the data itself. First, Home Depot prices and stocks products per store, and the proxy's exit IP decides which store answers (see the next section): the same search can come back priced for Atlanta on one run and for Tuscaloosa on the next, and page 2 can repeat a few products of page 1 (the Actor deduplicates them). Second, now and then the proxy returns a category page before Home Depot's stock and badge data loaded: prices, ratings and images are present, `availability` is `UNKNOWN`, `deliveryOptions` is empty and the item is marked `lightData: true`. Product pages never carry store stock, so product URLs and details have `availability: UNKNOWN` unless the product is discontinued, while products found through a search keep the stock data of their search tile. We check the Actor daily with a live run.

### Monitor Home Depot prices on a schedule

Turn on **Only new or changed items** and the Actor remembers what earlier runs of the same input returned: each run outputs only products that are new in the results or whose `price`, `originalPrice` (a sale starting or ending) or `availability` changed. Unchanged products are dropped before anything is saved and before any product or review page is requested, so they cost neither events nor Unblocker requests (a monitored search costs one proxy request per results page checked). **Max items** becomes the watched window: the first products of the listing are checked every run (for example 24 = one search page); turn **Include sponsored products** off so rotating ads do not show up as new products. Save the input as a task and add a Schedule to it in Apify Console (Schedules → Create new, daily). Every output item carries `changeType` (`new` or `changed`), and changed products carry `previousValues`, e.g. `{"price": 129.99}` for a product that dropped to $89.99. **Monitoring key** keeps several schedules on the same search separate. Because prices and stock are per store, a run that lands in another store can report changes that are store differences rather than price moves; `store` on every item shows which store answered. In our verification two consecutive runs of the same search, answered by two different stores, reported 0 changes among 24 products.

### Which store do the prices come from?

Home Depot prices and stocks products per store, and many results depend on it: lumber and other local goods have different prices and pickup quantities from store to store, delivery dates differ, and even the set and order of products on a results page change. Without a **Store number** the Actor lets Home Depot assign a store to each request from the proxy's exit IP (Atlanta, Tuscaloosa and West Virginia stores in our runs), so the same search can be priced for a different store on every run. Product pages are priced for Home Depot's online store (8119). Every product carries the store context in `store` and in the `deliveryOptions` rows (`location`, `locationId`), so you can verify it.

To track one store, enter its number in **Store number** (`storeId`), for example `121` for Cumberland (Atlanta) or `2702` for Warren, Michigan. You find a store's number at the end of its page address on homedepot.com (`/l/<city>/<state>/<id>`). Search and category pages are then requested for that store, and each product also records `requestedStoreId` and `locationApplied` (`true` when Home Depot answered for the store you asked for). The store is applied by the proxy's browser on most but not all requests; when a page comes back for another store the Actor requests it once more, and if it still does not match, the items are saved with `locationApplied: false` and the store that really answered in `store`. Filter on `locationApplied` if you need strictly one store. There is no ZIP code input, because Home Depot's store finder cannot be used without a browser session. A monitoring watch keeps a separate history for each store, since the input differs.

In our test, a search for "2x4 lumber" priced for Warren, MI and Cumberland, GA showed a 2 in. x 4 in. x 10 ft. board at $9.08 against $8.38, pickup stock of 220 against 186, and 13 of 24 products different between the two stores.

### How to scrape Home Depot reviews

Set **Max reviews per product** (reviews for every product found), or paste review-page URLs such as `https://www.homedepot.com/p/reviews/DEWALT-Atomic-20V-Lithium-Ion-Cordless-Compact-1-2-in-Drill-Driver-Kit-with-2-0Ah-Battery-and-Charger-DCD794D1/322138372/1` to get reviews only. With product details on, the first 10 reviews come free with the product page; beyond that the reviews page serves 30 per request. Reviews come in Home Depot's own order: reviews with photos first, newest first within each group. Syndicated reviews (from the brand's site or Home Depot Canada) are included and flagged. For monitoring, deduplicate on `reviewId`.

### Does it work without login or a browser?

Yes. Everything comes from public pages as an anonymous visitor sees them; you do not run a browser, the Unblocker proxy does. No account, no cookies on your side. Pro Xtra member prices and in-cart prices are not available.

### Integrations and API

Use the run in Zapier, Make, n8n, Google Sheets, or call it from Python/Node with the Apify client. See the **API** tab for ready-made snippets.

### Is it legal to scrape Home Depot

This Actor collects only data that Home Depot shows publicly to logged-out visitors: product listings, prices, stock, and the text, rating, reviewer nickname and location of customer reviews, as the review page shows them. It does not log in and does not collect avatars, contact details or the hidden author ids in Home Depot's review data. Reviewer nicknames and locations, and review texts written by individuals, can be personal data under GDPR, the CCPA and similar laws: make sure you have a lawful basis for processing them, and do not use them to contact or profile individuals. You are responsible for how you use the data and for complying with Home Depot's terms and applicable law.

### Support

Found a bug or need a field added? Open an issue in the **Issues** tab; it is usually answered within a day.

### Related scrapers

- [Lowe's Scraper](https://apify.com/tortuga/lowes-scraper): Products, Prices & Reviews
- [eBay Scraper](https://apify.com/tortuga/ebay-scraper): Listings, Prices & Sellers
- [Etsy Scraper](https://apify.com/tortuga/etsy-scraper): Listings, Prices, Shops & Badges
- [Walmart Scraper](https://apify.com/tortuga/walmart-scraper): Products, Prices & Reviews
- [Target Scraper](https://apify.com/tortuga/target-scraper): Products, Prices, Stock & Reviews

### Found it useful?

A ★ review on this Actor's Apify Store page helps other users find it and tells us what to improve. Issues and feature requests are welcome in the Actor's **Issues** tab.

# Actor input Schema

## `searchTerms` (type: `array`):

Keywords to search on homedepot.com, one per line (e.g. "air fryer", "cordless drill"). Each term is searched separately and paginated automatically: one request returns a results page of 24 products (12 when Home Depot answers the term with one of its category pages), sponsored tiles included.

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

homedepot.com URLs to scrape instead of (or in addition to) search terms: search pages (https://www.homedepot.com/s/air%20fryer), category pages (https://www.homedepot.com/b/Tools-Power-Tools-Drills/N-5yc1vZc27f, filters and sort parameters are kept), product pages (https://www.homedepot.com/p/DEWALT-Atomic-20V-.../322138372, returned with full details) or review pages (https://www.homedepot.com/p/reviews/DEWALT-Atomic-20V-.../322138372/1, returns reviews only). Department landing pages (/c/...) have no product list and are skipped with an error.

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

Stop after this many dataset items in total. Products and reviews both count, so with reviews on raise it accordingly (50 products with 10 reviews each = 550 items). With "Only new or changed items" on, this is the number of products checked per run instead. Keeps cost predictable.

## `maxPagesPerSearch` (type: `integer`):

How many result pages to open per search term or listing URL (one proxy request per page; 24 products per search page, 12 per category page). Pages are only requested while Max items still needs them.

## `includeSponsored` (type: `boolean`):

Home Depot mixes 2-3 sponsored tiles into every results page. They are saved with isSponsored = true. Turn this off to keep organic results only (recommended for scheduled price monitoring: ads rotate on every visit).

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

Also open every product page to get the description, highlights and feature bullets, the full specification table (grouped as on the page), every image, videos, manuals and other PDFs, UPC / GTIN, dimensions and weight, sale start and end dates, the 1-5 star rating breakdown, recommendation counts and the Q\&A count. One extra proxy request (7-60 seconds) and one extra `detail` charge per product (see pricing).

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

Customer reviews to collect per product, as separate items with type = "review" (rating, title, text, date, reviewer nickname and location as shown, recommended flag, helpful votes, photos, secondary ratings, brand response). 0 = no reviews. Up to 10 reviews come free with product details; beyond that Home Depot's reviews page serves 30 per request, in Home Depot's own order (reviews with photos first, newest first within).

## `storeId` (type: `string`):

Price and stock for one Home Depot store, e.g. 121 (Cumberland, Atlanta) or 2702 (Warren, MI). Leave empty to let Home Depot pick a store from the proxy's location, which can differ from request to request. Find a store number in the store's page URL on homedepot.com (the last number in /l/<city>/<state>/<id>). With a store set, listing results (price, strike-through price, pickup stock and quantities, delivery date, which products appear and in what order) are for that store, and every item records requestedStoreId and locationApplied next to the store Home Depot reported. ZIP code lookup is not offered: Home Depot's store finder cannot be reached anonymously.

## `onlyNewOrChanged` (type: `boolean`):

Remember what earlier runs of this search returned and output only new products or products whose price, strike-through price or stock status changed. Use with a Schedule; unchanged items are not charged and no product page is opened for them.

## `monitoringKey` (type: `string`):

Name for this watch, so several schedules on the same search stay separate; defaults to a key derived from the search input.

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

homedepot.com answers datacenter and residential proxies with an Akamai error page, so the default is Apify's Unblocker proxy (group UNBLOCKER, US). The Unblocker is billed to your Apify account per request: 10 Unblocker units, about $0.0015 on the free plan and less on paid plans, for every attempt the Actor makes, including the occasional attempt the proxy cannot complete (HTTP 502, retried automatically). One request returns a results page (12-24 products), one product page, or 30 reviews. The proxy renders the pages in a browser, which takes 7-75 seconds each.

## Actor input object example

```json
{
  "searchTerms": [
    "air fryer"
  ],
  "startUrls": [],
  "maxItems": 10,
  "maxPagesPerSearch": 1,
  "includeSponsored": true,
  "includeDetails": false,
  "maxReviewsPerProduct": 0,
  "onlyNewOrChanged": false,
  "proxyConfiguration": {
    "useApifyProxy": true,
    "apifyProxyGroups": [
      "UNBLOCKER"
    ],
    "apifyProxyCountry": "US"
  }
}
```

# Actor output Schema

## `results` (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 = {
    "searchTerms": [
        "air fryer"
    ],
    "startUrls": [],
    "maxItems": 10,
    "maxPagesPerSearch": 1,
    "proxyConfiguration": {
        "useApifyProxy": true,
        "apifyProxyGroups": [
            "UNBLOCKER"
        ],
        "apifyProxyCountry": "US"
    }
};

// Run the Actor and wait for it to finish
const run = await client.actor("tortuga/home-depot-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 = {
    "searchTerms": ["air fryer"],
    "startUrls": [],
    "maxItems": 10,
    "maxPagesPerSearch": 1,
    "proxyConfiguration": {
        "useApifyProxy": True,
        "apifyProxyGroups": ["UNBLOCKER"],
        "apifyProxyCountry": "US",
    },
}

# Run the Actor and wait for it to finish
run = client.actor("tortuga/home-depot-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 '{
  "searchTerms": [
    "air fryer"
  ],
  "startUrls": [],
  "maxItems": 10,
  "maxPagesPerSearch": 1,
  "proxyConfiguration": {
    "useApifyProxy": true,
    "apifyProxyGroups": [
      "UNBLOCKER"
    ],
    "apifyProxyCountry": "US"
  }
}' |
apify call tortuga/home-depot-scraper --silent --output-dataset

```

## MCP server setup

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