# Walmart Scraper - Products, Prices, Ratings, Sellers (`s-r/walmart-scraper`) Actor

Search Walmart and get products as clean rows: title, brand, model, UPC, category, rating, review count, availability, seller and the real current price from each product page. No browser and no CAPTCHA solving on your side.

- **URL**: https://apify.com/s-r/walmart-scraper.md
- **Developed by:** [SR](https://apify.com/s-r) (community)
- **Categories:** E-commerce, Automation
- **Stats:** 2 total users, 1 monthly users, 100.0% runs succeeded, 0 bookmarks
- **User rating**: No ratings yet

## Pricing

Pay per event

This Actor is paid per event. You are not charged for the Apify platform usage, but only a fixed price for specific events.

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

## Walmart Scraper

Search Walmart and get products back as rows: name, brand, rating, review count, availability, seller, and optionally the **real current price** from each product's own page.

No browser, no CAPTCHA solver.

### What you get

- **Products from the search and category pages**, about 60 per page, with rating and review count on nearly every row
- **The barcode (UPC) on every detailed row.** Walmart publishes it on the product page, and it is an exact join key against any other catalogue: match a Walmart listing to a Beslist, Discogs or Amazon record without fuzzy title matching
- **Price, brand, seller, category path and description**, all from each product's own page. Walmart serves none of them in search results, so they come with the detail stage
- **Prices that belong to the right product.** A Walmart product page carries dozens of price blocks: variants, bundles, "similar items" and sponsored rails. This actor anchors on the product's own id and refuses to reach beyond a bounded window, so a row either gets its own price or none at all
- **`was_price` where there is a genuine markdown**, filtered so it must be above the current price
- **Sponsored placements flagged** rather than mixed in silently
- **`price_source` on every priced row**, saying whether the number was found next to this product's id or elsewhere on its page

### Two things worth knowing before you run it

**Walmart answers HTTP 200 to everything**, including to requests it refuses, where the body is a 15 KB "Robot or human?" page. Judging this site by status code alone says it is wide open; judging by size alone says it is closed. Both are wrong, which is why this Actor scores success on the product data itself.

**The search payload has its prices removed.** A successful request returns the full product list with names, brands, ratings and review counts, and `price: 0` with an empty price block on every single product. This is Walmart's choice, not a parsing failure, and it is invisible if you count how often the word "price" appears in the JSON: the keys are all present, the values are not.

That is why prices are a separate, opt-in stage. It is one request per product instead of one per sixty, so a priced run is far slower and costs more. Making that a checkbox rather than doing it silently is the point.

### Input

| Field | Type | Required | Default | What it does |
|---|---|---|---|---|
| `query` | string | one of the two | `laptop` | What to search for |
| `url` | string | one of the two | – | A Walmart search or category URL. Takes precedence |
| `fetch_prices` | boolean | no | `false` | Open each product's page for price, UPC, brand, seller, category and description |
| `limit` | integer | no | `60` | Products to return, 1 to 600 |
| `retries` | integer | no | `3` | Retry attempts per page |

### Output

```json
{
  "position": 2,
  "item_id": "18656507313",
  "url": "https://www.walmart.com/ip/HP-14-inch-HD-Windows-Laptop/18656507313",
  "title": "HP 14 inch HD Windows Laptop Intel Processor N150 4GB 128GB UFS Waterfall Blue",
  "rating": 4.1,
  "reviews_count": 805,
  "availability": "IN_STOCK",
  "sponsored": false,
  "price": 259.0,
  "was_price": 379.0,
  "price_text": "$259.00",
  "currency": "USD",
  "price_source": "product_page",
  "query": "laptop"
}
```

### Use cases

**Catalogue and assortment work, cheaply.** Leave `fetch_prices` off and a run is one request per sixty products. You get the full product list with ratings and review counts, which is enough to see what Walmart stocks in a category and which items have traction.

**Price monitoring on a shortlist.** Turn `fetch_prices` on for a narrow query rather than a broad one. Fifty tracked products is fifty requests, which is a sensible daily job; five thousand is not.

**Finding what people actually buy.** `reviews_count` beside `rating` separates a 4,8 with eleven reviews from a 4,1 with eight hundred. The second is the one that sells.

**Marketplace seller research.** `seller` shows where a listing is Walmart's own and where it is a third party, which is the same question the Amazon buy box answers.

**Watching promotions.** `was_price` is only set when there is a real markdown, so a scheduled priced run on a small set is a discount alert.

### How it compares

| | this actor |
|---|---|
| Per 1.000 products | **$1,00** |
| Per 1.000 resolved prices | **$3,00**, and only for prices actually found |
| Needs a browser | **no** |
| Prices anchored to the right product | **yes** |
| Sponsored placements flagged | **yes** |

Most published Walmart actors reach the site through a browser or a paid unblocking service, because the plain request returns a bot wall. This one uses a crawler identity that Walmart still serves, which is why it is fast and cheap, and which is also its main risk: single-identity routes close. If it does, the run reports `bot_wall` and explains it rather than returning nothing.

### Pricing

Three events. `run_start` costs $0,0010 per run. `product` costs $0,0010 per product written, which is $1,00 per 1.000. `product_detail` costs $0,0030 and is charged **only when a product page was actually read**, never for a lookup that came back empty.

### Limits and gotchas

- **No prices without `fetch_prices`.** This is Walmart's doing. The run summary says so on every unpriced run rather than leaving an empty column unexplained.
- **The price comes from the product's own object, not from nearby text.** An earlier build searched forward from the product id for the closest price block and kept finding the "similar items" rail: it returned $949,99, then $539 on the next run, for a Chromebook that was neither. Reading `priceInfo` off the object already matched on `usItemId` cannot pick up a neighbour's price. Prices are now stable run to run.
- **Priced runs are slow.** One request per product, deliberately unparallelised. Sixty products takes minutes; six hundred takes a long time. Set the actor timeout accordingly.
- **`brand` is sparse** because Walmart often omits it from the search payload.
- **Sponsored rows are included**, flagged with `sponsored`, because filtering them out silently would misrepresent what the page shows.
- **US only.**

### FAQ

**Why are all my prices and barcodes empty?**
Because `fetch_prices` is off. Walmart's search payload has no price, no UPC, usually no brand and no category path. All of it lives on the product page, so it costs one request per product.

**Can I get the barcode?**
Yes, `upc`, with the detail stage on. It came back on every row in testing.

**Why did some products get no price even with `fetch_prices` on?**
Because no price block was found close enough to that product's own id on its page. The actor reports that as absent rather than substituting a nearby number that may belong to a different product.

**Does it need a proxy or a browser?**
A residential US exit, yes. A browser, no.

**How many products can I get?**
Up to 600. Without prices that is ten requests; with prices it is 610.

### Related Actors

- [Newegg Scraper](https://apify.com/s-r/newegg-scraper) — US retail with real discounts on the listing page
- [Amazon Buy Box Monitor](https://apify.com/s-r/amazon-buybox) — who currently wins an Amazon listing
- [Target Scraper](https://apify.com/s-r/target-scraper) — the other big US general retailer

# Actor input Schema

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

What to search for on walmart.com. Optional if you pass a URL.

## `url` (type: `string`):

A walmart.com search or category URL to read instead. Takes precedence.

## `fetch_prices` (type: `boolean`):

Open each product's own page to get its price, barcode (UPC), brand, seller, category path and description. Walmart serves none of these in search results. One extra request per product, so runs are much slower and cost more.

## `limit` (type: `integer`):

How many products to return, 1 to 600. A page carries about 60.

## `retries` (type: `integer`):

Retry attempts per page, each with a rotated identity and TLS fingerprint.

## Actor input object example

```json
{
  "query": "laptop",
  "url": "https://www.walmart.com/browse/electronics/laptops/3944_3951_1089430",
  "fetch_prices": false,
  "limit": 60,
  "retries": 3
}
```

# Actor output Schema

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

One row per product.

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

Products returned, rating coverage, how many prices were resolved and how many price lookups failed.

## `errors` (type: `string`):

Per-page failures with a code and a redacted message.

# 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": "laptop",
    "limit": 60,
    "retries": 3
};

// Run the Actor and wait for it to finish
const run = await client.actor("s-r/walmart-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": "laptop",
    "limit": 60,
    "retries": 3,
}

# Run the Actor and wait for it to finish
run = client.actor("s-r/walmart-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": "laptop",
  "limit": 60,
  "retries": 3
}' |
apify call s-r/walmart-scraper --silent --output-dataset

```

## MCP server setup

```json
{
    "mcpServers": {
        "apify": {
            "type": "http",
            "url": "https://mcp.apify.com/?tools=fetch-actor-details,s-r/walmart-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/diIVtSOoJ8ASc7Yzo/builds/9npSJAwou5IXRz4L2/openapi.json
