# Best Buy Scraper: Prices, Deals, Open-Box & Stock (`moggedhq/best-buy-scraper`) Actor

Get Best Buy products with price, regular price and savings, deal labels, open-box prices by condition, pickup and shipping availability for your ZIP, SKU, model, UPC, brand, rating and reviews. Search, categories or product links. About $0.003 per product. No login.

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

## Pricing

from $2.40 / 1,000 products

This Actor is paid per event. You are not charged for the Apify platform usage, but only a fixed price for specific events.
Since this Actor supports Apify Store discounts, the price gets lower the higher subscription plan you have.

Learn more: https://docs.apify.com/actors/running/actors-in-store.md#pay-per-event

## What's an Apify Actor?

An Actor is a serverless cloud program that runs on the Apify platform. It has two run modes.
In Batch mode, an Actor accepts a well-defined JSON input, performs an action which can take anything from a few seconds to a few hours,
and optionally produces a well-defined JSON output, datasets with results, or files in key-value store.
In Standby mode, an Actor provides a web server which can be used as a website, API, or an MCP server.

Apify vocabulary and the platform model are defined once, in the agent quickstart at https://apify.com/agents.md.

## How to integrate an Actor?

If asked about integration, you help developers integrate Actors into their projects.
You adapt to their stack and deliver integrations that are safe, well-documented, and production-ready.

Do not guess an integration path. Every one of them is in the agent quickstart at https://apify.com/agents.md: the Apify MCP server, Agent Skills with the Apify CLI, the JavaScript and Python clients, the REST API, and the account-free path for an agent with no human to sign in. It also carries the rule on stating cost before the first paid run.

For examples already wired to this Actor's own input schema, see the [API](#api) section below.

Each client library has reference documentation the quickstart does not restate: [JavaScript/TypeScript](https://docs.apify.com/api/client/js/docs.md) (`npm install apify-client`) and [Python](https://docs.apify.com/api/client/python/docs.md) (`pip install apify-client`).

# README

## Best Buy Scraper: Prices, Deals, Open-Box & Stock

For price analysts, electronics brands, comparison services and resellers who need Best Buy prices and pickup stock in a repeatable dataset. Search for laptops, headphones or TVs, read a category or promotion page, or monitor a list of known SKUs at selected stores.

About **$0.003 per saved product at one store**. A run with 20 product/store rows costs about **$0.06**, and 1,000 rows cost about **$3**, plus the small start charge. Apify plan discounts apply. No Best Buy login or developer key is needed.

The core inputs and output fields match our Safeway & Albertsons Scraper for shared retail integrations.

### What you get

Each `PRODUCT` row describes one SKU at one verified store. Prices are national USD quotes; pickup inventory belongs to that store. ZIPs select the nearest public pickup store, while store IDs select it directly.

| Data | Fields |
| --- | --- |
| Readable result | `verdict`, `recordType` |
| Store context | `retailer`, `country`, `currency`, `storeId`, `storeName`, `location`, `storeZip`, `storeDistance`, `requestedLocations` |
| Product identity | `productId`, `sku`, `gtin`, `upc`, `modelNumber`, `bsin`, `title`, `brand`, `condition`, `sellerType` |
| Current and reference price | `price`, `regularPrice`, `onSale` |
| Sale evidence | `promoText`, `promoType`, `promoStart`, `promoEnd`, `badges`, `isDeal` |
| Paid-member quotes | `memberPrice`, `memberProgram`, `memberPrices` |
| Open-box quotes | `openBox`, with source condition, condition code, price, SKU and URL |
| Store stock | `inStock`, `stockLevel`, `pickupAvailable`, `pickupDate`, `pickupType` |
| Shipping | `shippingAvailable`, `shippingZip`, `shippingBackordered`, `buttonState` |
| Product metadata | `rating`, `reviewCount`, `category`, `url`, `imageUrl`, `scrapedAt` |
| Optional metadata | `details`, with available source specifications, descriptions, features and images |
| Shared retail placeholders | `size`, `unitPrice`, `unitOfMeasure` remain null when unavailable |

Missing information stays `null`; stock, dates and prices are never guessed.

### Start in three steps

1. Enter a search term, a public Best Buy URL or numeric SKUs. Leave the other source arrays empty when you only want a watchlist.
2. Enter ZIP codes or exact store IDs. Set the global product limit and, for search jobs, the limit for each source at each store.
3. Run the Actor and open the Overview dataset view. Export JSON, CSV or Excel, or read the dataset using the Apify API.

A bounded first search:

```json
{
  "searchTerms": ["laptop"],
  "locations": ["10001"],
  "maxItemsPerSearch": 20,
  "maxItems": 20
}
```

The November 3, 2026 cloud suite passed 32 varied inputs across six ZIPs. Two large exports each delivered 1,100 products, including a real reboot check. Ten live comparisons matched prices, identity, stock and shipping; a changed pickup date matched on a fresh repeat.

### Input reference

| Input | Meaning |
| --- | --- |
| `searchTerms` | Array of terms such as `laptop`, `wireless headphones` or `OLED TV`. Default source: `laptop`. |
| `startUrls` | Optional Bestbuy.com search, category, promotion or SKU-specific product links. Legacy numeric `.p` product links are also accepted. |
| `productIds` | Numeric Best Buy SKUs. These are retailer product numbers, not UPCs or model numbers. Up to 5,000 input SKUs. |
| `locations` | US ZIP codes. Each resolves to one nearest public pickup store. ZIP+4 values are reduced to five digits. |
| `storeIds` | Exact numeric store IDs. Takes precedence over `locations`. |
| `maxItemsPerSearch` | Maximum newly delivered rows for each search, category or promotion source at each store. Default 20; maximum 2,000. |
| `maxItems` | Global maximum across all products and stores. Default 20; maximum 10,000. |
| `dealsOnly` | Keep source sales, qualifying deal badges or lower publicly advertised paid-member quotes. Default false. |
| `includeDetails` | Fetch optional specifications, descriptions, features and image metadata. Default false. No separate details fee. |
| `proxyConfiguration` | Optional Apify or custom routing. Default uses datacenter, with fresh-session retries and US residential fallback for transport failures. |

Empty location arrays use fallback store 7, Roseville. Use explicit locations for scheduled monitors and check `SUMMARY.resolvedStores` before importing.

Duplicates at one store are saved and charged once. ZIPs resolving to the same store are retained in `requestedLocations`. One SKU at two stores produces two rows.

Bad types, malformed ZIPs and unsupported external URLs produce a free `NOTE` row and an invalid-input summary. An unknown SKU or an unavailable source is reported without a product charge. Other valid source jobs can continue after a source failure.

### Monitor prices every day

Known-SKU monitoring avoids changes in search rankings and is suitable for scheduled catalogs, comparison feeds and daily price observations:

```json
{
  "productIds": ["6671006", "6611536", "6671806"],
  "storeIds": ["482", "1028"],
  "maxItems": 6,
  "includeDetails": false
}
```

Save a tested input as an Apify Task. In Apify Console, create a Schedule for that task and choose the cadence your data pipeline needs. Use `storeId` plus `productId` as the destination key, and retain `scrapedAt` to build history. A repeated scheduled run is a new observation and can charge for the same product again.

Compare consecutive datasets in a database, spreadsheet, Make or n8n workflow to build history or alerts. Check `SUMMARY.status`, `freeFailures` and stores before importing. Partial results should not erase a complete catalog.

After migration or reboot, saved dataset rows are recovered and reconciled with acknowledged charges before new delivery continues. Product/store keys prevent duplicate delivery within the run.

### Categories, promotions and filters

A category export:

```json
{
  "startUrls": [
    "https://www.bestbuy.com/site/laptop-computers/all-laptops/pcmcat138500050001.c"
  ],
  "locations": ["90210"],
  "maxItemsPerSearch": 100,
  "maxItems": 100
}
```

A retailer promotion page:

```json
{
  "startUrls": ["https://www.bestbuy.com/site/promo/laptop-and-computer-deals"],
  "locations": ["60601"],
  "maxItems": 20
}
```

Use `dealsOnly` with keyword or category jobs. Search/category URLs retain `qp` facets. Best Buy controls ordering and featured marketplace offers. Keyword searches exclude source-declared unrelated fallbacks. Use SKUs for exact monitoring.

Bare canonical `/product/.../BSIN` links need a numeric SKU separately. Use `/sku/NUMBER` or `productIds`; unresolved identities produce free notes.

### Understand price, stock and offer conditions

`price` is the current price for the row's exact SKU and source condition. `regularPrice` is the source reference price; it is not proof that shoppers previously paid that amount. Taxes, shipping fees, installation, protection plans and financing are not added to the price. Marketplace products may appear, and `sellerType` preserves the source classification. `1P` denotes Best Buy's own offer.

Open-box prices are a separate array. For example, the November 3 check of SKU 6671006 returned a new-product price of $1,199.99 and distinct Excellent, Good and Fair quotes. An open-box quote is not substituted into the new-product price, and it does not establish that a unit of that condition is available at the requested store. Conditions and quantities can change independently.

Paid-member prices come from the signed-out page's public what-if quotes. `memberPrices` retains the source program codes and savings; `memberPrice` is the lowest lower quote. This does not establish your membership eligibility, apply an offer or clip a coupon. The main product price remains separate.

`inStock` reflects the selected store's reported in-store inventory flag. `pickupAvailable` can be true when an item can be shipped to the store, even when shelf inventory is false. Check `pickupType` and `pickupDate` alongside it. `shippingAvailable` uses the requested ZIP, shown as `shippingZip`; exact-store inputs use the store ZIP. When ZIPs collapse to one store, shipping uses the first ZIP.

Best Buy sometimes reports large quantity codes such as `9999`; these are not audited physical counts. `stockLevel` is populated only for source counts from zero to three. Higher codes stay null. Stock and pickup dates are observations that can change; they do not reserve a product.

`promoEnd` is populated when the price response supplies a deal-expiration timestamp. `promoStart` remains null when the source gives no start date for the price promotion. General campaign badge dates remain in `badges`; a campaign running through a future year does not become the end date of today's sale. Size and unit-price fields stay null when Best Buy does not supply them.

### Dataset views and run summary

Overview shows prices, promotions, stock and store. Deals exposes `isDeal` and offer columns. Full product data includes identifiers, condition quotes and details.

`SUMMARY` is a key-value store record with:

- `products`, `stores`, `dealsFound` and `chargedProducts`;
- `status`, `freeFailures`, `spendingLimitReached` and `duplicateExclusions`;
- `resolvedStores`, per-source `outcomes`, source request counts and free `notes`.

The `DEALS` record contains the returned deal rows for ordinary-sized exports. For larger exports, its response points you to the dataset view and `isDeal` field. Notes and summaries have no product fee. A summary marked `complete` describes completed source processing, not an exhaustive export of Best Buy's entire catalog.

### Pricing and spending limits

One primary Product charge applies to each distinct saved product/store row. Optional details, open-box quotes, retries and duplicate source hits have no additional product fee. Notes and empty results have no Product charge. Apify's configured start charge is $0.00005 per allocated GB, with a minimum of one start event.

| Saved product/store rows | Base Product fees | Bronze Product fees |
| ---: | ---: | ---: |
| 20 | $0.06 | $0.057 |
| 100 | $0.30 | $0.285 |
| 1,000 | $3.00 | $2.85 |
| 5,000 | $15.00 | $14.25 |

Bronze is 5% below the base Product price, Silver 10% below, and Gold and higher listed tiers 20% below. Apify displays the price applicable to your plan. The small start fee is additional. A product monitored at five stores is five rows; set `maxItems` and the run's maximum total charge to bound the job.

When the charge limit leaves no room for another Product, collection stops cleanly. The run summary reports that limit. Invalid input and missing products do not create paid empty product rows. Apify subscription and destination charges are separate.

### API use

Use your own Apify token and keep it in an environment variable. Start a run, wait for it to finish, then read its dataset and summary. This Python example uses the official Apify client:

```python
import os
from apify_client import ApifyClient

client = ApifyClient(os.environ["APIFY_TOKEN"])
run = client.actor("moggedhq/best-buy-scraper").call(run_input={
    "productIds": ["6671006", "6611536"],
    "storeIds": ["482"],
    "maxItems": 2,
})
summary = client.key_value_store(run["defaultKeyValueStoreId"]).get_record("SUMMARY")
for row in client.dataset(run["defaultDatasetId"]).iterate_items():
    if row.get("recordType") == "PRODUCT":
        print(row["storeId"], row["sku"], row["price"], row["inStock"])
```

Safeway/Albertsons integrations can reuse the core input and output names. Retailer SKU values and store numbers differ.

### Use with AI agents (MCP)

Use Apify's MCP server at `https://mcp.apify.com` with an explicit request, for example: “Get Best Buy laptop prices, regular prices, UPCs, open-box condition quotes and pickup stock near ZIP 10001, up to 20 rows.” For a scheduled watchlist, provide exact SKUs and store numbers.

The agent should inspect the schema, set a charge cap and read `SUMMARY` before importing. Missing rows are coverage issues, never assumed zero prices or stock observations.

### Coverage and limitations

Reads public signed-out US data without accounts or verification solving. It makes no purchases or reservations. Independently operated; not affiliated with or endorsed by Best Buy.

Public source access can change. A product may be retired, unpriced, unavailable or missing optional metadata. Search is not a complete inventory of every variant or marketplace offer. Promotion pages may include products without a numeric discount. Exact shelf counts, local open-box inventory, full promotion start dates and membership eligibility are not guaranteed. Use Best Buy's current terms and the requirements that apply to your workflow.

### FAQ

**Does the ZIP change the product price?** Best Buy prices returned here are national. The ZIP selects a store and its pickup observation. The resolved store is always included.

**Why are dates or exact stock counts null?** Those values are not always published. The Actor keeps missing dates and non-exact quantity codes null rather than creating values.

**What happens after a source failure?** Missing rows have no Product charge. Existing rows remain in the dataset, notes explain coverage issues, and the summary identifies a partial result.

Aggregate ratings are included; individual reviewer profiles and account data are not exported.

# Actor input Schema

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

Find Best Buy products such as laptop, headphones or OLED TV. Each term is searched at each selected store.

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

Bestbuy.com category, search, promotion or product links. SKU-specific and legacy product links are accepted. A canonical product link without a SKU may require the numeric product ID.

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

Numeric Best Buy SKUs, such as 6671006 or 6611536. Ideal for scheduled product watchlists.

## `locations` (type: `array`):

US ZIP codes, such as 10001 or 90210. Selects the nearest public Best Buy pickup store. Empty uses the site fallback store 7 (Roseville).

## `storeIds` (type: `array`):

Exact Best Buy store numbers, such as 482 or 1028. Overrides ZIP locations; each store is verified.

## `maxItemsPerSearch` (type: `integer`):

Maximum new product rows from each term, category or deals source at one store. Duplicates are free.

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

Global limit across products and stores. About $0.003 per product: 20 products cost about $0.06 plus the small start charge.

## `dealsOnly` (type: `boolean`):

Keep sales, deal badges and publicly advertised paid-member prices. Open-box quotes remain separate from the main product price.

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

Optional source specifications, features, descriptions and images. No extra fee. Missing fields remain null.

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

Default: datacenter first, with US residential only after refused datacenter attempts. You may supply your own proxy configuration.

## Actor input object example

```json
{
  "searchTerms": [
    "laptop"
  ],
  "locations": [
    "10001"
  ],
  "maxItemsPerSearch": 20,
  "maxItems": 20,
  "dealsOnly": false,
  "includeDetails": false,
  "proxyConfiguration": {
    "useApifyProxy": true
  }
}
```

# Actor output Schema

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

No description

## `dealsView` (type: `string`):

No description

## `dealsOnly` (type: `string`):

No description

## `summary` (type: `string`):

No description

# API

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

## JavaScript example

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

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

// Prepare Actor input
const input = {
    "searchTerms": [
        "laptop"
    ],
    "locations": [
        "10001"
    ],
    "maxItemsPerSearch": 20,
    "maxItems": 20
};

// Run the Actor and wait for it to finish
const run = await client.actor("moggedhq/best-buy-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": ["laptop"],
    "locations": ["10001"],
    "maxItemsPerSearch": 20,
    "maxItems": 20,
}

# Run the Actor and wait for it to finish
run = client.actor("moggedhq/best-buy-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": [
    "laptop"
  ],
  "locations": [
    "10001"
  ],
  "maxItemsPerSearch": 20,
  "maxItems": 20
}' |
apify call moggedhq/best-buy-scraper --silent --output-dataset

```

## MCP server setup

```json
{
    "mcpServers": {
        "apify": {
            "type": "http",
            "url": "https://mcp.apify.com/?tools=fetch-actor-details,moggedhq/best-buy-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/qQoim4CMWgUClVsdc/builds/25ftvvQechWeeMiWz/openapi.json
