{
  "data": {
    "id": "Ed9cXcqgUuFh1rmod",
    "actId": "vTgN2nhL0hqk9nqMe",
    "userId": "zq8lKbpLzTjGDayPC",
    "startedAt": "2026-11-09T06:40:43.875Z",
    "finishedAt": "2026-11-09T06:41:12.924Z",
    "status": "SUCCEEDED",
    "meta": {
      "origin": "CLI"
    },
    "stats": {
      "durationMillis": 28901,
      "runTimeSecs": 28.901,
      "computeUnits": 0.03211222222222222,
      "imageSizeBytes": 3164270592
    },
    "options": {
      "useCache": true,
      "betaPackages": false,
      "memoryMbytes": 4096,
      "diskMbytes": 8192
    },
    "createdByOrganizationMemberUserId": "GK9YjZRyQZVzOdoH5",
    "exitCode": 0,
    "inputSchema": "{\n  \"title\": \"Best Buy Price Drop & Stock Tracker Input\",\n  \"description\": \"Find Best Buy products by keyword, category/search URL, product URL or SKU. Each record carries current and regular price, savings, stock status, rating, brand and product details.\",\n  \"type\": \"object\",\n  \"schemaVersion\": 1,\n  \"properties\": {\n    \"searchQueries\": {\n      \"title\": \"Search keywords\",\n      \"type\": \"array\",\n      \"description\": \"One or more Best Buy searches, for example `sony headphones` or `oled tv`. Each query is paginated until `maxResults` is reached.\",\n      \"editor\": \"stringList\",\n      \"prefill\": [\n        \"sony headphones\"\n      ],\n      \"sectionCaption\": \"What to scrape\",\n      \"sectionDescription\": \"Use any combination of keyword searches, category links, product links and SKUs. Results are combined and de-duplicated by SKU.\"\n    },\n    \"categoryUrls\": {\n      \"title\": \"Category or search URLs\",\n      \"type\": \"array\",\n      \"description\": \"Best Buy category, browse or search-result links, e.g. `https://www.bestbuy.com/site/headphones/.../pcmcat....c?id=...`. Pagination, sorting and condition filters are applied automatically.\",\n      \"editor\": \"stringList\",\n      \"default\": []\n    },\n    \"productUrls\": {\n      \"title\": \"Product URLs\",\n      \"type\": \"array\",\n      \"description\": \"Exact Best Buy product links in either the new `/product/.../sku/...` or legacy `/site/.../<sku>.p?skuId=...` format.\",\n      \"editor\": \"stringList\",\n      \"default\": []\n    },\n    \"skuIds\": {\n      \"title\": \"SKUs\",\n      \"type\": \"array\",\n      \"description\": \"Best Buy SKU numbers (6–9 digits). Product links are also accepted here.\",\n      \"editor\": \"stringList\",\n      \"default\": []\n    },\n    \"maxResults\": {\n      \"title\": \"Max results\",\n      \"type\": \"integer\",\n      \"description\": \"Hard cap on the total number of product records emitted across every mode.\",\n      \"default\": 24,\n      \"prefill\": 3,\n      \"minimum\": 1,\n      \"maximum\": 1000,\n      \"sectionCaption\": \"Limits and pagination\",\n      \"sectionDescription\": \"Control how many pages are read and how many records are returned.\"\n    },\n    \"maxPages\": {\n      \"title\": \"Max pages per query or category\",\n      \"type\": \"integer\",\n      \"description\": \"Pagination guard for each keyword or category link. Each page carries up to about 24 products.\",\n      \"default\": 50,\n      \"minimum\": 1,\n      \"maximum\": 100\n    },\n    \"sortBy\": {\n      \"title\": \"Sort results\",\n      \"type\": \"string\",\n      \"description\": \"Best Buy's own sort order. Price, rating and discount orders are also enforced on the collected records.\",\n      \"editor\": \"select\",\n      \"default\": \"Best-Match\",\n      \"enum\": [\n        \"Best-Match\",\n        \"Best-Selling\",\n        \"Best-Discount\",\n        \"Price-Low-To-High\",\n        \"Price-High-To-Low\",\n        \"Customer-Rating\",\n        \"New-Arrivals\"\n      ],\n      \"enumTitles\": [\n        \"Best match\",\n        \"Best selling\",\n        \"Biggest discount\",\n        \"Price: low to high\",\n        \"Price: high to low\",\n        \"Customer rating\",\n        \"New arrivals\"\n      ],\n      \"sectionCaption\": \"Search filters\",\n      \"sectionDescription\": \"Filters apply to keyword searches and category links; price, condition and stock filters also apply to product URLs and SKUs.\"\n    },\n    \"condition\": {\n      \"title\": \"Condition\",\n      \"type\": \"string\",\n      \"description\": \"Keep only new, open-box or refurbished products. `All conditions` disables this filter.\",\n      \"editor\": \"select\",\n      \"default\": \"all\",\n      \"enum\": [\n        \"all\",\n        \"new\",\n        \"open-box\",\n        \"refurbished\"\n      ],\n      \"enumTitles\": [\n        \"All conditions\",\n        \"New\",\n        \"Open-box\",\n        \"Refurbished\"\n      ]\n    },\n    \"minPrice\": {\n      \"title\": \"Minimum price ($)\",\n      \"type\": \"integer\",\n      \"description\": \"Drop products below this current price. `0` means no minimum.\",\n      \"default\": 0,\n      \"minimum\": 0,\n      \"maximum\": 1000000\n    },\n    \"maxPrice\": {\n      \"title\": \"Maximum price ($)\",\n      \"type\": \"integer\",\n      \"description\": \"Drop products above this current price. `0` means no maximum.\",\n      \"default\": 0,\n      \"minimum\": 0,\n      \"maximum\": 1000000\n    },\n    \"inStockOnly\": {\n      \"title\": \"In stock only\",\n      \"type\": \"boolean\",\n      \"description\": \"Drop products that Best Buy marks sold out, out of stock or unavailable.\",\n      \"default\": false\n    },\n    \"includeDetails\": {\n      \"title\": \"Include product-page details\",\n      \"type\": \"boolean\",\n      \"description\": \"Open each product page for description, model number, GTIN/UPC and seller. Slower; unavailable fields are omitted honestly.\",\n      \"default\": false,\n      \"sectionCaption\": \"Product details\",\n      \"sectionDescription\": \"The optional detail pass uses a real browser and is best for small watchlists.\"\n    }\n  },\n  \"required\": []\n}",
    "readme": "# Best Buy Price Drop & Stock Tracker\n\nWatch Best Buy prices and availability without opening a browser tab for every product. Give this actor a few keywords, a category link, product links or SKU numbers, and it returns one structured row per product: what the item is, what it costs now, what it used to cost, whether it is in stock, how shoppers rated it, and where it sits in the result grid.\n\nThe actor runs without a Best Buy account, API key, cookie or proxy setup. It reads the public Best Buy storefront and its public price endpoint, then writes clean product records to the Apify dataset.\n\n## Four ways to build a product list\n\n| Mode | Field | Best for |\n|---|---|---|\n| Keyword search | `searchQueries` | Exploring a category, brand or product idea |\n| Category or search URL | `categoryUrls` | Reusing a Best Buy browse/search link you already trust |\n| Product URL | `productUrls` | Watching exact items you found on the site |\n| SKU | `skuIds` | Feeding a restock or price watchlist from another system |\n\nAll four modes can be combined in a single run. Results are de-duplicated by SKU, filtered, sorted and capped by `maxResults`.\n\n## What you can do with it\n\n- **Price-drop watchlist** — run the same `skuIds` or `productUrls` on a schedule and compare `currentPrice` between datasets. A lower value is a drop; `regularPrice` tells you the reference price.\n- **Restock monitor** — keep `inStockOnly` off and watch `availability` flip from `OutOfStock` to `InStock`.\n- **Category deal scan** — pass a category URL with `sortBy: \"Best-Discount\"` or `condition: \"open-box\"` to surface markdowns and open-box units.\n- **Competitive snapshot** — collect brand, model, rating and review count for every product in a search grid.\n- **Rank tracking** — `position`, `searchPage` and `isSponsored` preserve the grid order Best Buy returned, so you can compare placement across runs.\n\n## Input\n\n| Field | Type | Default | What it does |\n|---|---|---|---|\n| `searchQueries` | array | – | One or more keyword searches (the input form prefills `[\"sony headphones\"]`). Each is paginated until the global result cap is reached. |\n| `categoryUrls` | array | `[]` | Best Buy category, browse or search-result links. `cp` pagination, sort and condition filters are added automatically. |\n| `productUrls` | array | `[]` | Exact product links in new `/product/.../sku/...` or legacy `/site/.../<sku>.p?skuId=...` form. |\n| `skuIds` | array | `[]` | Best Buy SKUs (6–9 digits). Product links are accepted here too. |\n| `maxResults` | integer | `24` | Total records across all modes, 1–1000. |\n| `maxPages` | integer | `50` | Page guard per keyword or category link, 1–100. |\n| `sortBy` | select | `Best-Match` | One of Best-Match, Best-Selling, Best-Discount, Price-Low-To-High, Price-High-To-Low, Customer-Rating, New-Arrivals. |\n| `condition` | select | `all` | `all`, `new`, `open-box` or `refurbished`. |\n| `minPrice` | integer | `0` | Minimum current price in dollars; `0` disables the bound. |\n| `maxPrice` | integer | `0` | Maximum current price in dollars; `0` disables the bound. |\n| `inStockOnly` | boolean | `false` | Drop products Best Buy marks sold out, out of stock or unavailable. |\n| `includeDetails` | boolean | `false` | Open each product page to add description, model, GTIN/UPC and seller where Best Buy publishes them. Slower. |\n\nEvery field in the input form is used by the actor. Older saved tasks that still send `keyword`, `searchQuery`, `categoryUrl`, `skus`, `maxItems`, `sort`, `skipOutOfStock` or `openBoxOnly` keep working: those legacy keys are mapped onto the current fields in code.\n\n### Example: exact-product watchlist\n\n```json\n{\n  \"skuIds\": [\"6505727\", \"6620467\", \"6689192\"],\n  \"inStockOnly\": false,\n  \"maxResults\": 10\n}\n```\n\n### Example: open-box deals in a category\n\n```json\n{\n  \"categoryUrls\": [\n    \"https://www.bestbuy.com/site/headphones/wireless-headphones/pcmcat331200050015.c?id=pcmcat331200050015\"\n  ],\n  \"condition\": \"open-box\",\n  \"sortBy\": \"Price-Low-To-High\",\n  \"maxResults\": 60\n}\n```\n\n### Example: keyword search with a price window\n\n```json\n{\n  \"searchQueries\": [\"sony headphones\", \"noise cancelling earbuds\"],\n  \"minPrice\": 100,\n  \"maxPrice\": 400,\n  \"inStockOnly\": true,\n  \"sortBy\": \"Customer-Rating\",\n  \"maxResults\": 50\n}\n```\n\n### Example: one exact link\n\n```json\n{\n  \"productUrls\": [\n    \"https://www.bestbuy.com/product/sony-wh1000xm5-wireless-noise-canceling-over-the-ear-headphones-black/J7XSRH5CXG/sku/6505727\"\n  ],\n  \"includeDetails\": true\n}\n```\n\n## Output fields\n\n| Field | Type | Meaning |\n|---|---|---|\n| `sku` | string | Best Buy SKU. |\n| `url` | string | Canonical product page URL. |\n| `bsin` | string | Best Buy canonical product-family identifier, when the URL exposes it. |\n| `name` | string | Product title. |\n| `description` | string | Product description, from the optional detail pass. |\n| `brand` | string | Manufacturer brand. |\n| `model` | string | Model number or MPN, from the optional detail pass. |\n| `gtin13` | string | GTIN/UPC, from the optional detail pass. |\n| `image`, `imageUrl` | string | Primary product image (same value under both keys). |\n| `currentPrice` | number | Price shown to a shopper now. |\n| `regularPrice` | number | Non-sale reference price. |\n| `salePrice` | number | Current price when it is below the regular price. |\n| `savings` | number | Regular price minus current price. |\n| `savingsPercent` | number | Savings as a percentage of the regular price. |\n| `onSale` | boolean | True when the current price is below the regular price. |\n| `currency`, `currencySymbol` | string | ISO currency code and display symbol. |\n| `availability` | string | Normalized stock state, e.g. `InStock`, `OutOfStock`, `PreOrder`, `BackOrder`, `LimitedAvailability`. |\n| `availabilityText` | string | Best Buy's own button text, e.g. `Add to Cart` or `Sold Out`. |\n| `buttonState` | string | Raw Best Buy button state. |\n| `priceType` | string | Best Buy price event type, e.g. `onSale` or `clearance`. |\n| `condition` | string | `new`, `open-box` or `refurbished` when known. |\n| `productType` | string | Best Buy product type, e.g. `hardgood`. |\n| `department`, `productClass`, `subclass` | string | Best Buy taxonomy labels. |\n| `categoryPath` | array | Department → class → subclass path. |\n| `rating` | number | Average customer rating. |\n| `reviewCount` | integer | Number of customer reviews. |\n| `seller` | string | Seller name, from the optional detail pass. |\n| `isSponsored` | boolean | True when the result card is labelled Sponsored. |\n| `dealBadge` | string | Best Buy promotional badge, e.g. `Trending Deal` or `Holiday Deal`. |\n| `position` | integer | 1-based position in this run's output after sorting. |\n| `searchPage` | integer | Result page where a search/category product was found. |\n| `searchTotalResults` | integer | Best Buy's reported result count for that query or category. |\n| `searchQuery` | string | Keyword or category URL that produced the record. |\n| `source` | string | `search`, `category`, `productUrl` or `sku`. |\n| `scrapedAt` | string | ISO-8601 UTC collection timestamp. |\n\nFields Best Buy does not publish for a product are omitted rather than sent as `null` or an empty string. Missing price, rating or detail fields therefore mean “not available on this page”, not zero.\n\n## How it works\n\n1. Keyword and category modes load Best Buy's result grid in a real headless browser, scroll it to hydrate lazy cards, and read the rendered product cards. A direct-HTML fallback reads the server-rendered product data if the browser grid is empty.\n2. Product URL and SKU modes skip search and go straight to Best Buy's public price endpoint, batching up to 20 SKUs per request.\n3. Every mode merges the card data with the price/stock response, so price, savings and availability come from Best Buy's current price source rather than a cached grid tile. If that endpoint omits a SKU, the price shown on the hydrated result card fills the row.\n4. Optional detail enrichment opens each product page and reads its structured product data for description, model, GTIN and seller.\n5. Filters and sorting are applied once the merged records exist; duplicates are removed by SKU.\n\nThe actor adds `intl=nosplash` to every request. That tells Best Buy to serve the US storefront instead of its international country selector.\n\n## Limitations and honest notes\n\n- **Online availability only.** Best Buy's per-store, per-ZIP inventory needs a location-bound fulfillment session. This actor reports the national online stock state and does not claim store-level counts.\n- **No stored price history.** The actor is stateless. Schedule it and keep each dataset, or write the rows to a spreadsheet, to build a price timeline.\n- **Detail fields are best-effort and often unavailable.** Best Buy resets product-page requests from many datacenter IPs. In cloud runs `description`, `model`, `gtin13` and `seller` are therefore usually omitted; the price and stock row still ships, and `includeDetails` never blocks it.\n- **SKUs with no usable data are skipped.** If Best Buy returns neither a name nor a price for a product (retired, region-locked, or a price-endpoint miss), that row is not emitted. `maxResults` is a cap, not a guarantee, so a run can return fewer rows. A run that finds no product at all returns one `bestbuy_error` row with `reason: \"no_results\"`.\n- **Full specification sheets are not included.** The detail pass reads structured product data, not the interactive spec table.\n- **Individual reviews are not included.** Use `rating` and `reviewCount` for reception; review text belongs to a dedicated reviews actor.\n- **Marketplace offers are summarized, not enumerated.** The record follows the primary offer Best Buy displays.\n\n## FAQ\n\n**Do I need a Best Buy API key?** No. The actor reads public storefront and price data. It does not use the gated developer API.\n\n**Do I need a proxy?** No. There is no proxy field and no proxy setup step. The actor uses a normal browser session and the public price endpoint.\n\n**Why does a SKU sometimes have no `rating` or `image`?** Those values come from the search card. Direct SKU and product-URL lookups skip the grid, so the actor can fill price, stock, name, brand and taxonomy but may not see the card-only fields. Add a keyword search for the richest row.\n\n**Why is `availability` different from what I see in a store?** The field tracks Best Buy's online button state. Store pickup and nearby inventory depend on a ZIP code and a different fulfillment call, which this actor does not make.\n\n**Can I get more than 24 results?** Yes. Raise `maxResults` and, if needed, `maxPages`. Best Buy caps a search at roughly 200 results for many queries; category pages can expose more.\n\n**What happens when a keyword finds nothing?** The dataset receives a single `bestbuy_error` row with `reason: \"no_results\"` and the inputs that produced it, so a failed run is visible instead of silently empty.\n\n**How do I track a price drop?** Run the same `skuIds` or `productUrls` daily, keep the datasets, and compare `currentPrice` or `savingsPercent` between consecutive runs.\n\n**Is this affiliated with Best Buy?** No. It reads publicly visible product information and is not endorsed by Best Buy.\n",
    "actorDefinition": {
      "actorSpecification": 1,
      "name": "best-buy-price-drop-and-stock-tracker",
      "title": "Best Buy Price Drop & Stock Tracker",
      "description": "Track Best Buy products by keyword, category, product URL or SKU. Get current and regular price, savings, stock status, rating, review count, brand, model and taxonomy in one structured dataset, with pagination, sorting and condition filters.",
      "version": "1.1",
      "buildTag": "latest",
      "defaultMemoryMbytes": 1024,
      "input": {
        "title": "Best Buy Price Drop & Stock Tracker Input",
        "description": "Find Best Buy products by keyword, category/search URL, product URL or SKU. Each record carries current and regular price, savings, stock status, rating, brand and product details.",
        "type": "object",
        "schemaVersion": 1,
        "properties": {
          "searchQueries": {
            "title": "Search keywords",
            "type": "array",
            "description": "One or more Best Buy searches, for example `sony headphones` or `oled tv`. Each query is paginated until `maxResults` is reached.",
            "editor": "stringList",
            "prefill": [
              "sony headphones"
            ],
            "sectionCaption": "What to scrape",
            "sectionDescription": "Use any combination of keyword searches, category links, product links and SKUs. Results are combined and de-duplicated by SKU."
          },
          "categoryUrls": {
            "title": "Category or search URLs",
            "type": "array",
            "description": "Best Buy category, browse or search-result links, e.g. `https://www.bestbuy.com/site/headphones/.../pcmcat....c?id=...`. Pagination, sorting and condition filters are applied automatically.",
            "editor": "stringList",
            "default": []
          },
          "productUrls": {
            "title": "Product URLs",
            "type": "array",
            "description": "Exact Best Buy product links in either the new `/product/.../sku/...` or legacy `/site/.../<sku>.p?skuId=...` format.",
            "editor": "stringList",
            "default": []
          },
          "skuIds": {
            "title": "SKUs",
            "type": "array",
            "description": "Best Buy SKU numbers (6–9 digits). Product links are also accepted here.",
            "editor": "stringList",
            "default": []
          },
          "maxResults": {
            "title": "Max results",
            "type": "integer",
            "description": "Hard cap on the total number of product records emitted across every mode.",
            "default": 24,
            "prefill": 3,
            "minimum": 1,
            "maximum": 1000,
            "sectionCaption": "Limits and pagination",
            "sectionDescription": "Control how many pages are read and how many records are returned."
          },
          "maxPages": {
            "title": "Max pages per query or category",
            "type": "integer",
            "description": "Pagination guard for each keyword or category link. Each page carries up to about 24 products.",
            "default": 50,
            "minimum": 1,
            "maximum": 100
          },
          "sortBy": {
            "title": "Sort results",
            "type": "string",
            "description": "Best Buy's own sort order. Price, rating and discount orders are also enforced on the collected records.",
            "editor": "select",
            "default": "Best-Match",
            "enum": [
              "Best-Match",
              "Best-Selling",
              "Best-Discount",
              "Price-Low-To-High",
              "Price-High-To-Low",
              "Customer-Rating",
              "New-Arrivals"
            ],
            "enumTitles": [
              "Best match",
              "Best selling",
              "Biggest discount",
              "Price: low to high",
              "Price: high to low",
              "Customer rating",
              "New arrivals"
            ],
            "sectionCaption": "Search filters",
            "sectionDescription": "Filters apply to keyword searches and category links; price, condition and stock filters also apply to product URLs and SKUs."
          },
          "condition": {
            "title": "Condition",
            "type": "string",
            "description": "Keep only new, open-box or refurbished products. `All conditions` disables this filter.",
            "editor": "select",
            "default": "all",
            "enum": [
              "all",
              "new",
              "open-box",
              "refurbished"
            ],
            "enumTitles": [
              "All conditions",
              "New",
              "Open-box",
              "Refurbished"
            ]
          },
          "minPrice": {
            "title": "Minimum price ($)",
            "type": "integer",
            "description": "Drop products below this current price. `0` means no minimum.",
            "default": 0,
            "minimum": 0,
            "maximum": 1000000
          },
          "maxPrice": {
            "title": "Maximum price ($)",
            "type": "integer",
            "description": "Drop products above this current price. `0` means no maximum.",
            "default": 0,
            "minimum": 0,
            "maximum": 1000000
          },
          "inStockOnly": {
            "title": "In stock only",
            "type": "boolean",
            "description": "Drop products that Best Buy marks sold out, out of stock or unavailable.",
            "default": false
          },
          "includeDetails": {
            "title": "Include product-page details",
            "type": "boolean",
            "description": "Open each product page for description, model number, GTIN/UPC and seller. Slower; unavailable fields are omitted honestly.",
            "default": false,
            "sectionCaption": "Product details",
            "sectionDescription": "The optional detail pass uses a real browser and is best for small watchlists."
          }
        },
        "required": []
      },
      "output": {
        "actorOutputSchemaVersion": 1,
        "title": "Best Buy Price Drop & Stock Tracker Output",
        "description": "One structured record per Best Buy product with current and regular price, savings, availability, rating, review count, brand, model, images, taxonomy and discovery rank.",
        "properties": {
          "products": {
            "type": "string",
            "title": "Best Buy products",
            "description": "Dataset containing every scraped Best Buy product.",
            "template": "{{links.apiDefaultDatasetUrl}}/items"
          }
        }
      },
      "dockerfile": "../Dockerfile",
      "readme": "# Best Buy Price Drop & Stock Tracker\n\nWatch Best Buy prices and availability without opening a browser tab for every product. Give this actor a few keywords, a category link, product links or SKU numbers, and it returns one structured row per product: what the item is, what it costs now, what it used to cost, whether it is in stock, how shoppers rated it, and where it sits in the result grid.\n\nThe actor runs without a Best Buy account, API key, cookie or proxy setup. It reads the public Best Buy storefront and its public price endpoint, then writes clean product records to the Apify dataset.\n\n## Four ways to build a product list\n\n| Mode | Field | Best for |\n|---|---|---|\n| Keyword search | `searchQueries` | Exploring a category, brand or product idea |\n| Category or search URL | `categoryUrls` | Reusing a Best Buy browse/search link you already trust |\n| Product URL | `productUrls` | Watching exact items you found on the site |\n| SKU | `skuIds` | Feeding a restock or price watchlist from another system |\n\nAll four modes can be combined in a single run. Results are de-duplicated by SKU, filtered, sorted and capped by `maxResults`.\n\n## What you can do with it\n\n- **Price-drop watchlist** — run the same `skuIds` or `productUrls` on a schedule and compare `currentPrice` between datasets. A lower value is a drop; `regularPrice` tells you the reference price.\n- **Restock monitor** — keep `inStockOnly` off and watch `availability` flip from `OutOfStock` to `InStock`.\n- **Category deal scan** — pass a category URL with `sortBy: \"Best-Discount\"` or `condition: \"open-box\"` to surface markdowns and open-box units.\n- **Competitive snapshot** — collect brand, model, rating and review count for every product in a search grid.\n- **Rank tracking** — `position`, `searchPage` and `isSponsored` preserve the grid order Best Buy returned, so you can compare placement across runs.\n\n## Input\n\n| Field | Type | Default | What it does |\n|---|---|---|---|\n| `searchQueries` | array | – | One or more keyword searches (the input form prefills `[\"sony headphones\"]`). Each is paginated until the global result cap is reached. |\n| `categoryUrls` | array | `[]` | Best Buy category, browse or search-result links. `cp` pagination, sort and condition filters are added automatically. |\n| `productUrls` | array | `[]` | Exact product links in new `/product/.../sku/...` or legacy `/site/.../<sku>.p?skuId=...` form. |\n| `skuIds` | array | `[]` | Best Buy SKUs (6–9 digits). Product links are accepted here too. |\n| `maxResults` | integer | `24` | Total records across all modes, 1–1000. |\n| `maxPages` | integer | `50` | Page guard per keyword or category link, 1–100. |\n| `sortBy` | select | `Best-Match` | One of Best-Match, Best-Selling, Best-Discount, Price-Low-To-High, Price-High-To-Low, Customer-Rating, New-Arrivals. |\n| `condition` | select | `all` | `all`, `new`, `open-box` or `refurbished`. |\n| `minPrice` | integer | `0` | Minimum current price in dollars; `0` disables the bound. |\n| `maxPrice` | integer | `0` | Maximum current price in dollars; `0` disables the bound. |\n| `inStockOnly` | boolean | `false` | Drop products Best Buy marks sold out, out of stock or unavailable. |\n| `includeDetails` | boolean | `false` | Open each product page to add description, model, GTIN/UPC and seller where Best Buy publishes them. Slower. |\n\nEvery field in the input form is used by the actor. Older saved tasks that still send `keyword`, `searchQuery`, `categoryUrl`, `skus`, `maxItems`, `sort`, `skipOutOfStock` or `openBoxOnly` keep working: those legacy keys are mapped onto the current fields in code.\n\n### Example: exact-product watchlist\n\n```json\n{\n  \"skuIds\": [\"6505727\", \"6620467\", \"6689192\"],\n  \"inStockOnly\": false,\n  \"maxResults\": 10\n}\n```\n\n### Example: open-box deals in a category\n\n```json\n{\n  \"categoryUrls\": [\n    \"https://www.bestbuy.com/site/headphones/wireless-headphones/pcmcat331200050015.c?id=pcmcat331200050015\"\n  ],\n  \"condition\": \"open-box\",\n  \"sortBy\": \"Price-Low-To-High\",\n  \"maxResults\": 60\n}\n```\n\n### Example: keyword search with a price window\n\n```json\n{\n  \"searchQueries\": [\"sony headphones\", \"noise cancelling earbuds\"],\n  \"minPrice\": 100,\n  \"maxPrice\": 400,\n  \"inStockOnly\": true,\n  \"sortBy\": \"Customer-Rating\",\n  \"maxResults\": 50\n}\n```\n\n### Example: one exact link\n\n```json\n{\n  \"productUrls\": [\n    \"https://www.bestbuy.com/product/sony-wh1000xm5-wireless-noise-canceling-over-the-ear-headphones-black/J7XSRH5CXG/sku/6505727\"\n  ],\n  \"includeDetails\": true\n}\n```\n\n## Output fields\n\n| Field | Type | Meaning |\n|---|---|---|\n| `sku` | string | Best Buy SKU. |\n| `url` | string | Canonical product page URL. |\n| `bsin` | string | Best Buy canonical product-family identifier, when the URL exposes it. |\n| `name` | string | Product title. |\n| `description` | string | Product description, from the optional detail pass. |\n| `brand` | string | Manufacturer brand. |\n| `model` | string | Model number or MPN, from the optional detail pass. |\n| `gtin13` | string | GTIN/UPC, from the optional detail pass. |\n| `image`, `imageUrl` | string | Primary product image (same value under both keys). |\n| `currentPrice` | number | Price shown to a shopper now. |\n| `regularPrice` | number | Non-sale reference price. |\n| `salePrice` | number | Current price when it is below the regular price. |\n| `savings` | number | Regular price minus current price. |\n| `savingsPercent` | number | Savings as a percentage of the regular price. |\n| `onSale` | boolean | True when the current price is below the regular price. |\n| `currency`, `currencySymbol` | string | ISO currency code and display symbol. |\n| `availability` | string | Normalized stock state, e.g. `InStock`, `OutOfStock`, `PreOrder`, `BackOrder`, `LimitedAvailability`. |\n| `availabilityText` | string | Best Buy's own button text, e.g. `Add to Cart` or `Sold Out`. |\n| `buttonState` | string | Raw Best Buy button state. |\n| `priceType` | string | Best Buy price event type, e.g. `onSale` or `clearance`. |\n| `condition` | string | `new`, `open-box` or `refurbished` when known. |\n| `productType` | string | Best Buy product type, e.g. `hardgood`. |\n| `department`, `productClass`, `subclass` | string | Best Buy taxonomy labels. |\n| `categoryPath` | array | Department → class → subclass path. |\n| `rating` | number | Average customer rating. |\n| `reviewCount` | integer | Number of customer reviews. |\n| `seller` | string | Seller name, from the optional detail pass. |\n| `isSponsored` | boolean | True when the result card is labelled Sponsored. |\n| `dealBadge` | string | Best Buy promotional badge, e.g. `Trending Deal` or `Holiday Deal`. |\n| `position` | integer | 1-based position in this run's output after sorting. |\n| `searchPage` | integer | Result page where a search/category product was found. |\n| `searchTotalResults` | integer | Best Buy's reported result count for that query or category. |\n| `searchQuery` | string | Keyword or category URL that produced the record. |\n| `source` | string | `search`, `category`, `productUrl` or `sku`. |\n| `scrapedAt` | string | ISO-8601 UTC collection timestamp. |\n\nFields Best Buy does not publish for a product are omitted rather than sent as `null` or an empty string. Missing price, rating or detail fields therefore mean “not available on this page”, not zero.\n\n## How it works\n\n1. Keyword and category modes load Best Buy's result grid in a real headless browser, scroll it to hydrate lazy cards, and read the rendered product cards. A direct-HTML fallback reads the server-rendered product data if the browser grid is empty.\n2. Product URL and SKU modes skip search and go straight to Best Buy's public price endpoint, batching up to 20 SKUs per request.\n3. Every mode merges the card data with the price/stock response, so price, savings and availability come from Best Buy's current price source rather than a cached grid tile. If that endpoint omits a SKU, the price shown on the hydrated result card fills the row.\n4. Optional detail enrichment opens each product page and reads its structured product data for description, model, GTIN and seller.\n5. Filters and sorting are applied once the merged records exist; duplicates are removed by SKU.\n\nThe actor adds `intl=nosplash` to every request. That tells Best Buy to serve the US storefront instead of its international country selector.\n\n## Limitations and honest notes\n\n- **Online availability only.** Best Buy's per-store, per-ZIP inventory needs a location-bound fulfillment session. This actor reports the national online stock state and does not claim store-level counts.\n- **No stored price history.** The actor is stateless. Schedule it and keep each dataset, or write the rows to a spreadsheet, to build a price timeline.\n- **Detail fields are best-effort and often unavailable.** Best Buy resets product-page requests from many datacenter IPs. In cloud runs `description`, `model`, `gtin13` and `seller` are therefore usually omitted; the price and stock row still ships, and `includeDetails` never blocks it.\n- **SKUs with no usable data are skipped.** If Best Buy returns neither a name nor a price for a product (retired, region-locked, or a price-endpoint miss), that row is not emitted. `maxResults` is a cap, not a guarantee, so a run can return fewer rows. A run that finds no product at all returns one `bestbuy_error` row with `reason: \"no_results\"`.\n- **Full specification sheets are not included.** The detail pass reads structured product data, not the interactive spec table.\n- **Individual reviews are not included.** Use `rating` and `reviewCount` for reception; review text belongs to a dedicated reviews actor.\n- **Marketplace offers are summarized, not enumerated.** The record follows the primary offer Best Buy displays.\n\n## FAQ\n\n**Do I need a Best Buy API key?** No. The actor reads public storefront and price data. It does not use the gated developer API.\n\n**Do I need a proxy?** No. There is no proxy field and no proxy setup step. The actor uses a normal browser session and the public price endpoint.\n\n**Why does a SKU sometimes have no `rating` or `image`?** Those values come from the search card. Direct SKU and product-URL lookups skip the grid, so the actor can fill price, stock, name, brand and taxonomy but may not see the card-only fields. Add a keyword search for the richest row.\n\n**Why is `availability` different from what I see in a store?** The field tracks Best Buy's online button state. Store pickup and nearby inventory depend on a ZIP code and a different fulfillment call, which this actor does not make.\n\n**Can I get more than 24 results?** Yes. Raise `maxResults` and, if needed, `maxPages`. Best Buy caps a search at roughly 200 results for many queries; category pages can expose more.\n\n**What happens when a keyword finds nothing?** The dataset receives a single `bestbuy_error` row with `reason: \"no_results\"` and the inputs that produced it, so a failed run is visible instead of silently empty.\n\n**How do I track a price drop?** Run the same `skuIds` or `productUrls` daily, keep the datasets, and compare `currentPrice` or `savingsPercent` between consecutive runs.\n\n**Is this affiliated with Best Buy?** No. It reads publicly visible product information and is not endorsed by Best Buy.\n",
      "storages": {
        "dataset": {
          "actorSpecification": 1,
          "views": {
            "overview": {
              "title": "Best Buy Products",
              "transformation": {
                "fields": [
                  "sku",
                  "name",
                  "brand",
                  "currentPrice",
                  "regularPrice",
                  "savings",
                  "savingsPercent",
                  "onSale",
                  "availability",
                  "availabilityText",
                  "rating",
                  "reviewCount",
                  "condition",
                  "categoryPath",
                  "isSponsored",
                  "position",
                  "url"
                ]
              },
              "display": {
                "component": "table",
                "properties": {
                  "sku": {
                    "label": "SKU"
                  },
                  "name": {
                    "label": "Product"
                  },
                  "brand": {
                    "label": "Brand"
                  },
                  "currentPrice": {
                    "label": "Current Price"
                  },
                  "regularPrice": {
                    "label": "Regular Price"
                  },
                  "savings": {
                    "label": "Savings"
                  },
                  "savingsPercent": {
                    "label": "Savings %"
                  },
                  "onSale": {
                    "label": "On Sale"
                  },
                  "availability": {
                    "label": "Stock"
                  },
                  "availabilityText": {
                    "label": "Stock Text"
                  },
                  "rating": {
                    "label": "Rating"
                  },
                  "reviewCount": {
                    "label": "Reviews"
                  },
                  "condition": {
                    "label": "Condition"
                  },
                  "categoryPath": {
                    "label": "Category"
                  },
                  "isSponsored": {
                    "label": "Sponsored"
                  },
                  "position": {
                    "label": "Position"
                  },
                  "url": {
                    "label": "URL",
                    "format": "link"
                  }
                }
              }
            }
          }
        }
      },
      "defaultRunOptions": {
        "build": "latest",
        "timeoutSecs": 1800,
        "memoryMbytes": 1024
      }
    },
    "buildNumber": "1.1.1",
    "imageDigest": "5992fb1787e9378edfca1716df5ad26582c0e2e5f5cfb56a077e1f9c9f87a7ba",
    "actVersion": {
      "sourceType": "SOURCE_FILES",
      "buildTag": "latest",
      "versionNumber": "1.1"
    },
    "usage": {
      "ACTOR_COMPUTE_UNITS": 0.03211222222222222
    }
  }
}