If you've been paying attention the last few years, you know prices for nearly everything have increased significantly. This is well-reflected in macroeconomic data like the U.S. Bureau of Labor Statistics' overall inflation rate.

However the reality is everyone has a unique inflation rate depending on their own shopping habits. The above aggregate data is based on a basket of goods estimated by economists. It doesn't necessarily reflect what individuals actually buy and the economists periodically change the composition of the basket which further confuses things.

Additionally, aggregated inflation data doesn't tell you anything about inflation within particular categories of goods. Inflation might be 3% overall, but it doesn't help you understand if one category is 7% and another is -2%.

To best understand real world inflation, it can be worth it to track and calculate yourself. With SerpApi's Amazon Search API, you can easily start tracking price changes for any custom basket of goods sold by Amazon.

In this tutorial, we'll walk through the steps of creating a basic Python script that will scrape Amazon price data and and calculate the inflation rate of any custom basket of goods.

For more specifics on scraping Amazon product data with or without our API, check out this blog post:

How to Scrape Amazon Product Data (2025 Tutorial)
Learn how to scrape Amazon search results to get product data, including product name, rating, price and more using a simple API.

Be sure to sign up for a free SerpApi account to get 250 free searches and your API key. You'll need this to follow along. Register here: https://serpapi.com/users/sign_up

Once register, your API key will be here: https://serpapi.com/manage-api-key

Organizing Your Products List

We'll begin by creating a source list of products to query in Amazon. This can include any product listing on Amazon, but I'll be focusing on grocery products in this tutorial. The process would be the same for anything else you want to track on Amazon.

As a starting point, I've created a list of 10 grocery items that I buy regularly. You can copy my Google Sheet or raw text CSV below to help you get started. Even if you delete all 10 items I've listed, you'll still want to use this format as the Python script we'll create later will expect the same structure.

Amazon Products Starter Sheet
title,asin,zip,monthly_purchases,date_checked,base_price,monthly_cost
"Blueberries, 1 Pint",B003AYKYIG,94404,4,2025-09-24,$4.49,$17.96
"Cage Free Large Brown Eggs, Grade AA, 1 Dozen",B0BXRKRF93,94404,5,2025-09-24,$2.99,$14.95
"Amazon Grocery, Whole Milk, 1 Gallon, 128 Fl Oz",B075K1MQZ8,94404,5,2025-09-24,$3.26,$16.30
"Amazon Grocery, Ground Beef, 80% Lean/20% Fat, 1 lb",B08LJVQSL2,94404,10,2025-09-24,$6.93,$69.30
"Beef Ribeye Steak, Grass-Fed, Pasture-Raised | 0.625 lbs.",B01H0AI64Y,94404,1,2025-09-24,$13.12,$13.12
"Quaker, Quick 1 Minute Whole Grain Oats, 42 Oz",B000PWK3KK,94404,3,2025-09-24,$4.99,$14.97
"Zucchini Squash, 1 Each""",B000P6G1AC,94404,10,2025-09-24,$1.02,$10.20
"Laura Scudder's All Natural Nutty Peanut Butter, 16 oz. Jar",B00CJ8K18W,94404,2,2025-09-24,$4.88,$9.76
"FAGE Total Greek Yogurt, 5% Whole Milk, Plain, 32 oz",B00WTR0CDM,94404,5,2025-09-24,$6.99,$34.95
"Taylor Farms Spinach, 9 oz Bag",B00KMM8I6Y,94404,5,2025-09-24,$2.06,$10.30

The sheet has the following columns:

  1. title: This is the Amazon product title. You can technically put whatever you want here. It's only for your benefit.
  2. asin: This stands for Amazon Standard Identification Number. It's a unique code for every product on Amazon. You can get this from the URL of any product listing. For example B003AYKYIG in: https://www.amazon.com/Fresh-Produce-Brands-Vary-100174/dp/B003AYKYIG
  3. zip: This is your delivery zip/post code. Grocery products, in particular, can have different prices and availability in different parts of the country. Keep this consistent.
  4. monthly_purchases: This is how many times you purchase this item each month. Put your best estimate.
  5. date_checked: This is the original date you input the product in the list. This will be crucial for the script to calculate an annualized inflation rate. For example October 1, 2025 would be: 2025-10-01.
  6. base_price: This is the base starting price of the product when you first looked it up on Amazon.

Use the screenshot below as a reference for where to find each data point sourced from Amazon. Ensure you use the same zip when manually searching and in the spreadsheet. Amazon prices, particularly groceries, can vary by region.

Scraping Amazon Prices

Before we get into connecting to SerpApi's Amazon API, you'll need to ensure you have our Python library installed. Run the following to do that:

pip install google-search-results

More instructions here: https://serpapi.com/integrations

Next, I'll share this starter code as our jumping off point. Copy and paste this in your local environment.

import csv
import sys
from serpapi import GoogleSearch
from decimal import Decimal
from datetime import date, datetime, timedelta

def read_csv(file):
    with open(file, newline='', encoding='utf-8') as f:
        reader = csv.DictReader(f)
        return list(reader)

if __name__ == "__main__":
    products = read_csv("products.csv")

We'll add a search function and pretty much copy the sample code we have in our Amazon API docs. We'll only make small changes like including a delivery_zip. This and the k query parameter will be settable with inputs to our search function.

def search(query,zip):
    params = {
        "api_key": "your_key_here",
        "engine": "amazon",
        "k": query,
        "delivery_zip": zip
    }

    search = GoogleSearch(params)
    results = search.get_dict()
    return results

Let's quickly test our search function with the first product in our products.csv file.

if __name__ == "__main__":
    products = read_csv("products.csv")
    print(search(products[0]["asin"],products[0]["zip"]))

If you run the script now, you should see a large JSON dump in your terminal. This is a good sign the search worked, but we'll obviously need to extract just the product we want.

The Amazon Search API returns an array of organic results with the following structure. The example below has only 1 result, but many queries will return multiple results. We'll need to identify the matching asin and then select the extracted_price field for that result.

"organic_results":
[

    {
        "position": 1,
        "asin": "B01H0AI64Y",
        "tags":
        [
            "Ribeye Steak"
        ]
        ,
        "title": "Pre, Beef Ribeye Steak, Grass-Fed, Pasture-Raised | 0.625 lbs.",
        "link": "https://www.amazon.com/Pre-Ribeye-Steak-Grass-Finished-Pasture-Raised/dp/B01H0AI64Y/ref=sr_1_1?dib=eyJ2IjoiMSJ9.KGRC7U9W7UNHi6Lb8ubxbQ.vpBa-Hj3Wv8a3AQi2P5kTvmYit303_veEpuAHeYjttw&dib_tag=se&keywords=B01H0AI64Y&qid=1761648220&sr=8-1",
        "link_clean": "https://www.amazon.com/Pre-Ribeye-Steak-Grass-Finished-Pasture-Raised/dp/B01H0AI64Y/",
        "thumbnail": "https://m.media-amazon.com/images/I/81U1xlobC2L._AC_UL320_.jpg",
        "rating": 4.4,
        "reviews": 4000,
        "bought_last_month": "10K+ bought in past month",
        "price": "$13.12",
        "extracted_price": 13.12,
        "price_unit": "$20.99/lb",
        "extracted_price_unit": 20.99,
        "offers":
        [
            "SNAP EBT eligible"
        ]
        ,
        "snap_ebt_eligible": true,
        "delivery":
        [
            "$12.99 delivery Today 10 AM - 3 PM"
        ]
    }

]

Let's add a new function to handle this logic and return the price.

def fetch_product_price(product):
    results = search(product["asin"],product["zip"])
    organic_results = results.get("organic_results", [])
    target = next((result for result in organic_results if result.get("asin") == product["asin"]), None)
    if not target:
        sys.exit(f"Could not fetch price for '{product["title"]}' (ASIN: {product["asin"]}). Exiting.")
    return Decimal(str(target.get("extracted_price")))

If for some reason the product doesn't appear in search results, we'll simply exit the script to keep this tutorial simple. Feel free to adjust this if you want any more custom logic.

We can now test this function and print its output.

if __name__ == "__main__":
    products = read_csv("products.csv")
    print(fetch_product_price(products[0]))

If all goes well, we should see the price of our first product printed to console. E.g. 4.49 for blueberries.

Next we need a way to calculate the total cost of our base shopping basket. We'll add a calculate_base_basket function to do this. It will loop through our products.csv file while summing up the the total monthly spend for each product.

def calculate_base_basket(products):
    base_basket_sum = Decimal("0")
    
    for product in products:
        base_basket_sum += int(product["monthly_purchases"]) * Decimal(str(product["base_price"]))
    
    return base_basket_sum

Once again, we'll test this.

if __name__ == "__main__":
    products = read_csv("products.csv")
    print(calculate_base_basket(products))

You should see the total cost of your monthly basket printed to console. It's worth double checking the output the first time to ensure nothing was misconfigured.

If all the math checks out, we can move to fetching the latest prices. We'll add a calculate_latest_basket function to do this.

This function will run a new price check for each product in our CSV, print the new price, and add it to our latest monthly basket cost.

def calculate_latest_basket(products):
    latest_basket_sum = Decimal("0")

    for product in products:
        latest_price = fetch_product_price(product)
        print(f"{product["title"]} base: ${product["base_price"]} | latest price: ${latest_price}")
        latest_basket_sum += int(product["monthly_purchases"]) * latest_price
    
    return latest_basket_sum

If you're running this soon after populating your products list, it's unlikely any prices have changed. As a start, we can test everything works by ensuring base_basket_sum and new_basket_sum are equal.

if __name__ == "__main__":
    products = read_csv("products.csv")
    print(calculate_base_basket(products))
    print(calculate_latest_basket(products))

Here's what I get. Looks like a match.

211.81
211.81

Calculating Inflation

We can next work on the logic to calculate your custom basket's inflation rate. However to test this properly, it would be better to have a price difference to play with.

Let's manipulate the data for testing purposes by adding $0.25 to each product's monthly cost. This will add $2.50 to the total basket cost since there are 10 products listed.

def calculate_latest_basket(products):
    latest_basket_sum = Decimal("0")

    for product in products:
        latest_price = fetch_product_price(product)
        print(f"{product["title"]} base: ${product["base_price"]} | latest price: ${latest_price}")
        latest_basket_sum += int(product["monthly_purchases"]) * fetch_product_price(product) + Decimal("0.25") # artificially inflates prices
    
    return latest_basket_sum

Now I get:

211.81
214.31

We'll then use the following simple formula to calculate the price change percentage.

In code:

inflation = ((latest_basket_sum - base_basket_sum) / base_basket_sum) * 100

We'll drop this formula into a check_inflation function.

def check_inflation(products):
    base_basket_sum = calculate_base_basket(products)
    latest_basket_sum = calculate_latest_basket(products)

    inflation = ((latest_basket_sum - base_basket_sum) / base_basket_sum) * 100

    print(f"Your basket has increased by {inflation:.2f}%")
    print(f"Base basket: ${base_basket_sum:.2f}")
    print(f"Latest basket: ${latest_basket_sum:.2f}")

Then we'll call it from main.

if __name__ == "__main__":
    products = read_csv("products.csv")
    check_inflation(products)

Expected output:

Your basket has increased by 1.18%
Base basket: $211.81
Latest basket: $214.31

This is helpful of course but a 1.18% change isn't useful without a standard time reference. A 1.18% change over a year would be negligible, but a 1.18% change over a week would be significant.

To get a more helpful number, we'll annualize the change and calculate this in a new function that will take a start date, end date, and the inflation rate we just calculated above.

def calculate_annual_rate(start_date, end_date, inflation):
    inflation = inflation / 100
    days = (end_date - start_date).days
    periods_per_year = Decimal("365") / days
    annual_rate = ((1 + inflation) ** periods_per_year - 1) * 100
    return annual_rate

We'll call the above function from check_inflation. I've made 3 additional changes to our previous version.

  1. Set a start_date using the date_checked value of our first product
  2. Set end_date equal to today
  3. Update the prints to include dates and annual inflation
def check_inflation(products):
    base_basket_sum = calculate_base_basket(products)
    latest_basket_sum = calculate_latest_basket(products)

    inflation = ((latest_basket_sum - base_basket_sum) / base_basket_sum) * 100

    start_date = datetime.strptime(products[0]["date_checked"], "%Y-%m-%d").date()
    end_date = date.today()

    annual_inflation = calculate_annual_rate(start_date,end_date,inflation)

    print(f"{start_date} Base basket: ${base_basket_sum:.2f}")
    print(f"{end_date} Latest basket: ${latest_basket_sum:.2f}")
    print("===============================================================")
    print(f"Between {start_date} and {end_date}")
    print(f"Your basket has changed by {inflation:.2f}%")
    print(f"In annual terms, it's changed by {annual_inflation:.2f}%")

Before testing this, let's do one last manipulation to run this as if a month has passed since we checked prices. Let's force start_date to be 30 days ago.

def check_inflation(products):
...

    start_date = date.today() - timedelta(days=30) # manipulated to be 30 days ago
    end_date = date.today()

    annual_inflation = calculate_annual_rate(start_date,end_date,inflation)
    
...

Finally, we can run the whole thing.

2025-09-24 Base basket: $211.81
2025-10-24 Latest basket: $214.31
===============================================================
Between 2025-09-24 and 2025-10-24
Your basket has changed by 1.18%
In annual terms, it's changed by 15.35%

That looks just right. We can wrap up here. The last thing I'll do is share the full working code below. The code below does not include the price and date manipulations for testing purposes. Add those yourself if you'd like.

Happy scraping!

Full Code

import csv
import sys
from serpapi import GoogleSearch
from decimal import Decimal
from datetime import date, datetime, timedelta

def read_csv(file):
    with open(file, newline='', encoding='utf-8') as f:
        reader = csv.DictReader(f)
        return list(reader)

def search(query,zip):
    params = {
        "api_key": "your_key_here",
        "engine": "amazon",
        "k": query,
        "delivery_zip": zip
    }

    search = GoogleSearch(params)
    results = search.get_dict()
    return results

def fetch_product_price(product):
    results = search(product["asin"],product["zip"])
    organic_results = results.get("organic_results", [])
    target = next((result for result in organic_results if result.get("asin") == product["asin"]), None)

    if not target:
        sys.exit(f"Could not fetch price for '{product["title"]}' (ASIN: {product["asin"]}). Exiting.")

    return Decimal(str(target.get("extracted_price")))

def calculate_base_basket(products):
    monthly_basket_cost = Decimal("0")

    for product in products:
        monthly_basket_cost += int(product["monthly_purchases"]) * Decimal(str(product["base_price"]))
    
    return monthly_basket_cost

def calculate_latest_basket(products):
    latest_basket_sum = Decimal("0")

    for product in products:
        latest_price = fetch_product_price(product)
        print(f"{product["title"]} base: ${product["base_price"]} | latest price: ${latest_price}")
        latest_basket_sum += int(product["monthly_purchases"]) * latest_price
    
    return latest_basket_sum

def calculate_annual_rate(start_date, end_date, inflation):
    inflation = inflation / 100
    days = (end_date - start_date).days
    periods_per_year = Decimal("365") / days
    annual_rate = ((1 + inflation) ** periods_per_year - 1) * 100

    return annual_rate

def check_inflation(products):
    base_basket_sum = calculate_base_basket(products)
    latest_basket_sum = calculate_latest_basket(products)
    inflation = ((latest_basket_sum - base_basket_sum) / base_basket_sum) * 100

    start_date = datetime.strptime(products[0]["date_checked"], "%Y-%m-%d").date()
    end_date = date.today()
    annual_inflation = calculate_annual_rate(start_date,end_date,inflation)

    print(f"{start_date} Base basket: ${base_basket_sum:.2f}")
    print(f"{end_date} Latest basket: ${latest_basket_sum:.2f}")
    print("===============================================================")
    print(f"Between {start_date} and {end_date}")
    print(f"Your basket has changed by {inflation:.2f}%")
    print(f"In annual terms, it's changed by {annual_inflation:.2f}%")

if __name__ == "__main__":
    products = read_csv("products.csv")
    check_inflation(products)