This post addresses the challenge of programmatically checking GameStop inventory for a specific product across multiple zip codes from a CSV file. The solution leverages Python’s requests library to interact with GameStop’s store availability API and the csv module for efficient data processing.
The Problem
Manually checking product availability across numerous zip codes on an e-commerce website like GameStop is inefficient and time-consuming. The user requires an automated method to query GameStop’s inventory system using a list of zip codes from a .csv file, specifically for an “obscure game,” and report which locations have the item in stock. This involves simulating web requests, parsing structured data, and managing input from a local file.
The Solution
The following Python script reads zip codes from a CSV file, iterates through them, and queries GameStop’s API to determine stock availability for a specified product.
import csv
import requests
import time
import os
# --- Configuration ---
# IMPORTANT: Replace 'YOUR_PRODUCT_ID_HERE' with the actual GameStop Product ID (PID)
# You can often find this in the URL of the game's product page, e.g.,
# https://www.gamestop.com/video-games/products/the-legend-of-zelda-tears-of-the-kingdom/11200021.html
# The PID would be '11200021'.
PRODUCT_ID = 'YOUR_PRODUCT_ID_HERE'
CSV_FILE_PATH = 'zip_codes.csv'
# Delay between requests to avoid overwhelming the server or triggering rate limits
REQUEST_DELAY_SECONDS = 2
# --- End Configuration ---
def check_gamestop_stock(product_id, zip_code):
"""
Checks GameStop stock for a given product ID and zip code.
Returns True if in stock (or available for pickup/shipping), False otherwise,
or None if an error occurs.
"""
if product_id == 'YOUR_PRODUCT_ID_HERE':
print("Error: Please update PRODUCT_ID in the script with the actual GameStop Product ID.")
return None
# GameStop API endpoint for store availability by postal code
# This URL may change; regular verification is recommended.
api_url = f"https://www.gamestop.com/on/demandware.store/Sites-gamestop-us-Site/default/Stores-GetStores?postalCode={zip_code}&showMap=false&radius=50&pid={product_id}"
headers = {
'User-Agent': 'Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/91.0.4472.124 Safari/537.36',
'Accept': 'application/json',
'Accept-Language': 'en-US,en;q=0.9',
'Connection': 'keep-alive',
}
try:
response = requests.get(api_url, headers=headers, timeout=10)
response.raise_for_status() # Raise an HTTPError for bad responses (4xx or 5xx)
data = response.json()
# Check if the API returned any stores
if data and 'stores' in data:
for store in data['stores']:
# The 'productStoreAvailability' list contains stock info for the requested product
product_availability = store.get('productStoreAvailability', [])
for prod_info in product_availability:
if prod_info.get('productID') == product_id:
# 'available' usually indicates general availability for pickup/shipping
if prod_info.get('available'):
return True
# No store found with availability for the specific product ID
return False
return False # No stores found for the postal code or data structure unexpected
except requests.exceptions.HTTPError as e:
print(f"HTTP error for {zip_code}: {e.response.status_code} - {e.response.text}")
return None
except requests.exceptions.ConnectionError as e:
print(f"Connection error for {zip_code}: {e}")
return None
except requests.exceptions.Timeout:
print(f"Timeout error for {zip_code}: Request timed out.")
return None
except requests.exceptions.RequestException as e:
print(f"An unexpected request error occurred for {zip_code}: {e}")
return None
except ValueError:
print(f"Failed to decode JSON from response for {zip_code}. Response: {response.text}")
return None
except Exception as e:
print(f"An unknown error occurred for {zip_code}: {e}")
return None
def main():
if not os.path.exists(CSV_FILE_PATH):
print(f"Error: CSV file '{CSV_FILE_PATH}' not found. Please ensure it exists.")
return
zip_codes_to_check = []
try:
with open(CSV_FILE_PATH, mode='r', newline='', encoding='utf-8') as csvfile:
reader = csv.reader(csvfile)
for i, row in enumerate(reader):
if not row: # Skip empty rows
continue
# Assuming zip codes are in the first column; adjust index if needed.
zip_code = row[0].strip()
if zip_code: # Ensure zip code is not empty after stripping
zip_codes_to_check.append(zip_code)
except FileNotFoundError:
print(f"Error: The file '{CSV_FILE_PATH}' was not found.")
return
except Exception as e:
print(f"Error reading CSV file: {e}")
return
if not zip_codes_to_check:
print("No zip codes found in the CSV file to check.")
return
print(f"Checking availability for Product ID: {PRODUCT_ID}")
print(f"Processing {len(zip_codes_to_check)} zip codes...")
available_zips = []
unavailable_zips = []
error_zips = []
for i, zip_code in enumerate(zip_codes_to_check):
print(f"[{i+1}/{len(zip_codes_to_check)}] Checking stock for {zip_code}...")
is_available = check_gamestop_stock(PRODUCT_ID, zip_code)
if is_available is True:
available_zips.append(zip_code)
elif is_available is False:
unavailable_zips.append(zip_code)
else: # None implies an error occurred
error_zips.append(zip_code)
time.sleep(REQUEST_DELAY_SECONDS) # Adhere to delay
print("\n--- Stock Check Results ---")
if available_zips:
print("\nAvailable in the following zip codes:")
for z in available_zips:
print(f"- {z}")
else:
print("\nProduct not found as available in any checked zip codes.")
if unavailable_zips:
print("\nNot available in the following zip codes:")
for z in unavailable_zips:
print(f"- {z}")
if error_zips:
print("\nErrors occurred for the following zip codes (check console output for details):")
for z in error_zips:
print(f"- {z}")
print("\nProcessing complete.")
if __name__ == "__main__":
main()
Why It Works
- HTTP Requests with
requests: Therequestslibrary is used to send GET requests to GameStop’s internal API endpoint for store availability. It abstracts away complexities of network communication, making it simple to fetch web content. - JSON Response Parsing: GameStop’s API responds with data in JSON (JavaScript Object Notation) format. The
response.json()method automatically parses this data into a Python dictionary, allowing easy access to structured information like store details and product availability. - CSV File Handling with
csv: Thecsvmodule is Python’s standard library for reading and writing CSV files. It handles various CSV formats and ensures proper parsing of each row and column, making it straightforward to extract zip codes. - Product Identification: The script requires a specific
PRODUCT_ID. This ID is critical for the API to identify the “obscure game” in question and fetch relevant stock information. - Error Handling: Comprehensive
try-exceptblocks are implemented to catch common issues such as network connectivity problems (requests.exceptions.ConnectionError), HTTP status errors (requests.exceptions.HTTPError), timeouts (requests.exceptions.Timeout), and JSON decoding failures. This makes the script robust against transient network issues or unexpected API responses. - Rate Limiting Mitigation: A
time.sleep()call is included between requests. This deliberate delay prevents the script from overwhelming the server with too many requests in a short period, which could lead to IP blocking or CAPTCHA challenges.