# Best Buy Product Scraper (`mrdoe/bestbuy-product-scraper`) Actor

Extract Best Buy products, prices, ratings, reviews, brands, images, availability and product details. Search by keyword or fetch products by SKU, with batch support and clean structured output.

- **URL**: https://apify.com/mrdoe/bestbuy-product-scraper.md
- **Developed by:** [MrDoe](https://apify.com/mrdoe) (community)
- **Categories:** E-commerce, Developer tools, Automation
- **Stats:** 2 total users, 1 monthly users, 0.0% runs succeeded, 0 bookmarks
- **User rating**: No ratings yet

## Pricing

from $0.70 / 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?

Actors are web data automations that power AI and operations. They run on the Apify platform to scrape websites, process data, connect APIs, and automate workflows.
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.
Actors are written with capital "A".

## 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.
The best way to integrate Actors is as follows.

- **AI agents and MCP clients** — the [Apify MCP server](https://docs.apify.com/integrations/mcp.md) at `https://mcp.apify.com` (remote, streamable HTTP, OAuth on first use).
- **Agentic workflows and local Actor development** — [Agent Skills](https://apify.com/.well-known/agent-skills/index.json) with the [Apify CLI](https://docs.apify.com/cli/docs.md): `npm install -g apify-cli`, then `apify login`.
- **JavaScript/TypeScript projects** — the official [JS/TS client](https://docs.apify.com/api/client/js/docs.md): `npm install apify-client`.
- **Python projects** — the official [Python client](https://docs.apify.com/api/client/python/docs.md): `pip install apify-client`.
- **Any other language** — the [REST API](https://docs.apify.com/api/v2.md).

For usage examples, see the [API](#api) section below.

For more details, see Apify documentation as [Markdown index](https://docs.apify.com/llms.txt) and [Markdown full-text](https://docs.apify.com/llms-full.txt).

# README

![Website Preview](./assets/website-preview.png)

### What does Best Buy Product Scraper do?

**Best Buy Product Scraper** extracts product data from [BestBuy.com](https://www.bestbuy.com) - keyword search results and full product detail pages - **anonymously, no login, no Best Buy account, no API key**. Two operations live in one actor: search for products by keyword, or look up full detail for one or many SKUs.

### Why use this Actor?

- **Price tracking** - schedule `productDetails` on a cron and diff consecutive runs to catch price drops and restocks.
- **Market research / assortment mapping** - `search` gives you ranked results for any keyword, with price, rating, review count, and sponsored-listing badges.
- **Batch, one start fee** - pass a list of keywords or SKUs and one run covers all of them.

### How to use it

1. Pick an **Operation**: Product Search or Product Details.
2. Fill the matching field:
   - **Search** → `query` (e.g. `coffee maker`) or `queries` for a batch.
   - **Product Details** → `sku` (e.g. `6570530`) or a full product URL, or `skus` for a batch.
3. Optionally set `maxItems` to cap total rows.
4. Click **Start**.

There is no page cap on `search` by default - it follows a query through to Best Buy's own last reported page. Batch a lot of keywords and this can produce a very large run; use `maxItems` to bound it.

Batch fields (`queries`/`skus`) win over their singular counterparts when filled; duplicates and blanks are dropped automatically.

### Input

| Field                | Type              | Description                                                                                            |
| -------------------- | ----------------- | ------------------------------------------------------------------------------------------------------ |
| `operation`          | string (required) | One of: `search`, `productDetails`.                                                                    |
| `query` / `queries`  | string / array    | Search keyword(s). Required by `search`.                                                               |
| `sku` / `skus`       | string / array    | A Best Buy SKU (e.g. `6570530`) or a full product URL. Used by `productDetails`.                       |
| `maxItems`           | integer           | Caps total rows returned across the run. First 10 rows are free. Leave blank for no cap.               |
| `proxyConfiguration` | object            | A residential US proxy is strongly recommended - see [Why a real browser?](#why-a-real-browser) below. |

### Why a real browser?

Live-verified (2026-08-25): a plain, cookie-less HTTP request (curl, `got-scraping`) to any bestbuy.com URL hangs indefinitely - Akamai completes the TLS handshake and then never answers, a client-fingerprint-level block with no response to parse around. A real browser is required.

More surprising: **plain headless Chromium works for search but not for product pages** - the same client that successfully renders `/site/searchpage.jsp` gets `net::ERR_HTTP2_PROTOCOL_ERROR` on every attempt at a `/product/.../sku/{id}` page, live-verified across three retries and two navigation methods (direct URL, in-page link click). [Camoufox](https://camoufox.com/) (a fingerprint-patched Firefox, driven through Playwright's Firefox launcher) gets through both reliably, so this Actor standardizes on it for every request rather than mixing browser engines.

A residential **US** proxy is the default - Best Buy geo-redirects non-US traffic to a "Choose your country" splash page. This Actor also appends `intl=nosplash` to every request (the same bypass the site's own "Continue to the US site" link uses) as a second layer of defense against that redirect.

### Output

One flat row per item. Search rows carry search-result fields; product-detail rows carry the full page (parsed from Best Buy's own embedded schema.org `Product` JSON-LD - live-verified far more reliable than hand-picking CSS selectors against the page's heavily-obfuscated utility classes). Every row has `_operation` and `status` (`success` or `error`) so you can split/filter a mixed export.

Search row example:

```json
{
    "_operation": "search",
    "sku": "6570530",
    "title": "Ninja - Hot & Iced XL Coffee Maker with Rapid Cold Brew 12-cup Drip Coffee Maker & Single Serve Brewing - Black",
    "price": 139.99,
    "listPrice": 179.99,
    "currency": "USD",
    "rating": 4.8,
    "reviewCount": 291,
    "image": "https://pisces.bbystatic.com/image2/BestBuy_US/images/products/6570/6570530_sd.jpg",
    "productUrl": "https://www.bestbuy.com/product/ninja-hot-iced-xl-coffee-maker-with-rapid-cold-brew-12-cup-drip-coffee-maker-single-serve-brewing-black/JXJVXGVT3C/sku/6570530",
    "isSponsored": false,
    "query": "coffee maker",
    "status": "success"
}
```

Product detail row example:

```json
{
    "_operation": "productDetails",
    "sku": "6570530",
    "title": "Ninja - Hot & Iced XL Coffee Maker with Rapid Cold Brew 12-cup Drip Coffee Maker & Single Serve Brewing - Black",
    "brand": "Ninja",
    "model": "CM371",
    "color": "Black",
    "price": 139.99,
    "currency": "USD",
    "availability": "InStock",
    "outOfStock": false,
    "rating": 4.8,
    "reviewCount": 291,
    "image": "https://pisces.bbystatic.com/image2/BestBuy_US/images/products/6570/6570530_sd.jpg",
    "images": ["https://pisces.bbystatic.com/image2/BestBuy_US/images/products/6570/6570530_sd.jpg"],
    "sampleReviews": [{ "rating": 5, "title": "...", "text": "...", "author": "JamieT" }],
    "specs": { "Coffee Preparation Method": "Drip" },
    "productUrl": "https://www.bestbuy.com/product/ninja-hot-iced-xl-coffee-maker-with-rapid-cold-brew-12-cup-drip-coffee-maker-single-serve-brewing-black/JXJVXGVT3C/sku/6570530",
    "status": "success"
}
```

### Pricing

This Actor uses pay-per-event pricing - one small run-start charge, then a per-row charge for each search result or product-detail lookup. See the **Pricing** tab for current rates. Failed lookups land as `status: "error"` rows and are never charged. There is no page cap - `search` runs to Best Buy's own last reported page for each keyword unless you set `maxItems`.

### Limitations

- Only the numbers/text Best Buy shows to an anonymous, logged-out guest are available.
- Best Buy's search grid lazy-hydrates below the fold (cards render a bare placeholder until scrolled into view) - this Actor scrolls the full result page before extracting, but a very slow-loading page could still occasionally miss a card; those cards are silently skipped rather than pushed as garbage rows (verified: title is always present on a real card).
- `sampleReviews` on `productDetails` is a small sample embedded in the page's own JSON-LD (typically 1-3 reviews), not the full review history.
- US site (bestbuy.com) only in this version.
- Best Buy's page markup drifts over time; the extraction code targets stable structures (`#main-results`, `data-testid` attributes, the embedded `Product` JSON-LD) but a large redesign may need an update.

### FAQ

**Does Best Buy have a public API?** Best Buy's Developer API exists but requires an approved API key application and is rate-limited for approved partner use, not general scraping. This Actor gets you search and product data anonymously, no approval process.

**Do I need a Best Buy account or API key?** No - it runs entirely against Best Buy's public, logged-out web pages.

**Why did I get redirected to a country-selection page?** That's Best Buy's own geo-detection - this Actor already works around it (see [Why a real browser?](#why-a-real-browser)), but if you're using a custom, non-US proxy this can still surface. Use the default US residential proxy configuration.

### Disclaimer

This Actor is an independent tool, not affiliated with or endorsed by Best Buy Co., Inc. It only accesses data Best Buy serves publicly to anonymous visitors. Use it in compliance with Best Buy's Terms of Use and applicable law in your jurisdiction. Found a bug or have a feature request? Use the Issues tab on this Actor's page.

# Actor input Schema

## `operation` (type: `string`):

Which Best Buy data to scrape. One operation per run.

## `query` (type: `string`):

Keyword to search Best Buy, e.g. "coffee maker". Used by the search operation. Defaults to a demo query if left blank.

## `queries` (type: `array`):

Many keywords in one run. Wins over "query" when filled. Duplicates and blanks are dropped.

## `sku` (type: `string`):

A Best Buy SKU (e.g. "6570530") or a full product URL. Used by the productDetails operation. Defaults to a demo product if left blank.

## `skus` (type: `array`):

Many SKUs or product URLs in one run. Wins over "sku" when filled.

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

Caps total rows returned across the whole run (applies to search; productDetails always returns one row per SKU). The first 10 rows of any run are free. Leave blank for no cap - the search operation then follows Best Buy's own reported max page for the query.

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

Best Buy's Akamai bot-protection blocks plain HTTP outright and blocks product pages under plain headless Chromium; this Actor drives a fingerprint-patched real browser (Camoufox). A residential proxy is strongly recommended for sustained volume.

## Actor input object example

```json
{
  "operation": "search",
  "query": "coffee maker",
  "sku": "6570530",
  "proxyConfiguration": {
    "useApifyProxy": true,
    "apifyProxyGroups": [
      "RESIDENTIAL"
    ],
    "apifyProxyCountry": "US"
  }
}
```

# Actor output Schema

## `overview` (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 = {
    "query": "coffee maker",
    "sku": "6570530"
};

// Run the Actor and wait for it to finish
const run = await client.actor("mrdoe/bestbuy-product-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 = {
    "query": "coffee maker",
    "sku": "6570530",
}

# Run the Actor and wait for it to finish
run = client.actor("mrdoe/bestbuy-product-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 '{
  "query": "coffee maker",
  "sku": "6570530"
}' |
apify call mrdoe/bestbuy-product-scraper --silent --output-dataset

```

## MCP server setup

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