# Lowe's Price, Stock & Specification Scraper (`dataspryva/lowes-price-stock-and-specification-scraper`) Actor

Search Lowe's products by keyword, browse a category, or fetch details by item ID or URL. Get price, original price, discount percent, stock status, ratings, model number, and full specifications for each product.

- **URL**: https://apify.com/dataspryva/lowes-price-stock-and-specification-scraper.md
- **Developed by:** [Dataspryva](https://apify.com/dataspryva) (community)
- **Categories:** E-commerce, Automation, Lead generation
- **Stats:** 3 total users, 2 monthly users, 100.0% runs succeeded, 0 bookmarks
- **User rating**: No ratings yet

## Pricing

from $0.49 / 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/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

## Lowe's Price, Stock & Specification Scraper

Lowe's product pages carry live pricing, store stock, fulfilment promises, ratings, and a deep spec sheet. This actor finds Lowe's product pages by keyword, department, item ID, or URL, then reads the live product data for every product it finds.

Search and category discovery use a public web index to locate Lowe's product pages. That is a candidate set, not a full replica of Lowe's on-site search. Product price, stock, specs, and store context are then read live from Lowe's own product data.

### What this actor does

- Searches Lowe's products by keyword, with multiple query variants and result pages.
- Browses a department or any Lowe's `/pl/` category URL. It first tries the category page for embedded product links and falls back to keyword discovery if Lowe's blocks or omits them.
- Looks up products by item number or by `/pd/` product URL.
- Accepts mixed URLs: product, search, and category URLs can be supplied in one run.
- Reads store-aware price, was/sale price, stock by fulfilment method, ratings, specifications, UPC, dimensions, manuals, badges, variants, and more.
- Deduplicates products across queries and pages.
- Omits empty fields instead of emitting placeholders.

### Output per product

Identity and context:

- `itemId`, `itemNumber`, `model`, `brand`, `title`, `url`
- `imageUrl`, `images`, `videos`
- `category`, `categoryPath`, `merchandising`
- `storeId`, `storeNumber`, `storeName`, `storeCity`, `storeState`, `storeZip`
- `aisle`, `bay`
- `source`, `sourceQuery`, `position`, `scrapedAt`

Price and promotion:

- `price`, `priceText`, `priceScope`, `currency`, `priceNote`
- `originalPrice`, `discountPercent`, `savings`, `savingsPercent`, `onSale`, `saleEndDate`

Stock and fulfilment:

- `inStock`, `availability` (method, availability, quantity, lead time, ship date, delivery date)
- `onlineQuantity`, `pickupAvailable`, `pickupQuantity`, `storeQuantity`, `storeAvailability`, `deliveryDate`

Ratings and merchandising:

- `rating`, `reviewCount`, `brandRating`, `brandReviewCount`
- `badges`, `isSponsored`, `isMarketplace`, `isSpecialOrder`, `programType`
- `isBuyable`, `lowesExclusive`, `energyStar`, `prop65`, `socialProofing`

Details (when `includeDetails` is on):

- `description`, `romanceCopy`, `marketingBullets`
- `specifications`, `keySpecs`
- `upc`, `barcodes`, `dimensions`, `weight`, `weightUnit`, `packageQuantity`
- `warranty`, `guides`, `listedAt`, `lastModifiedAt`, `maxPurchaseQuantity`

Variants (when Lowe's exposes them):

- `variantCount`, `variantAttribute`, `variants`, `selectedOptions`

### Input

| Field | Type | Default | Description |
|---|---|---|---|
| `mode` | string | `productDetails` | `search`, `byCategory`, `productDetails`, or `byUrl` |
| `searchQueries` | array | `["power drill"]` | Keywords for `search`; each query adds discovery results |
| `category` | string | `tools` | Department for `byCategory` |
| `itemIds` | array | `[]` | Item numbers or `/pd/` URLs for `productDetails` |
| `startUrls` | array | `[]` | Product, search, or `/pl/` category URLs for `byUrl` |
| `storeId` | string | `0208` | Four-digit store number for price and stock context |
| `zipCode` | string | `92253` | Five-digit ZIP used with the store number |
| `sortBy` | string | `featured` | `featured`, `bestSellers`, `highestRated`, `newest`, `priceLowToHigh`, `priceHighToLow`, or `brand` |
| `inStockOnly` | boolean | `false` | Keep products with at least one available fulfilment method |
| `onSaleOnly` | boolean | `false` | Keep products with a current was/sale price |
| `onShelfOnly` | boolean | `false` | Keep products with pickup quantity above zero at the selected store |
| `minPrice` | integer | – | Drop products below this price |
| `maxPrice` | integer | – | Drop products above this price |
| `minRating` | number | – | Drop products below this rating |
| `includeDetails` | boolean | `true` | Add specs, bullets, UPC, dimensions, warranty, and manuals |
| `maxItems` | integer | `50` | Maximum products to emit (1–5000) |

#### Example: keyword search

```json
{
  "mode": "search",
  "searchQueries": ["power drill", "cordless drill kit"],
  "maxItems": 20,
  "storeId": "0208",
  "zipCode": "92253"
}
```

#### Example: browse a department

```json
{
  "mode": "byCategory",
  "category": "paint",
  "inStockOnly": true,
  "sortBy": "priceLowToHigh",
  "maxItems": 50
}
```

#### Example: look up item IDs

```json
{
  "mode": "productDetails",
  "itemIds": ["5013207487", "50040962"],
  "includeDetails": true
}
```

#### Example: mixed URLs

```json
{
  "mode": "byUrl",
  "startUrls": [
    "https://www.lowes.com/pd/Kobalt-24-volt-Max-1-2-in-Metal-Ratcheting-Brushless-Cordless-Drill-1-Battery-Included-and-Charger-Included/5013207487",
    "https://www.lowes.com/search?searchTerm=interior+paint",
    "https://www.lowes.com/pl/tools/4294936478"
  ],
  "maxItems": 30
}
```

### Use cases

- Track price and was/sale changes for a product list or a whole department.
- Build a store-level stock and fulfilment tracker for items you restock.
- Compare specifications, dimensions, manuals, and ratings across competing products.
- Feed Lowe's product data into a price-comparison, estimating, or catalogue tool.
- Find current product pages for a keyword without maintaining your own Lowe's link list.

### Reliability and limits

- Search and category discovery is index-based. It returns a candidate set of Lowe's product pages and can return fewer products than `maxItems` or fewer than Lowe's own search page shows. Split broad topics into several `searchQueries` or use narrower category URLs to widen coverage.
- Category browsing tries the Lowe's category page first. If that page is blocked or has no product links, the actor derives keywords from the category path and uses index discovery instead.
- Product data is read live for each product, so price, stock, and fulfilment reflect the run time.
- Price and stock are store-scoped. `storeId` is the store you asked for; `storeNumber` is the price store Lowe's returned, which can be a nearby store. A product with no national or store price is emitted without a price rather than with zero.
- Reviews are aggregate rating and review count only. Individual review text is not included.
- The sponsored flag is included when Lowe's category page exposes it. Product data does not carry that flag, so it is omitted for ID, URL, and keyword-only records.
- Variants are included when Lowe's exposes a variant group. Products without variants omit the field.
- The actor selects its proxy automatically. No proxy configuration is needed.

### FAQ

**Is this actor affiliated with Lowe's?**
No. It reads publicly visible Lowe's product pages and has no relationship with Lowe's.

**Do I need a Lowe's account or cookies?**
No. Every field comes from public product data that does not require a login.

**Do I need to configure a proxy?**
No. The actor chooses its own proxy path and retries when a request is blocked.

**Why do I get fewer products than Lowe's search shows?**
Keyword and category discovery uses a public web index, not Lowe's on-site search. It returns a candidate set, so broad queries can be shallow. Use several specific `searchQueries` or a narrower category URL to find more.

**Why is a price missing on some products?**
Some items are marketplace, special-order, or out of stock and have no national price. The actor omits the price instead of writing zero or a guess.

**Why does the store differ from the ZIP I entered?**
Lowe's returns the store it used for the price. `storeId` is the store you requested; `storeNumber` is the price store Lowe's returned, which may be a nearby store.

**Do you return review text?**
No. The actor returns the aggregate rating and review count. Individual review text is not part of the product data it reads.

**Why are specifications missing on some products?**
Specifications are included when `includeDetails` is on and Lowe's publishes them for that product. Missing specs are omitted rather than filled with placeholders.

**How current is the data?**
Each run reads Lowe's live product data, so price, stock, and fulfilment reflect what Lowe's returns at run time.

# Actor input Schema

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

What to look up.

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

Keywords to search for (mode=search). Each query adds its own discovery results.

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

Lowe's department to browse (mode=byCategory).

## `itemIds` (type: `array`):

Lowe's item numbers (for example 5013207487) or /pd/ product URLs. Used by mode=productDetails.

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

Lowe's product, search, or /pl/ category URLs. Used by mode=byUrl, and category URLs are also accepted by mode=byCategory.

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

Four-digit Lowe's store number used for price and stock context. Default 0208 (La Quinta, CA).

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

Five-digit ZIP code used with the store number for price and stock context. Default 92253.

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

How to order the products found in this run.

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

Only emit products with at least one fulfilment method available.

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

Only emit products with a current was/sale price.

## `onShelfOnly` (type: `boolean`):

Only emit products with pickup quantity above zero at the selected store.

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

Drop products priced below this value. Products without a price are skipped when a price filter is set.

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

Drop products priced above this value. Products without a price are skipped when a price filter is set.

## `minRating` (type: `number`):

Drop products rated below this value. Products without a rating are skipped when this filter is set.

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

Add description, bullets, specifications, UPC, dimensions, warranty, and manuals to each product.

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

Maximum number of products to emit. Discovery may return fewer candidates than this.

## Actor input object example

```json
{
  "mode": "productDetails",
  "searchQueries": [],
  "category": "tools",
  "itemIds": [
    "5013207487"
  ],
  "startUrls": [],
  "storeId": "0208",
  "zipCode": "92253",
  "sortBy": "featured",
  "inStockOnly": false,
  "onSaleOnly": false,
  "onShelfOnly": false,
  "includeDetails": true,
  "maxItems": 1
}
```

# Actor output Schema

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

Dataset containing the scraped Lowe's products.

# API

You can run this Actor programmatically using our API. Below are code examples in JavaScript, Python, and CLI, as well as the OpenAPI specification and MCP server setup.

## JavaScript example

```javascript
import { ApifyClient } from 'apify-client';

// Initialize the ApifyClient with your Apify API token
// Replace the '<YOUR_API_TOKEN>' with your token
const client = new ApifyClient({
    token: '<YOUR_API_TOKEN>',
});

// Prepare Actor input
const input = {
    "mode": "productDetails",
    "searchQueries": [],
    "category": "tools",
    "itemIds": [
        "5013207487"
    ],
    "startUrls": [],
    "storeId": "0208",
    "zipCode": "92253",
    "sortBy": "featured",
    "inStockOnly": false,
    "onSaleOnly": false,
    "onShelfOnly": false,
    "includeDetails": false,
    "maxItems": 1
};

// Run the Actor and wait for it to finish
const run = await client.actor("dataspryva/lowes-price-stock-and-specification-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": "productDetails",
    "searchQueries": [],
    "category": "tools",
    "itemIds": ["5013207487"],
    "startUrls": [],
    "storeId": "0208",
    "zipCode": "92253",
    "sortBy": "featured",
    "inStockOnly": False,
    "onSaleOnly": False,
    "onShelfOnly": False,
    "includeDetails": False,
    "maxItems": 1,
}

# Run the Actor and wait for it to finish
run = client.actor("dataspryva/lowes-price-stock-and-specification-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": "productDetails",
  "searchQueries": [],
  "category": "tools",
  "itemIds": [
    "5013207487"
  ],
  "startUrls": [],
  "storeId": "0208",
  "zipCode": "92253",
  "sortBy": "featured",
  "inStockOnly": false,
  "onSaleOnly": false,
  "onShelfOnly": false,
  "includeDetails": false,
  "maxItems": 1
}' |
apify call dataspryva/lowes-price-stock-and-specification-scraper --silent --output-dataset

```

## MCP server setup

```json
{
    "mcpServers": {
        "apify": {
            "type": "http",
            "url": "https://mcp.apify.com/?tools=fetch-actor-details,dataspryva/lowes-price-stock-and-specification-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/KnnU4GxLeum2JdDP7/builds/psFnduI7nHVgiC7bh/openapi.json
