By the end of this tutorial, you will have a Python script that turns a walmart.com.mx keyword search into structured JSON: one row per product with the price in Mexican pesos, the was-price and discount when the site shows one, stock status, the seller (Walmart itself or a marketplace seller), rating, review count and category path.
This is for anyone tracking prices on Walmart Mexico: comparing TV prices across sellers, watching discounts, or checking which products are out of stock. We use the Apify Actor Walmart Mexico Scraper (reventadata/walmart-mexico-scraper), called from Python through the Apify API. You will learn how to configure a search, filter by seller, price and stock, run the Actor and read its rows.
⏱️ Time estimate: About 20 minutes.
Prerequisites
To follow this tutorial, you will need:
-
Python 3.11+ installed locally (
apify-client3.x requires it). - The Apify API client for Python.
- An Apify account and API token. Your token is on the API & Integrations page in Apify Console.
Install the client:
pip install "apify-client~=3.0"
The code loads the token from an environment variable:
export APIFY_API_TOKEN="your_apify_token_here"
What you'll achieve
You will run a keyword search on walmart.com.mx and get back one row per product: title, url, price in MXN, wasPrice, savingsAmount and discountPercent when a was-price is shown, availability and inStock, seller and sellerType (WALMART or MARKETPLACE), rating, reviewCount, categories, badges and the instalment text.
Note: The Actor is unofficial and not affiliated with Walmart or Walmart de Mexico. It reads search result pages and
/browse/category pages, the page types the site's robots.txt leaves open, and does not open product pages.
Example use case: Suppose you want the cheapest TVs that Walmart itself sells and has in stock. Set searchQueries: ["televisor"], sort: "PRICE_ASC", seller: "WALMART" and onlyInStock: true, and the dataset holds those rows from the pages it walks (maxPages, default 5), cheapest first.
Step 1: Access Walmart Mexico Scraper
Go to the Walmart Mexico Scraper page on Apify Store. It lists every input field and the output format.
In this tutorial we run it from Python, so all we need from the page is the Actor name: reventadata/walmart-mexico-scraper.
Step 2: Configure search parameters
The main input is searchQueries: a list of keywords in Spanish, as a shopper would type them, for example televisor or leche deslactosada. The Actor walks each keyword's result pages and saves one row per product. A result page holds 40 to 54 products.
If the site treats a keyword as a category (laptop is one), the Actor follows it to that category page. You can also give category pages directly in startUrls, as https://www.walmart.com.mx/browse/... URLs copied from the site.
Let's initialize the client and define the input:
import os
from apify_client import ApifyClient
# 1. Initialize ApifyClient with token from environment
client = ApifyClient(os.environ["APIFY_API_TOKEN"])
# 2. Define the extraction parameters
run_input = {
"searchQueries": ["televisor"],
"maxItems": 20,
"maxPages": 1,
"sort": "PRICE_ASC",
}
This asks for the first result page of televisor, cheapest first, and stops at 20 saved products.
Step 3: Configure optional settings and filters
Every filter below runs before a row is saved, so dropped products never reach your dataset:
| Parameter | Default | What it does |
|---|---|---|
searchQueries |
none | Keywords to search. |
startUrls |
none | Category pages (/browse/...). Search and product URLs are refused. |
maxItems |
100 |
Total products to save, counted after the filters. |
maxPages |
5 |
Result pages per keyword or category, 1 to 25. |
sort |
BEST_MATCH |
BEST_MATCH, PRICE_ASC or PRICE_DESC. |
minPrice, maxPrice
|
none | Price band in MXN, sent to the site and checked again on each row. |
minRating |
none | Minimum average rating, 0 to 5. Unrated products are dropped when set. |
onlyDiscounted |
false |
Keep only products with a was-price above the price. |
onlyInStock |
false |
Drop products the site marks out of stock. |
seller |
ANY |
ANY, WALMART or MARKETPLACE. |
includeSponsored |
false |
Sponsored slots are dropped unless this is on. |
includeKeywords, excludeKeywords
|
none | Words the title, brand or category must or must not contain, ignoring case and accents. |
💡 A few combinations that work well:
-
Cheapest first:
sort: "PRICE_ASC"with a smallmaxItemsreturns the bottom of the price list. -
Deals only:
onlyDiscounted: truekeeps rows with a was-price above the selling price. -
Walmart stock only:
seller: "WALMART"plusonlyInStock: true.
Step 4: Run the Actor
Now we start the run with .call(), which waits until the Actor finishes, and then read the dataset:
# 3. Start the Actor run and wait for it to complete
print("Starting Walmart Mexico extraction...")
run = client.actor("reventadata/walmart-mexico-scraper").call(run_input=run_input)
if run is None or run.status != "SUCCEEDED":
status = run.status if run else "unknown"
raise SystemExit(f"Run did not succeed (status: {status}).")
# 4. Fetch the resulting dataset items
dataset = client.dataset(run.default_dataset_id).list_items().items
print(f"Extraction complete! Retrieved {len(dataset)} products.\n")
Behind the scenes:
- The Actor fetches each result page through an Apify residential proxy in Mexico, its default. In testing on 2026-10-21, requests without a proxy and through datacenter proxies got a block page instead of results.
- When the site answers with a block page, the Actor retries on a fresh residential exit while the run has time left.
- It reads the product data the page embeds as JSON, applies your filters, and saves each product once, even when it appears on several pages.
Step 5: View and download results
Let's print the fields that matter for price tracking:
for item in dataset:
print(item.get("title"))
print(f" Price: {item.get('price')} MXN")
if item.get("wasPrice") is not None:
print(f" Was: {item['wasPrice']} MXN ({item.get('discountPercent')}% off)")
print(f" Seller: {item.get('seller')} ({item.get('sellerType')})")
print(f" In stock: {item.get('inStock')}")
if item.get("rating") is not None:
print(f" Rating: {item.get('rating')} from {item.get('reviewCount')} ratings")
print("-" * 50)
The dataset also exports as JSON, CSV, XML, Excel, HTML table, RSS or JSONL.
Here is a sample from a capture dated 2026-10-21: page 12 of the televisor search, parsed by the Actor's own row builder (not output of the snippet above; scrapedAt, added when a row is saved, is left out):
{
"id": "00880609633127",
"title": "TV LG 77 Pulgadas OLED AI B5 4K Smart TV webOS 2025",
"url": "https://www.walmart.com.mx/ip/TV-LG-77-Pulgadas-OLED-AI-B5-4K-Smart-TV-webOS-2025/00880609633127",
"brand": null,
"price": 29990.0,
"currency": "MXN",
"wasPrice": 39990.0,
"savingsAmount": 10000.0,
"discountPercent": 25,
"installments": "Hasta 24 meses sin intereses",
"availability": "IN_STOCK",
"inStock": true,
"seller": "Walmart",
"sellerType": "WALMART",
"rating": 4.9,
"reviewCount": 6490,
"department": "Electrónica",
"categories": [
"TV y Video",
"Pantallas",
"Todas"
],
"image": "https://i5-mx.walmartimages.com/asr/a65686fa-eaa8-44bd-9670-6e9c3fe8440d.e22fb0ae34da230f03548804b8d9e2e6.jpeg",
"badges": [
"Rebaja"
],
"variantCount": null,
"isSponsored": false,
"sourceQuery": "televisor",
"sourceUrl": "https://www.walmart.com.mx/search?q=televisor&z=1&page=12",
"page": 12
}
Understanding your results
The key fields:
-
price: selling price in MXN as shown on the result page. -
wasPrice,savingsAmount: the was-price and the saving,nullwhen no was-price above the price is shown. -
discountPercent: computed by the Actor frompriceandwasPrice, rounded to a whole number. -
availability,inStock: the site's stock status and whether it isIN_STOCK. Out-of-stock products keep their price. -
seller,sellerType: seller name, andWALMARTorMARKETPLACE. -
rating,reviewCount: bothnullfor a product nobody has rated, so an unrated product never shows as zero stars. -
brand: given on sponsored slots only; organic results carrynull. -
badges: promotion labels on the tile, such asRebaja. -
sourceQuery,sourceUrl,page: where the row came from.
What one page looks like: the 2026-10-21 capture of page 12 held 54 products, 44 organic and 10 sponsored. Of the 44 organic rows, 25 were marketplace offers and 19 sold by Walmart; 39 were in stock and 5 out of stock; 28 showed a was-price and 16 did not; 24 were rated and 20 unrated.
Pro tips
-
Sort before you cap.
maxItemsstops the run once that many rows are saved. Withsort: "PRICE_ASC"or"PRICE_DESC", a small cap returns the cheapest or dearest products first. -
Sponsored slots are off by default. The site repeats 7 to 10 sponsored slots on every page of a result. Set
includeSponsored: trueif you want them; every row carriesisSponsored. -
Use the price band.
minPriceandmaxPricego to the site in the search URL, so pages hold fewer off-band products, and each row is checked again. -
Narrow with words.
includeKeywords: ["oled"]keeps only products whose title, brand or category contains "oled";excludeKeywordsdrops the ones that do. Matching ignores case and accents, sotelevisionalso matchesTelevisión. -
Go deeper with
maxPages. The default is 5 pages per keyword. Raise it up to 25 for a fuller walk of a broad keyword; the site's own last page ends the walk earlier.
Troubleshooting
-
Run ended FAILED with no rows: the Actor fails a run that saves zero products, so an empty result never looks like success. Check the keyword spelling and loosen
minRating, the price band or the seller filter. -
A start URL was refused:
startUrlstakes only/browse/category pages. A search URL stops the run with a message telling you to put the keyword insearchQueries. -
Invalid
sortorseller: both accept fixed values; any other value is refused before the run starts. - Prices differ from what you see signed in: rows show what an anonymous visitor with no store chosen sees, which can differ from what a signed-in shopper near a given store sees.
-
Reading the log: the last line starts
Run finished: N rows pushed.and lists rejections by reason. Read it withclient.log(run.id).get().
Next steps
To repeat a search, save the input as a task and add an Apify schedule, which starts an Actor or task on a cron expression. To trigger your own code when a run succeeds, add a webhook on ACTOR.RUN.SUCCEEDED: its payload carries the run, including defaultDatasetId.
For current pricing and details, see the Store page.
Links:
Which Walmart Mexico prices are you planning to track? Drop a comment! 💬
Top comments (0)