{
  "openapi": "3.0.1",
  "info": {
    "title": "Lowe's Scraper - Products, Prices, Stock & Reviews",
    "description": "Scrape Lowe's (lowes.com) home improvement, tools, appliances and building supplies by keyword search. Extract product names, brands, prices, descriptions, specifications, stock availability, ratings and customer reviews. Ideal for price monitoring, competitor analysis and retail market research.",
    "version": "0.1",
    "x-build-id": "SzSSpb5CqW6BcDlll"
  },
  "servers": [
    {
      "url": "https://api.apify.com/v2"
    }
  ],
  "paths": {
    "/acts/abotapi~lowes-com-scraper/run-sync-get-dataset-items": {
      "post": {
        "operationId": "run-sync-get-dataset-items-abotapi-lowes-com-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/abotapi~lowes-com-scraper/runs": {
      "post": {
        "operationId": "runs-sync-abotapi-lowes-com-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/abotapi~lowes-com-scraper/run-sync": {
      "post": {
        "operationId": "run-sync-abotapi-lowes-com-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": {
          "mode": {
            "title": "Mode",
            "enum": [
              "search",
              "urls"
            ],
            "type": "string",
            "description": "Search mode walks keyword search result pages. Links mode walks the storefront links you paste: search pages, category pages and product pages.",
            "default": "urls"
          },
          "searchTerms": {
            "title": "Search terms",
            "type": "array",
            "description": "Keyword searches to walk (search mode). Each term walks its result pages in order.",
            "items": {
              "type": "string"
            }
          },
          "urls": {
            "title": "Storefront links",
            "type": "array",
            "description": "Links to walk (links mode): keyword search pages, category pages (/pl/<name>/<id> links from the storefront's menus) and product pages.",
            "default": [
              {
                "url": "https://www.lowes.com/search?searchTerm=drill"
              },
              {
                "url": "https://www.lowes.com/pd/CRAFTSMAN-20-volt-Max-1-2-in-Keyless-Brushless-Cordless-Drill-1-Batteries-Included-Soft-Bag-Included/5016412045"
              }
            ],
            "items": {
              "type": "object",
              "required": [
                "url"
              ],
              "properties": {
                "url": {
                  "type": "string",
                  "title": "URL of a web page",
                  "format": "uri"
                }
              }
            }
          },
          "fetchDetails": {
            "title": "Fetch product details",
            "type": "boolean",
            "description": "Read each product's detail JSON: description, model, availability, full spec table, image gallery and breadcrumbs. Billed per enriched record.",
            "default": true
          },
          "fetchReviews": {
            "title": "Fetch reviews",
            "type": "boolean",
            "description": "Collect customer reviews per product (rating summary, distribution and up to Max reviews review texts). Billed per record that delivered reviews.",
            "default": true
          },
          "maxReviews": {
            "title": "Max reviews per product",
            "minimum": 0,
            "maximum": 1000,
            "type": "integer",
            "description": "Cap on review texts collected per product. Values above 100 are treated as 100. 0 skips review texts.",
            "default": 20
          },
          "zipCode": {
            "title": "ZIP code for pricing",
            "type": "string",
            "description": "Not applied in this version: prices and stock come from the storefront's default store regardless of the connection country, and the row's storeNumber names it. Leave empty."
          },
          "maxItems": {
            "title": "Max items",
            "minimum": 0,
            "maximum": 100000,
            "type": "integer",
            "description": "Maximum records this run may push (up to 100000). 0 means no limit.",
            "default": 20
          },
          "proxyConfiguration": {
            "title": "Proxy configuration",
            "type": "object",
            "description": "Residential proxies are required (US by default): the storefront's edge refuses scripted readers on datacenter exits. When the selected country's exits keep being refused, the run continues on the same proxy group in other countries, which the storefront serves the same US catalog and prices.",
            "default": {
              "useApifyProxy": true,
              "apifyProxyGroups": [
                "RESIDENTIAL"
              ],
              "apifyProxyCountry": "US"
            }
          },
          "resumeFromRunId": {
            "title": "Resume from a previous run",
            "type": "string",
            "description": "Paste the run ID or dataset ID of an interrupted run to continue it without returning, or charging for, the products it already collected. A run that is restarted by the platform (for example after a server move) continues by itself and needs no ID. Combine it with Incremental mode to finish an interrupted monitoring run: the products it already returned are not returned again and are tracked as seen. EXPIRED detection never runs on a resumed run. For recurring monitoring of the same scope use Incremental mode below instead."
          },
          "incrementalMode": {
            "title": "Incremental changes for scheduled runs",
            "type": "boolean",
            "description": "Turn this on for daily or recurring monitoring. The first run returns every matching product as NEW. Later runs return only what changed (NEW, UPDATED, REAPPEARED), and a product whose listing data did not change is neither read again nor charged. What is compared: price, was-price, savings and sale end, unit price, title, brand, model, ids, in-stock, pickup and parcel availability, free shipping, packaging, badges, highlights, specifications, categories, collections and promotions. What is excluded by default (still returned in the row, never a change): scrape time, the product's rank on the page, the store nearest the connection, per-delivery-method availability detail, and the counters stock units, review count and average rating (they tick between two reads of an unchanged product; turn on 'Count stock unit changes' to compare the stock counter). Lists whose order carries no meaning (badges, collections, categories, promotions) are compared regardless of order. 'Changes to watch' narrows the comparison to price, sale and availability only. The state is kept per scope: search terms, links and the detail and review settings, so two different scopes never mix; caps, proxy and the incremental controls themselves never start a new baseline. Use State key to name or deliberately share a campaign. A run that ends early (time limit, abort, server move) remembers the rows it already returned, so the next run does not return them again; after a run is killed without notice the last few rows can return once, and Resume closes that gap. To continue one specific interrupted run instead, use Resume from a previous run above.",
            "default": false
          },
          "stateKey": {
            "title": "State key (incremental mode only)",
            "type": "string",
            "description": "Optional. Name this monitoring campaign to keep its state stable, or to deliberately share state across differently configured runs. Leave empty to derive a key automatically from the scope, so two different scopes never mix state. A shared key with a different scope never produces EXPIRED rows."
          },
          "emitUnchanged": {
            "title": "Emit unchanged products (incremental mode only)",
            "type": "boolean",
            "description": "Off by default. Turn on to also return products that have not changed since the last run, marked UNCHANGED, with the product-page details the last run collected for them. This returns, and bills, rows you already have, so leave it off unless you want a full snapshot every run.",
            "default": false
          },
          "emitExpired": {
            "title": "Emit expired products (incremental mode only)",
            "type": "boolean",
            "description": "Off by default. Turn on to also return products that were present in a previous run but are no longer in the results, marked EXPIRED. Only produced after a run that read the whole scope to its end: never when Max items capped it, a page could not be read, the time or spending limit stopped it, or Resume was used. A product that left the results is not necessarily unavailable, so consider 'Expire after missed scans' above 1. EXPIRED rows count against Max items (a run returns at most the room left under it; the rest follow on a later complete run) and are returned and billed like any row, so leave it off unless you need expiry tracking.",
            "default": false
          },
          "changeScope": {
            "title": "Changes to watch (incremental mode only)",
            "enum": [
              "all",
              "priceAndStock"
            ],
            "type": "string",
            "description": "All fields (default): any change to the compared product data marks a product UPDATED. Price and availability only: just price, was-price, savings, sale end, unit price, in-stock, pickup and parcel availability, free shipping and per-option price and stock, so title, description or specification edits never produce a billable UPDATED row. Changing this never starts a new baseline: the saved state is kept and each stored product is compared under the new setting.",
            "default": "all"
          },
          "compactUpdates": {
            "title": "Compact UPDATED rows (incremental mode only)",
            "type": "boolean",
            "description": "Off by default. When on, UPDATED and EXPIRED rows are slim: ids, link, title, current price and availability, plus priceChanges (old and new value of each field that moved) and variantChanges (per-option ADDED, REMOVED or CHANGED). NEW rows stay full. A compact row carries no product-page detail or reviews, so no detail or review charge applies to it and the product page is not read.",
            "default": false
          },
          "watchStockQuantity": {
            "title": "Count stock unit changes (incremental mode only)",
            "type": "boolean",
            "description": "Off by default. The units-in-stock counter ticks as the product sells, so counting it marks fast sellers UPDATED, and bills them, on most scans. Turn on to compare it anyway. In-stock, pickup and parcel availability are always compared.",
            "default": false
          },
          "expireAfterMissedScans": {
            "title": "Expire after missed scans (incremental mode only)",
            "minimum": 1,
            "maximum": 30,
            "type": "integer",
            "description": "Used with 'Emit expired products'. A product is marked EXPIRED only after it was missing from this many COMPLETE scans in a row (default 1). Dropping out of a result list is not the same as being unavailable, so 2 or more avoids false expiries; a product that returns resets the count.",
            "default": 1
          },
          "ignoreFieldsForChanges": {
            "title": "Ignore fields when detecting changes (incremental mode only)",
            "type": "array",
            "description": "A list of field names that must not count as a change, for example [\"title\", \"badges\"]. Use a dotted path to ignore a key inside every element of a list, for example variants.label. Ignored fields are still returned in the row. Scrape time, rank, nearest store, delivery detail, stock units, review count and average rating are already ignored by default. Changing this list never starts a new baseline: the saved state is kept and every stored product is re-compared under the new list."
          },
          "mcpConnectors": {
            "title": "MCP connectors",
            "type": "array",
            "description": "Internal: connector ids that receive the run's records as they push.",
            "items": {
              "type": "string"
            }
          },
          "notionParentPageUrl": {
            "title": "Notion parent page URL",
            "type": "string",
            "description": "Internal: parent page for the Notion connector."
          },
          "maxNotifyListings": {
            "title": "Max listings to notify",
            "type": "integer",
            "description": "Internal: cap on records sent to connectors per run.",
            "default": 50
          }
        }
      },
      "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
                  },
                  "PROXY_UNBLOCKER_UNITS": {
                    "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
                  },
                  "PROXY_UNBLOCKER_UNITS": {
                    "type": "integer",
                    "example": 0
                  }
                }
              }
            }
          }
        }
      }
    }
  }
}