Checking a Walmart product's price once tells you what it costs today. To know when that price drops, you need to collect it regularly, save previous prices, and compare each new result against the history.
In this tutorial, you'll build a Walmart price tracker with Python and Spidra. It will collect product prices, store a timestamped history in SQLite, and send an alert when a price falls below your target or drops significantly. You'll also learn how to schedule the script to run automatically.
How the Walmart price tracker works
A price tracker needs three things: a way to retrieve current product prices, somewhere to store previous observations, and logic to detect changes.
We'll use Spidra to retrieve Walmart product data, Python's built-in SQLite database to store price history, and an optional Discord webhook for notifications.
The workflow is straightforward:
- Read the Walmart products you want to track from a CSV file.
- Retrieve the current product price and seller information.
- Save the price with a timestamp.
- Compare the new price against the previous observation.
- Send an alert when a configured threshold is reached.
We'll focus on the featured offer for each product. This matters because Walmart listings can include multiple sellers offering the same item at different prices and conditions.
Get Walmart product prices with Python
Let's start with a real product.
We'll track the Sony WH-1000XM5 wireless headphones in black.
The Walmart product data includes its title, price, availability, seller, and additional offers.
Here's an excerpt of the structured data for this product:
{
"type": "product",
"usItemId": "386006068",
"title": "Sony WH-1000XM5 The Best Wireless Noise Canceling Headphones, Black",
"brand": "Sony",
"condition": "New",
"price": 298,
"currency": "USD",
"availability": "In stock",
"inStock": true,
"seller": {
"name": "Focus Camera"
},
"marketplace": "walmart.com"
}This product was listed at $298 when the data was collected on October 28, 2026. We'll use that price as our initial example, although the live price may differ when you run the script.
Set up Spidra
You'll need Python 3.9 or later and a Spidra API key.
Create a Spidra account, generate an API key, and install the Python SDK:
pip install spidraSet your API key as an environment variable. On macOS or Linux:
export SPIDRA_API_KEY="spd_YOUR_API_KEY"On Windows PowerShell:
$env:SPIDRA_API_KEY="spd_YOUR_API_KEY"Create a file named inspect_walmart.py:
# inspect_walmart.py
import os
from spidra import Spidra
client = Spidra(api_key=os.environ["SPIDRA_API_KEY"])
url = "https://www.walmart.com/ip/386006068"
result = client.scrape(url, output="json")
product = result.content
print(product["title"])
print(f"Price: ${product['price']:.2f}")
print(f"Seller: {product['seller']['name']}")Run it:
python inspect_walmart.pyUsing the captured product response, the output is:
Sony WH-1000XM5 The Best Wireless Noise Canceling Headphones, Black
Price: $298.00
Seller: Focus CameraFor Walmart product URLs, Spidra returns structured JSON containing fields such as price, condition, inStock, and seller. You don't need to inspect HTML elements or maintain CSS selectors for those fields.
You can find the available product fields in the Walmart data documentation.
Now that we can retrieve a price, let's build the tracker.
Create a list of Walmart products to track
Instead of hardcoding a single product into the tracker, we'll read products from a CSV file. That makes it easy to add more listings without editing the Python code.
Create products_to_track.csv:
name,url,target_price
Sony WH-1000XM5 (Black),https://www.walmart.com/ip/386006068,275The target_price column defines when you want an alert. In this example, we want to know when the headphones fall to $275 or less.
You can add additional rows for other products. Each product can have its own target price.
Store Walmart price history with SQLite
A tracker needs to preserve previous observations. Without that history, it cannot tell whether a product became cheaper or more expensive.
We'll use SQLite because it's included with Python and doesn't require setting up a database server.
For every successful observation, the script will save:
- Walmart item ID and product URL
- Product name and current price
- Currency and seller
- Location associated with the captured offer
- Date and time of the observation
The price is stored as an integer number of cents. This avoids floating-point rounding problems when comparing monetary values.
We'll also compare prices only within the same seller and location context. If the featured seller changes, the new offer starts with its own baseline rather than being mistaken for a price drop from the previous seller.
Build the complete Walmart price tracker
Create walmart_price_tracker.py and add the following code:
# walmart_price_tracker.py
import csv
import json
import os
import sqlite3
from datetime import datetime, timezone
from decimal import Decimal, InvalidOperation, ROUND_HALF_UP
from pathlib import Path
from urllib.error import URLError
from urllib.request import Request, urlopen
from spidra import Spidra, SpidraError
PRODUCTS_CSV = Path("products_to_track.csv")
DATABASE = Path("walmart_prices.db")
WEBHOOK_URL = os.getenv("DISCORD_WEBHOOK_URL")
DROP_ALERT_PERCENT = Decimal("5")
def as_price(value):
if value is None or isinstance(value, bool):
return None
try:
price = Decimal(str(value))
except (InvalidOperation, ValueError):
return None
return (
price.quantize(Decimal("0.01"), rounding=ROUND_HALF_UP)
if price.is_finite() and price > 0
else None
)
def get_product(client, url):
response = client.scrape(url, output="json")
data = response.content
if isinstance(data, str):
data = json.loads(data)
if (
not isinstance(data, dict)
or data.get("type") != "product"
or data.get("marketplace") != "walmart.com"
):
raise ValueError("Expected structured Walmart product data")
return data
def notify(message):
print(f" ALERT: {message}")
if not WEBHOOK_URL:
return
request = Request(
WEBHOOK_URL,
data=json.dumps({"content": message}).encode("utf-8"),
headers={"Content-Type": "application/json"},
method="POST",
)
try:
with urlopen(request, timeout=10):
pass
except (URLError, TimeoutError) as exc:
print(f" Discord notification failed: {exc}")
def setup_database(connection):
connection.execute("""
CREATE TABLE IF NOT EXISTS prices (
id INTEGER PRIMARY KEY AUTOINCREMENT,
item_id TEXT NOT NULL,
url TEXT NOT NULL,
observed_at TEXT NOT NULL,
price_cents INTEGER NOT NULL,
currency TEXT NOT NULL,
seller_id TEXT NOT NULL,
seller_name TEXT NOT NULL,
postal_code TEXT NOT NULL,
product_name TEXT NOT NULL
)
""")
connection.commit()
def check_product(client, connection, config):
name = config["name"]
data = get_product(client, config["url"])
price = as_price(data.get("price"))
if price is None:
print(f"{name}: no usable price; skipping")
return
if data.get("condition") != "New" or data.get("inStock") is not True:
print(f"{name}: featured offer is not a new, in-stock item; skipping")
return
if data.get("currency") != "USD":
print(f"{name}: price is not in USD; skipping")
return
seller = data.get("seller") or {}
location = data.get("location") or {}
item_id = str(data["usItemId"])
seller_id = str(seller.get("id") or seller.get("name") or "unknown")
seller_name = seller.get("name") or "Unknown seller"
postal_code = str(location.get("postalCode") or "unknown")
currency = data["currency"]
observed_at = datetime.now(timezone.utc).isoformat(timespec="seconds")
cents = int(price * 100)
previous = connection.execute("""
SELECT price_cents FROM prices
WHERE item_id = ?
AND seller_id = ?
AND postal_code = ?
AND currency = ?
ORDER BY id DESC LIMIT 1
""", (item_id, seller_id, postal_code, currency)).fetchone()
connection.execute("""
INSERT INTO prices (
item_id, url, observed_at, price_cents, currency, seller_id,
seller_name, postal_code, product_name
) VALUES (?, ?, ?, ?, ?, ?, ?, ?, ?)
""", (
item_id, config["url"], observed_at, cents, currency,
seller_id, seller_name, postal_code, data["title"]
))
connection.commit()
print(f"{name}: ${price:.2f} {currency} | {seller_name}")
if previous is None:
print(" Baseline saved; no alert on the first comparable observation.")
return
old_price = Decimal(previous[0]) / 100
if price == old_price:
print(" Price unchanged.")
return
direction = "down" if price < old_price else "up"
print(f" Price {direction} from ${old_price:.2f} to ${price:.2f}.")
if price >= old_price:
return
target = as_price(config.get("target_price"))
drop_pct = (old_price - price) / old_price * 100
target_crossed = (
target is not None and old_price > target >= price
)
large_drop = drop_pct >= DROP_ALERT_PERCENT
if target_crossed or large_drop:
reason = (
f"target ${target:.2f} reached"
if target_crossed
else f"price dropped {drop_pct:.1f}%"
)
notify(
f"{name}: ${old_price:.2f} -> ${price:.2f} "
f"({reason}). Seller: {seller_name}. {config['url']}"
)
def main():
client = Spidra(api_key=os.environ["SPIDRA_API_KEY"])
with PRODUCTS_CSV.open(newline="", encoding="utf-8") as handle:
products = list(csv.DictReader(handle))
with sqlite3.connect(DATABASE) as connection:
setup_database(connection)
for product in products:
try:
check_product(client, connection, product)
except (SpidraError, ValueError, KeyError) as exc:
print(
f"{product['name']}: could not check product ({exc})"
)
if __name__ == "__main__":
main()The script handles extraction, storage, and price comparisons in one file.
A few parts are worth understanding.
get_product() retrieves the Walmart listing as structured JSON using Spidra.
setup_database() creates the SQLite table the first time the script runs. On later executions, the existing table and its price history are preserved.
check_product() retrieves the current price, validates the product's availability and condition, finds the previous comparable observation, and writes the latest result.
Finally, notify() prints an alert to the terminal and optionally sends the same message to Discord.
The tracker uses two notification rules: a product crosses its configured target price, or its price drops by at least 5% compared with the previous comparable observation.
Run the Walmart price tracker
Make sure products_to_track.csv and walmart_price_tracker.py are in the same directory.
Run:
python walmart_price_tracker.pyUsing the Sony product data shown earlier, the initial output is:
Sony WH-1000XM5 (Black): $298.00 USD | Focus Camera
Baseline saved; no alert on the first comparable observation.The script also creates walmart_prices.db in the project directory.
The first execution creates a baseline. There is no previous price to compare against, so the tracker doesn't send a change alert yet.
On subsequent executions, the script looks up the latest comparable observation and checks whether the price increased, decreased, or stayed the same.
If the price hasn't changed, it prints:
Price unchanged.If the price decreases, the script calculates the difference and checks your notification rules.
For example, a future drop from $298 to $269 would cross the $275 target and trigger an alert. That is an illustration of the alert logic, not a claim that Walmart's live price has fallen to $269.
Why the tracker checks seller and product condition
The Sony listing contains several offers from different sellers. The captured data includes a $298 featured new offer, an alternative new offer at $288, an open-box offer at $189, and restored offers.
Our tracker intentionally uses the top-level price, which represents the featured offer, rather than choosing the lowest price from every offer.
It also checks that the featured item is new and in stock.
A cheaper restored or open-box product shouldn't be treated as a discount on a new product. Likewise, if Walmart switches the featured offer to another seller, the script records that seller separately.
This produces a more useful history for tracking individual offers. If your goal is to track the lowest available new offer across sellers, you can instead filter the returned offers array for in-stock products with condition set to New and track that price as a separate series.
Send Walmart price-drop alerts to Discord
Terminal messages are useful while developing, but you'll probably want notifications without opening the script.
The tracker supports Discord webhooks. When an alert is triggered, it can send a message directly to a Discord channel.
Create a webhook in your Discord server's channel settings and copy its URL.
Set it as an environment variable:
export DISCORD_WEBHOOK_URL="YOUR_DISCORD_WEBHOOK_URL"On Windows PowerShell:
$env:DISCORD_WEBHOOK_URL="YOUR_DISCORD_WEBHOOK_URL"You don't need to change the Python code. The notify() function automatically uses the webhook when the variable is available.
Without a webhook, alerts still appear in the terminal.
An alert contains the product name, previous price, current price, reason for the notification, seller, and Walmart product URL.
Keep the webhook URL private, since anyone with access to it may be able to post messages to the channel.
Schedule automatic price checks
Running the script manually is useful during setup. A price tracker becomes more useful when it checks products on a schedule.
On Linux or macOS, you can use cron.
Open your crontab:
crontab -eAdd a daily schedule:
0 9 * * * cd /absolute/path/to/project && /absolute/path/to/python walmart_price_tracker.py >> tracker.log 2>&1This runs the tracker at 9 AM according to the machine's configured timezone.
Replace the project path and Python executable path with the actual locations on your system. If you're using a Python virtual environment, point cron to the Python executable inside that environment.
Also make sure the scheduled process has access to SPIDRA_API_KEY and, if you're using Discord, DISCORD_WEBHOOK_URL. Environment variables set only in an interactive terminal may not be available to cron.
Every successful check adds a new timestamped observation to the SQLite database. Over time, you'll accumulate a price history for the products you're tracking.
For larger catalogs, you can extend the collector to use Spidra Batch scrape, which accepts up to 50 URLs per request and returns separate results for each page. Our guide on scraping multiple URLs in Python and handling failures covers batch processing and partial failures in more detail.
Analyze your Walmart price history
Because prices are stored in SQLite, you can query them later to build charts, calculate averages, or identify the lowest observed price.
For example, the following SQL query returns the price history for a particular Walmart item:
SELECT
observed_at,
product_name,
seller_name,
postal_code,
price_cents / 100.0 AS price_usd
FROM prices
WHERE item_id = '386006068'
ORDER BY observed_at DESC;This gives you the observations needed to understand how prices have changed over time.
You can also group results by seller or location, or use the history to create reports for products you're monitoring.
For recurring price analysis, make sure you're comparing observations with the same seller and product context. A different seller's featured offer is not necessarily a price change by the original seller.
Track Walmart prices without managing a scheduler
If you don't want to run your own Python scheduler and notification service, Spidra also provides Monitors.
Monitors can rerun saved jobs on a schedule and send notifications when tracked data changes. They support conditions such as a price falling below a chosen value and can notify you through email, Discord, Slack, or a webhook.
For structured price monitoring, use a saved job or template that returns the relevant price field and configure the matching alert rule. Monitoring a raw page URL instead detects changes in its page text.
The Python approach gives you direct control over your database, custom comparison rules, and downstream processing. Monitors are an alternative when your main requirement is to be notified about changes.
Start tracking Walmart product prices
You now have a Python price tracker that retrieves Walmart product data, preserves historical prices, checks for changes, and sends notifications when a price drops.
You can add more products to the CSV file, adjust your price thresholds, or build reports from the SQLite history. The same approach can support product research and pricing analysis wherever you have permission to collect the required data.
Before automating collection, review Walmart's Terms of Use, which restrict automated scraping without express prior written consent, and ensure your use is authorized. Our web scraping legality guide discusses the broader considerations.
Create a free Spidra account and try the tracker with your own permitted product URLs.