A CLI for REWE grocery pickup ordering — designed for AI agent integration.
Installation · Quick Start · Commands · Agent Skill
Search products, manage baskets, check timeslots, and place pickup orders from the terminal. All output is JSON, making it ideal for AI agents to parse and act on.
Disclaimer: This is an unofficial project and is not affiliated with, endorsed by, or connected to REWE Group or REWE digital in any way. It interacts with REWE's public-facing web APIs, which are undocumented and may change at any time. This tool may break without notice. Use at your own risk.
- Node.js >= 18
- Playwright browsers (installed automatically)
- A REWE account with pickup enabled for your store
- A 2Captcha account and API key (for solving Turnstile CAPTCHAs during login)
- Linux recommended (tested on Ubuntu). macOS should work but is untested.
- X server or xvfb — login opens a headed browser. On headless servers (VPS), install
xvfband prefix the login command withxvfb-run.
git clone https://github.com/Tobi4s1337/karrt.git
cd karrt
npm install
npx playwright install chromium
npm run buildThe login flow uses a Chromium browser extension from 2Captcha to automatically solve Cloudflare Turnstile challenges on the REWE login page.
-
Get a 2Captcha account at 2captcha.com and add funds (a few dollars lasts a long time — each solve costs ~$0.002).
-
Download the 2Captcha browser extension. The upstream repo at
2captcha/solver_browser_extensionwas archived, so use this mirror instead:git clone https://github.com/Tobi4s1337/2captcha-solver-mirror.git 2captcha-solver
Alternatively, install from the Chrome Web Store and unpack the crx.
-
Verify that
2captcha-solver/manifest.jsonexists at the project root after cloning. -
Configure the extension by editing
2captcha-solver/common/config.jsand setting your API key:const defaultConfig = { apiKey: 'YOUR_2CAPTCHA_API_KEY', // ... };
Alternatively, launch the browser manually once, open the extension popup, and enter your API key there — it persists in the Chrome profile stored in
.chrome-data/.
Set these for fully autonomous login (no manual interaction needed):
export REWE_EMAIL="your@email.com"
export REWE_PASSWORD="your-password"For fully autonomous 2FA, store your REWE account's TOTP secret:
node dist/cli.js totp-setup YOUR_BASE32_TOTP_SECRETTo get the TOTP secret:
- Go to your REWE account security settings
- Set up an authenticator app for 2FA
- When shown the QR code, look for the "manual entry" option — that gives you the base32 secret
- Enter it both in your authenticator app AND via
totp-setup
With TOTP configured, karrt login is fully hands-free: it fills credentials, solves the CAPTCHA, and auto-generates the 2FA code.
# 1. Find your local REWE pickup store
node dist/cli.js store search 66113
# 2. Set your store
node dist/cli.js store set 840254 66113
# 3. Log in (opens browser, solves CAPTCHA, handles 2FA)
node dist/cli.js login
# 4. Search for products
node dist/cli.js search "Vollmilch" --sort PRICE_ASC --category milch
# 5. Add to basket
node dist/cli.js basket add "8-Y4PWBC9S-d1125764-996e-3535-8619-eff4f86b672f"
# 6. Check timeslots
node dist/cli.js timeslotskarrt store show # Show current store
karrt store search <zip> # Find pickup stores near ZIP code
karrt store set <wwIdent> <zip> # Set active storekarrt login [--email X] [--password Y] # Browser-based login
karrt verify <code> # Provide 2FA code (if TOTP not configured)
karrt login-status # Check login flow status
karrt import-cookies <file> # Import cookies from Netscape file
karrt totp-setup <secret> # Store TOTP secret for auto-2FAHeadless server? Login opens a real browser. On a VPS without a display, use:
xvfb-run node dist/cli.js loginInstall xvfb first:
apt install xvfb
karrt search <query> [options]| Option | Description |
|---|---|
--sort <order> |
RELEVANCE_DESC, PRICE_ASC, PRICE_DESC, NAME_ASC, NAME_DESC |
--category <slug> |
Filter by category (e.g., milch, nudeln, gefluegelfleisch) |
--page <n> |
Page number (default: 1) |
--per-page <n> |
Results per page (default: 40) |
--offers |
Only discounted items |
--organic |
Organic/Bio products |
--regional |
Regional products |
--vegan |
Vegan products |
--vegetarian |
Vegetarian products |
Category slugs constrain results to the right product type. Without them, a search for "Milch" might return shower gel. Common slugs:
| Category | Slug |
|---|---|
| Milk | milch |
| Eggs | eier-ei-ersatz |
| Cheese (hard) | hartkaese |
| Cheese (fresh) | frischkaese |
| Poultry | gefluegelfleisch |
| Pork | schweinefleisch |
| Beef | rindfleisch |
| Bacon/Ham | roher-schinken-speck |
| Pasta | nudeln |
| Rice | reis |
| Fresh fruit | frisches-obst |
| Fresh vegetables | frisches-gemuese |
| Spices | gewuerze |
| Butter | butter |
| Bread | brot |
Slugs are kebab-case German category names (ä→ae, ö→oe, ü→ue). If a slug returns 404, check categoryPath in any search result to discover the correct one.
karrt basket show # Show current basket
karrt basket add <listingId> [--qty N] # Add item
karrt basket update <listingId> <qty> # Update quantity
karrt basket remove <listingId> # Remove item
karrt basket clear # Clear all items
karrt basket bulk-add '<json>' # Add multiple: '[{"listingId":"x","qty":1}]'karrt timeslots # List available pickup timeslots
karrt timeslot-reserve <slotId> # Reserve a timeslotTime-sensitive commands include a now field with the current local date/time (Europe/Berlin).
karrt orders show # List all orders
karrt orders get <orderId> # Order details
karrt orders cancel <orderId> # Cancel orderkarrt receipts show # List digital receipts
karrt receipts download <receiptId> [--output] # Download PDFkarrt suggestion <N> # Suggest N items based on order history to reach free pickupAll commands output JSON. Add -p for pretty-printed output:
node dist/cli.js search "Banane" -pPrices are in cents (e.g., currentRetailPrice: 85 = 0.85 EUR).
Want an AI agent to do your grocery shopping? Install the karrt agent skill:
npx skills add Tobi4s1337/karrt-skillThe skill works with Claude Code, Cursor, Codex, and 40+ other agents that support the Agent Skills spec.
Login creates a browser session stored in ~/.config/karrt/session.json. The session cookies (especially rstp) expire roughly every 10 minutes. When you get a 401/403 error, re-run karrt login.
All config is stored in ~/.config/karrt/:
session.json— Browser cookiesselected_store/selected_zip— Current storebasket-id— Active basket IDtotp-secret— TOTP secret for 2FAlogin-state.json— Login flow IPC
- Search is public — no authentication needed
- Everything else (basket, orders, timeslots) requires a valid session
- Login uses Playwright with stealth plugins to automate the REWE login page
- Turnstile CAPTCHA is solved by the 2Captcha browser extension running inside Chromium
- The login page sometimes shows a "continue with remembered account" prompt instead of the login form — both flows are handled automatically
- Cookies are extracted from the browser and reused for API calls via axios
- Session expires frequently (~10 min) — no automatic refresh yet
- The 2Captcha extension needs a few seconds to solve each CAPTCHA
- Checkout/payment is not yet implemented — you can build a basket and reserve a timeslot, but need to complete the order on rewe.de
- Only REWE Pickup is supported (not delivery)
- Category slugs may change if REWE reorganizes their product categories
MIT

