Skip to main content

🛒 Kroger Public API 🛍️ -- with Examples in Python 🐍

A comprehensive Python client library for the Kroger Public API, featuring robust token management, comprehensive examples, and easy-to-use interfaces for all available endpoints.

📚 Docs: https://cupofowls.github.io/kroger-api/ — tutorials, how-to guides, concepts, and the full reference.

📺 Demo

Adding an item to your cart via an interactive Python script, and checking that it appears in your account:

https://github.com/user-attachments/assets/0079cbc7-5af0-473b-909a-d43508fe43d5

You can also check out kroger-mcp, which is an implementation of the Model Context Protocol leveraging this kroger-api package!

🚀 Quick Start

Installation

pip install kroger-api

From Source

git clone https://github.com/CupOfOwls/kroger-api.git
cd kroger-api
python3 -m venv venv
source venv/bin/activate  # On Windows: venv\Scripts\activate
pip install -r requirements.txt
pip install -e .

Basic Usage

from kroger_api import KrogerAPI
from kroger_api.utils.env import load_and_validate_env, get_zip_code

# Env -- set in .env
load_and_validate_env(["KROGER_CLIENT_ID", "KROGER_CLIENT_SECRET"])
zip_code = get_zip_code(default="10001")

# Initialize the client
kroger = KrogerAPI()

# Get a client credentials token for public data
token_info = kroger.authorization.get_token_with_client_credentials("product.compact")

locations = kroger.location.search_locations(
                zip_code=zip_code,
                radius_in_miles=10,
                limit=1
            )

# Search for products
products = kroger.product.search_products(
        term="milk",
        location_id=locations["data"][0]["locationId"],
        limit=5
    )

print(f"Found {len(products['data'])} products!")

🔐 Getting Started with Credentials

1. Create a Kroger Developer Account

Visit the Kroger Developer Portal to:

  1. Create a developer account
  2. Register your application
  3. Get your CLIENT_ID, CLIENT_SECRET, and set your REDIRECT_URI

2. Set Up Environment Variables

Copy .env.example to .env and fill in your credentials:

# Kroger API Credentials
KROGER_CLIENT_ID=your_client_id_here
KROGER_CLIENT_SECRET=your_client_secret_here
KROGER_REDIRECT_URI=http://localhost:8000/callback

# Optional (Recommended): Your zip code for location-based searches
KROGER_USER_ZIP_CODE=90210

Important: Set your KROGER_REDIRECT_URI during app registration. While marked as optional in the form, the OAuth flow requires it.

3. First Run Authorization

The first time you run a script requiring user authentication, you'll be prompted to authorize your app through your web browser. You're granting permission to your own registered app, not to any third party.

🔄 Token Management

This library implements robust, automatic token management:

✨ Features

  • Automatic token refresh - No manual token handling required
  • Persistent storage - Tokens saved securely to avoid repeated logins
  • Expiry tracking - Checks a token's expiry time before use, with no API call
  • Reactive recovery - Automatically refreshes expired tokens during API calls
  • PKCE Support - Enhanced OAuth security with Proof Key for Code Exchange
  • Shared sign-ins - Processes and threads that share a token file renew it one at a time, so they never sign each other out

🔧 How it Works

Proactive Approach:

  1. Loads saved tokens and checks their expiry time (no API request)
  2. Automatically refreshes if token is expired and refresh token is available, while it holds a lock on the token file (<token file>.lock). A process that waited for the lock uses the token that another process renewed meanwhile, so a refresh token is never sent twice. A new sign-in and clear_token wait for the same lock, and a token whose file clear_token deleted is not renewed.

Reactive Approach:

  1. Makes API requests with current token
  2. On 401 Unauthorized errors, refreshes the user token, or requests a new client-credentials token
  3. Retries the original request once with the new token

Token files (automatically managed):

  • .kroger_token_client_product.compact.json - Client credentials tokens
  • .kroger_token_user.json - User authorization tokens These tokens are stored in the first matching location:
  1. $KROGER_TOKEN_DIR — set this environment variable to choose the directory yourself
  2. $XDG_DATA_HOME/kroger-mcp/ (defaults to ~/.local/share/kroger-mcp/) on Unix-like machines (macOS, Linux)
  3. %APPDATA%\kroger-mcp\ on Windows

The directory is shared with the kroger-mcp package so both reuse the same tokens, and it is always writable even when the process is launched with a read-only working directory (e.g. MCP servers under Claude Desktop on Windows).

🔒 Enhanced Security with PKCE

This library supports PKCE (Proof Key for Code Exchange) for enhanced security in the OAuth flow. authenticate_user uses it automatically; if you build the flow yourself, pass the parameters as shown:

from kroger_api import KrogerAPI
from kroger_api.utils import generate_pkce_parameters

# Generate PKCE parameters
pkce_params = generate_pkce_parameters()

# Initialize the client
kroger = KrogerAPI()

# Get authorization URL with PKCE
auth_url = kroger.authorization.get_authorization_url(
    scope="cart.basic:write profile.compact",
    state="random_state_value",
    code_challenge=pkce_params['code_challenge'],
    code_challenge_method=pkce_params['code_challenge_method']
)

# After user authorization and redirect, exchange code for token with verifier
token_info = kroger.authorization.get_token_with_authorization_code(
    code="authorization_code_from_redirect",
    code_verifier=pkce_params['code_verifier']
)

PKCE helps protect against authorization code interception attacks, particularly important for public clients or those using external tools to manage OAuth flows.

⚠️ Error Handling

Every exception the library raises derives from KrogerAPIError. Invalid arguments are rejected before any request is sent, and every non-2xx response raises an exception that carries Kroger's own error code and message:

from kroger_api import KrogerAPI, KrogerAPIError, InvalidParameterError, NotFoundError

try:
    kroger.location.get_location("99999999")
except NotFoundError as e:
    print(e)
    # Kroger API error 404 Not Found: (no error message in the response body)
    #   request: GET /v1/locations/99999999
    #   correlation id: akam_1792606007_ba10cee2-f276-444a-aeac-082b98ac9ca3
    #   hint: No store has this locationId. Find valid IDs with a location search.
except KrogerAPIError as e:
    print(e.to_dict())  # the same details as JSON-safe data
Exception When
InvalidParameterError An argument breaks a documented API constraint, such as fulfillment="delivery" (valid: ais, csp, dth, sth). No request is sent.
ConfigurationError Credentials or the redirect URI are missing
NotAuthenticatedError A call was made before any token was obtained
BadRequestError (400) The API rejected a parameter; kroger_message names it
AuthenticationError (401) The token, or at the token endpoint the client credentials, were rejected after one automatic refresh-and-retry
PermissionDeniedError (403) The token type or scope cannot use this endpoint, such as a client-credentials token on the cart
NotFoundError (404) The location, chain, or department does not exist
RateLimitError (429) The endpoint's daily rate limit is used up
InternalServerError (5xx) Kroger's server failed
APIConnectionError, APITimeoutError No response arrived (requests time out after 30 seconds by default; set KrogerAPI(timeout=...))

HTTP and network errors also subclass the matching requests exceptions, so existing except requests.exceptions.HTTPError code still catches every error response from the API. An argument that fails a parameter check raises InvalidParameterError (a ValueError) without sending a request, so catch KrogerAPIError to handle both. A failed cart add whose outcome_unknown is True may have gone through: check the cart before sending it again. See the error handling reference for every attribute.

📚 Example Scripts

The examples/ directory contains comprehensive demonstrations:

Script Description Authentication Required
location_api_examples.py Search stores, get details about locations, chains, and departments Client credentials
product_api_examples.py Search products, get details, filter by various criteria Client credentials
cart_api_examples.py Add items to user's cart, full shopping workflow User authorization
identity_api_examples.py Get user profile information User authorization
oauth_flow.py Complete OAuth2 authorization code flow example User authorization
token_refresh_example.py Demonstrates automatic token refresh functionality Both
authorization_api_examples.py All authorization endpoints and flows Both
clear_tokens.py Utility to delete all saved token files None

🏃‍♂️ Running Examples

# Make sure your .env file is configured first!

# Public API examples (no user login required)
python examples/location_api_examples.py
python examples/product_api_examples.py

# User-specific examples (requires browser login)
python examples/cart_api_examples.py
python examples/identity_api_examples.py
python examples/oauth_flow.py

# Utility scripts
python examples/clear_tokens.py  # Clear saved tokens

Here's a quick demo of browsing via the Product API with examples/product_api_examples.py:

Kroger API Python Demo

🏪 Kroger Public API Information

API Versions & Rate Limits

API Version Rate Limit Notes
Authorization 1.0.13 No specific limit Token management
Products 1.2.4 10,000 calls/day Search and product details
Locations 1.2.2 1,600 calls/day per endpoint Store locations and details
Cart 1.2.3 5,000 calls/day Add/manage cart items
Identity 1.2.3 5,000 calls/day User profile information

Note: Rate limits are enforced per endpoint, not per operation. You can distribute calls across operations using the same endpoint as needed.

🔑 Available Scopes

When requesting user authorization, you can specify these scopes:

  • product.compact - Read product information
  • cart.basic:write - Add items to cart
  • profile.compact - Read user profile information

Request only the scopes of the API products your app is registered for (cart.basic:write needs the Cart API, profile.compact the Identity API). Kroger refuses the whole sign-in with invalid_scope when one is missing.

📖 API Documentation

For complete API documentation, visit:

🤝 Contributing

Contributions are welcome! Please feel free to submit a Pull Request. For major changes, please open an issue first to discuss what you would like to change.

📄 License

This project is licensed under the MIT License - see the LICENSE file for details.

⚠️ Disclaimer

This is an unofficial Python client for the Kroger Public API. It is not affiliated with, endorsed by, or sponsored by Kroger.

Metadata

Release files for kroger-api 0.4.0

For a detailed explanation of source distributions (sdists) and built distributions (wheels), please see the package formats documentation.

Source distribution (sdist)

Source distribution for kroger-api 0.4.0
File Size Uploaded Provenance
kroger_api-0.4.0.tar.gz 74.5 kB Without provenance Details

Built distribution (wheel)

Table of built distributions (wheels) for kroger-api 0.4.0
File Interpreter ABI Platform
kroger_api-0.4.0-py3-none-any.whl Python 3 none any Details

Total release size: 142.0 kB

Release files / kroger_api-0.4.0.tar.gz

Download URL kroger_api-0.4.0.tar.gz
Size 74.5 kB
Tags Source
SHA-256 checksum
How to use checksums
a2db5a48c7d3179b2b705a75fed284287113f217107c4fb0e2044820282740ac
BLAKE2b-256 checksum
How to use checksums
a79be765120525e5cd77a0315a3c5d796861809570764a42879bd064ce43ac33
Upload date
Uploaded using Trusted Publishing?
What is trusted publishing?
No
Uploaded via uv/0.8.22

Release files / kroger_api-0.4.0-py3-none-any.whl

Download URL kroger_api-0.4.0-py3-none-any.whl
Size 67.5 kB
Tags Python 3
SHA-256 checksum
How to use checksums
dc941d61b5b7c13c34ac6be6c6eb5b12a5fbc88a257aebf4e20216a662a9a887
BLAKE2b-256 checksum
How to use checksums
d36e7ea5899715ee2708a0d10e2620c36110f2d2480f35d6bd498e5532f85faf
Upload date
Uploaded using Trusted Publishing?
What is trusted publishing?
No
Uploaded via uv/0.8.22

Security for kroger-api 0.4.0

Provenance

Provenance describes where a file came from. On PyPI, provenance is shared via attestations, which provide a verifiable record of the build or publishing details. View details, limitations and caveats.

No provenance found

None of the files in this release were uploaded with provenance metadata.

A note on package security

PyPI is a repository for distributing packages, not a service for auditing them. While third-party security researchers and our staff do their best to detect and remove malicious packages, PyPI cannot guarantee the quality, security or suitability of any given package.

Anthropic, PBC Visionary sponsor Bloomberg Visionary sponsor Hudson River Trading Visionary sponsor Meta Visionary sponsor NVIDIA Visionary sponsor Microsoft Sustainability sponsor Depot Continuous Integration AWS Cloud computing and Security Sponsor Datadog Monitoring Fastly CDN Google Download Analytics Sentry Error logging StatusPage Status page