🛒 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
From PyPI (Recommended)
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:
- Create a developer account
- Register your application
- Get your
CLIENT_ID,CLIENT_SECRET, and set yourREDIRECT_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:
- Loads saved tokens and checks their expiry time (no API request)
- 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 andclear_tokenwait for the same lock, and a token whose fileclear_tokendeleted is not renewed.
Reactive Approach:
- Makes API requests with current token
- On 401 Unauthorized errors, refreshes the user token, or requests a new client-credentials token
- 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:
$KROGER_TOKEN_DIR— set this environment variable to choose the directory yourself$XDG_DATA_HOME/kroger-mcp/(defaults to~/.local/share/kroger-mcp/) on Unix-like machines (macOS, Linux)%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 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 informationcart.basic:write- Add items to cartprofile.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)
| File | Size | Uploaded | Provenance | |
|---|---|---|---|---|
| kroger_api-0.4.0.tar.gz | 74.5 kB | Without provenance | Details |
Built distribution (wheel)
| File | Interpreter | ABI | Platform | Reset |
|---|---|---|---|---|
| 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.