# Best Buy Products Scraper (`benthepythondev/bestbuy-scraper`) Actor

Export Best Buy product prices, ratings, model numbers and specifications by keyword, category or SKU. Direct HTTP access with optional proxies.

- **URL**: https://apify.com/benthepythondev/bestbuy-scraper.md
- **Developed by:** [Ben](https://apify.com/benthepythondev) (community)
- **Categories:** E-commerce, Developer tools, Automation
- **Stats:** 68 total users, 9 monthly users, 89.0% runs succeeded, 0 bookmarks
- **User rating**: No ratings yet

## Pricing

from $2.00 / 1,000 results

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 Product Scraper

Export Best Buy products by keyword, category URL or product URL. Each saved row contains a verified SKU, its current customer price, title, brand, model number, rating and review count. You can also include specifications, features, descriptions and image URLs.

The Actor reads Best Buy's public product API. It does not need a Best Buy login, developer key or browser. Direct access is the default; an Apify or custom proxy is optional. It downloads product data rather than photos, fonts, advertisements or browser bundles.

Use it for product price monitoring, catalog enrichment and comparisons across brands. Local store inventory and delivery promises are outside its coverage. The `availability` and `isSponsored` compatibility fields are null because this API path does not verify them.

### Start with a small export

This input retrieves up to 25 laptop products, following another search page when needed:

```json
{
  "mode": "search",
  "searchQuery": "laptop",
  "maxProducts": 25,
  "includeSpecifications": false
}
```

After the run, open the default dataset's Overview table. Export it as JSON, CSV or Excel, or read the dataset through the Apify API. `maxProducts` limits saved rows, including when some source products are excluded by filters. A lower run charge limit can reduce this further; the log reports the affordable row count before collecting products. The same SKU is saved once per run.

Start with a bounded query before scheduling a larger export. Search rankings, prices and offer conditions can change between requests. A run is a current observation, not a permanent price quote or a reservation of stock.

### Input

| Field | Behavior |
|---|---|
| `mode` | `search`, `category` or `direct_urls` |
| `searchQuery` | Search terms; defaults to `laptop` |
| `categoryUrl` | A public Best Buy category URL ending in `.c`; existing URL facets are retained |
| `productUrls` | Current product links, canonical product links or legacy SKU links ending in `.p` |
| `maxProducts` | Saved-product limit, from 1 to 1,000; default 5 |
| `minPrice`, `maxPrice` | Inclusive USD bounds, checked against the price actually exported |
| `brands` | Brand names, such as `Lenovo`, `HP` or `Dell` |
| `minRating` | Minimum rating; products without a rating cannot satisfy this filter |
| `onSaleOnly` | Require a positive source-reported saving |
| `openBoxOnly` | Select the lowest-priced matching open-box offer for each SKU |
| `sortBy` | `bestMatch`, `priceLow`, `priceHigh`, `rating`, `bestSelling` or `newest` |
| `includeSpecifications` | Include specifications, description, features and image URLs in search/category output |
| `proxyConfiguration` | Optional routing; direct access is the default |

A price-filtered Lenovo search:

```json
{
  "mode": "search",
  "searchQuery": "laptop",
  "brands": ["Lenovo"],
  "minPrice": 500,
  "maxPrice": 1000,
  "sortBy": "priceLow",
  "maxProducts": 25
}
```

A minimum-only price filter is checked against returned products and can require more search pages. Two-sided and maximum-only bounds also use Best Buy's native range filter. Source product groups can contain several offers, so returned prices are checked again before saving. Sorting follows Best Buy's ordering; a group's ranking is not a guarantee that every selected offer has the same ordering by price.

For category mode, use a URL such as `https://www.bestbuy.com/site/laptop-computers/all-laptops/pcmcat138500050001.c`. For direct mode, provide `productUrls` and set `mode` to `direct_urls`. Direct exports always include the available detail fields. Canonical links are resolved to their current featured SKU; providing the canonical link and that SKU link together produces one row.

The old `debugMode` browser setting is no longer needed. The old `zipCode` input did not control local inventory and is not offered.

### Output and price meaning

This shortened example was fetched on September 5, 2026. Its prices and review totals will change:

```json
{
  "skuId": "6671006",
  "title": "Lenovo - Yoga 7i 2-in-1 16\" 2K Touchscreen Laptop - Core Ultra 7 Processor 256V 2024 - 16GB Memory - 512GB SSD- Copilot+ PC - Luna Grey",
  "brand": "Lenovo",
  "modelNumber": "83JT0047US",
  "price": 749.99,
  "originalPrice": 1199.99,
  "savings": 450,
  "savingsPercent": 37.5,
  "onSale": true,
  "rating": 4.9,
  "reviewCount": 80,
  "condition": "new",
  "openBoxCondition": null,
  "availability": null,
  "isSponsored": null,
  "source": "bestbuy"
}
```

The full row also includes the canonical SKU URL, primary image URL and UTC `scrapedAt` timestamp. Detail output adds `specifications` as a name/value object, `features` as a text array, `description`, and an `images` array. Missing optional fields remain empty or null. Specifications differ by product category; the Actor does not invent missing attributes.

`price` belongs to the same SKU and open-box condition as the row. It is not a savings amount, a financing payment or an unrelated alternative offer. `originalPrice` is Best Buy's displayed reference price, which may be described as comparable value. It does not prove a previous transaction price. `reviewCount` is an aggregate count; individual customer reviews are not exported.

With `openBoxOnly`, the Actor selects one matching offer per SKU and retains the source's `openBoxCondition` code. The code is not converted into an assumed condition label. An open-box price is not substituted into a normal new-product row. Offer availability can change; check the product page before making a purchase.

### Charges

The Free-tier Actor fee is **$0.0025 per saved product**, or **$2.50 per 1,000 products**, plus the configured startup event. Startup costs $0.00005 per allocated GB, with a minimum of one event. Store plan discounts apply to the published events.

At 512 MB, the nominal Free-tier Actor fees are:

| Saved products | Actor fees |
|---:|---:|
| 5 | $0.01255 |
| 25 | $0.06255 |
| 1,000 | $2.50005 |

Specifications have no extra result surcharge. Duplicate input links and duplicate page results do not create extra saved-product charges. A repeated run can export and charge for the same products again; use `skuId` to compare or update records in your own destination. Your subscription and downstream integration costs are separate.

### Coverage, empty results and failures

Best Buy's search is broader than exact text matching. When Best Buy answers only with related products, or quietly searches for a different term than the one you typed, the Actor saves nothing, charges nothing and writes a warning to the log. If Best Buy corrected a typo, the warning names the term it used, so you can run that term instead.

A search without matches finishes successfully with zero rows. Filtered-out products produce no saved-row charge.

In a list of product URLs, one bad entry does not stop the run. A retired SKU, a product without a current price or a link that is not a Best Buy product page is skipped with a warning, and the remaining products are saved. In a search, a listing whose name, link or price cannot be verified is left out and counted in the log.

A run fails only when Best Buy cannot be read at all: the first search page does not load, or none of the product URLs can be fetched. If Best Buy stops answering after some pages, the rows already saved stay in the dataset and the log says where the run stopped.

Bundle offers are excluded so every row represents one SKU and its own price. Marketplace products can appear in Best Buy's results. The Actor does not guarantee that every item is sold directly by Best Buy. It does not provide ZIP-specific stock, pickup times, delivery dates or a complete inventory of every variant. Source access can change, and a successful small run does not establish reliability for every category or volume.

### Scheduling and support

Create an Apify Task with tested input, then schedule it or call it through the API. Compare rows by SKU and condition, retain timestamps, and avoid overwriting a good dataset with a failed run's partial output. JSON preserves nested specifications and image arrays more faithfully than a flat spreadsheet export.

If a run fails or a field looks wrong, open an issue on this Actor with the run URL, expected SKU and relevant input. Enable shared debugging if you want the run's input and logs inspected. Do not include API tokens or destination credentials in an issue. An honest Store review after testing a real workflow helps other users understand where the Actor fits.

# Actor input Schema

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

Choose how to scrape products

## `searchQuery` (type: `string`):

Search keywords (e.g., 'laptop', 'gaming laptop', 'macbook pro')

## `categoryUrl` (type: `string`):

Best Buy category page URL (for category mode)

## `productUrls` (type: `array`):

Direct URLs to specific Best Buy products (for direct_urls mode)

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

Minimum price filter

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

Maximum price filter

## `brands` (type: `array`):

Filter by brand names (e.g., HP, Dell, Apple, Lenovo, ASUS)

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

Minimum customer rating (1-5)

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

Only show products that are on sale

## `openBoxOnly` (type: `boolean`):

Only show open box deals

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

Sort order for search results

## `maxProducts` (type: `integer`):

Maximum number of products to scrape

## `includeSpecifications` (type: `boolean`):

Include source specifications, features, description and image URLs. These fields can be empty when Best Buy does not supply them.

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

Public API requests use direct access by default. You may supply an Apify or custom proxy.

## Actor input object example

```json
{
  "mode": "search",
  "searchQuery": "laptop",
  "categoryUrl": "https://www.bestbuy.com/site/all-laptops/pc-laptops/pcmcat247400050000.c",
  "productUrls": [
    "https://www.bestbuy.com/site/apple-macbook-air-13-inch-laptop/6534606.p"
  ],
  "minPrice": 500,
  "maxPrice": 2000,
  "brands": [
    "HP",
    "Dell",
    "Apple"
  ],
  "minRating": 4,
  "onSaleOnly": false,
  "openBoxOnly": false,
  "sortBy": "bestMatch",
  "maxProducts": 5,
  "includeSpecifications": false,
  "proxyConfiguration": {
    "useApifyProxy": false
  }
}
```

# Actor output Schema

## `results` (type: `string`):

No description

# API

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

## JavaScript example

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

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

// Prepare Actor input
const input = {
    "mode": "search",
    "searchQuery": "laptop",
    "maxProducts": 5
};

// Run the Actor and wait for it to finish
const run = await client.actor("benthepythondev/bestbuy-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": "search",
    "searchQuery": "laptop",
    "maxProducts": 5,
}

# Run the Actor and wait for it to finish
run = client.actor("benthepythondev/bestbuy-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": "search",
  "searchQuery": "laptop",
  "maxProducts": 5
}' |
apify call benthepythondev/bestbuy-scraper --silent --output-dataset

```

## MCP server setup

```json
{
    "mcpServers": {
        "apify": {
            "type": "http",
            "url": "https://mcp.apify.com/?tools=fetch-actor-details,benthepythondev/bestbuy-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/pbUZ4z2ORsyKhZshL/builds/1BKTuE1ExWpMkxDh5/openapi.json
