skills$openclaw/supermarkt-prijzen
cgnl7.2kā˜…

by cgnl

supermarkt-prijzen – OpenClaw Skill

supermarkt-prijzen is an OpenClaw Skills integration for coding workflows. Albert Heijn bonuses, product search, multi-store price comparison (12 supermarkets), recipe search by ingredients, and fridge scanner with vision AI.

7.2k stars8.1k forksSecurity L1
Updated Feb 7, 2026Created Feb 7, 2026coding

Skill Snapshot

namesupermarkt-prijzen
descriptionAlbert Heijn bonuses, product search, multi-store price comparison (12 supermarkets), recipe search by ingredients, and fridge scanner with vision AI. OpenClaw Skills integration.
ownercgnl
repositorycgnl/supermarkt-prijzen
languageMarkdown
licenseMIT
topics
securityL1
installopenclaw add @cgnl/supermarkt-prijzen
last updatedFeb 7, 2026

Maintainer

cgnl

cgnl

Maintains supermarkt-prijzen in the OpenClaw Skills directory.

View GitHub profile
File Explorer
42 files
.
_meta.json
286 B
ah-api.py
9.7 KB
ah-graphql-schema-full.md
253.8 KB
ah-mobile-auth.py
8.5 KB
ah-oauth-api.py
2.7 KB
ah-recipes.py
7.7 KB
auto-fetch-cookies.sh
1.8 KB
card-generator.py
987 B
check-card-offers.py
4.3 KB
checkjebon-search.py
5.9 KB
debug-api.py
898 B
exchange-code.py
1.5 KB
extract-cookies.sh
1.8 KB
find-search-query.py
1.8 KB
fridge-scan.sh
1.9 KB
get-bonuses-v2.py
9.3 KB
get-bonuses.py
5.8 KB
get-product-details.py
8.0 KB
graphql-fingerprint.txt
2.0 KB
GRAPHQL-INVESTIGATION.md
4.9 KB
improved-search.py
608 B
introspect.py
1.1 KB
list-queries.py
1.2 KB
oauth-flow.py
2.5 KB
README.md
2.3 KB
refresh-token.py
1.3 KB
setup-cookies.sh
267 B
SKILL.md
10.9 KB
smart-cook.sh
3.6 KB
test-allerhande-introspection.py
1.7 KB
test-bonuses-anonymous.py
1.8 KB
test-bonuskaart-detailed.sh
994 B
test-bonuskaart-smart.sh
1.3 KB
test-bonuskaart-validation.sh
897 B
test-full-search.py
1017 B
test-invalid-card.sh
1.6 KB
test-personal-bonus.py
2.6 KB
test-product-search-graphql.py
1.6 KB
test-products-graphql2.py
2.0 KB
test-real-search.py
1.0 KB
test-rest-search.py
899 B
test-search-full.py
1.0 KB
SKILL.md

name: supermarkt-prijzen description: Albert Heijn bonuses, product search, multi-store price comparison (12 supermarkets), recipe search by ingredients, and fridge scanner with vision AI. homepage: https://www.ah.nl metadata: {"openclaw":{"emoji":"šŸ›’","requires":{"bins":["python3","curl"]}}}

Albert Heijn API Skill

Complete AH bonussen + producten + recepten via GraphQL (web) en OAuth (mobile).

Features

āœ… Bonussen ophalen (GraphQL, 200+ items, geen login)
āœ… Producten zoeken (REST API, 20k+ items, geen login)
āœ… Recepten zoeken (GraphQL, geen login)
āœ… Multi-supermarkt prijsvergelijking (Checkjebon.nl - 12 supermarkten, 107k producten)
āœ… OAuth token flow (mobile API access - alleen voor persoonlijke data)
āœ… Fridge scanner (vision AI → recepten → shopping list)

Quick Start

1. Bonussen + Producten (GEEN LOGIN NODIG!)

Bonussen ophalen (200+ items):

./ah-api.py bonuses --filter WEB_BONUS_PAGE --pretty

Producten zoeken (20.000+ items):

./ah-api.py search --query "melk" --limit 10 --pretty

Recepten zoeken:

./ah-recipes.py search --query "pasta carbonara" --pretty

Recept ophalen via URL:

./ah-recipes.py url --url "https://www.ah.nl/allerhande/recept/R-R1187649/zoete-tortillachips" --pretty

✨ Alles werkt zonder cookies! Gebruikt curl-cffi met Chrome fingerprint.

2. OAuth Token Flow (mobile API)

Get initial token:

  1. Open Appie app
  2. Tap profiel → instellingen → scroll down → "Developer" (hidden option)
  3. Tap "OAuth Code" → copy code
  4. Run binnen 30 seconden:
curl -X POST 'https://api.ah.nl/mobile-auth/v1/auth/token' \
  -H 'Content-Type: application/json' \
  -H 'User-Agent: Appie/8.22.3' \
  -d '{"clientId":"appie","code":"PASTE_CODE_HERE"}'

Response:

{
  "access_token": "USERID_TOKEN",
  "refresh_token": "REFRESH_TOKEN",
  "expires_in": 604798
}

Save to ~/.ah_tokens.json:

echo '{"access_token":"...","refresh_token":"...","expires_in":604798}' > ~/.ah_tokens.json

Refresh token (na 7 dagen):

./refresh-token.py

3. Multi-store price comparison

Search across 12 supermarkets:

./checkjebon-search.py --compare "melk" --top 10

Stores: AH, Jumbo, Lidl, Plus, Dekamarkt, Spar, Dirk, Hoogvliet, Poiesz, Aldi, Vomar, Ekoplaza

Tools

ToolPurpose
ah-api.pyCookie-based bonussen + producten (GraphQL + REST)
ah-recipes.pyNEW! Recipe search by text or ingredients
fridge-scan.shNEW! Scan fridge with camera/peekaboo
smart-cook.shNEW! Complete workflow: scan → recipes → shopping
get-bonuses.pyLegacy bonus tool (GraphQL only)
checkjebon-search.pyMulti-store prijsvergelijking
refresh-token.pyOAuth token vernieuwen
setup-cookies.shCookie setup helper

Technical Details

Authentication (NONE NEEDED!)

Previous: Required session cookies from browser
Now: Uses curl-cffi with impersonate='chrome120'

How it works:

  • curl-cffi sends real Chrome TLS fingerprints
  • AH's bot detection sees it as a normal browser
  • No cookies, no login, no setup required! šŸŽ‰

Only needed for:

  • OAuth mobile API (receipts, personal data) - requires app login

Endpoint: https://www.ah.nl/gql

Query:

query FetchBonusPromotions($periodStart: String, $periodEnd: String) {
  bonusPromotions(
    filterSet: WEB_BONUS_PAGE
    input: {
      periodStart: "2026-02-01"
      periodEnd: "2026-02-08"
      filterUnavailableProducts: false
      forcePromotionVisibility: true
    }
  ) {
    id title promotionType
    price { now { amount } }
    product { title category }
  }
}

Available filters:

  • WEB_BONUS_PAGE - Alle bonussen (326 items!)
  • APP_PERSONAL - Persoonlijke aanbiedingen
  • APP_BONUS_BOX - Bonus box
  • COUPON - Kortingsbonnen
  • FREE_DELIVERY - Gratis bezorging
  • SPOTLIGHT - Spotlight aanbiedingen

REST Product Search

Endpoint: https://www.ah.nl/zoeken/api/products/search

Example:

curl 'https://www.ah.nl/zoeken/api/products/search?query=melk' \
  -H 'Cookie: SSOC=...; jsessionid_myah=...' \
  --user-agent 'Mozilla/5.0 (compatible; AH-Bot/1.0)'

Response:

{
  "cards": [
    {
      "products": [
        {
          "id": 441199,
          "title": "Campina Halfvolle melk",
          "price": { "now": 1.99, "unitSize": "1,5 l" }
        }
      ]
    }
  ]
}

OAuth Mobile API

Authorization: https://login.ah.nl/secure/oauth/authorize
Token exchange: https://api.ah.nl/mobile-auth/v1/auth/token
Token refresh: https://api.ah.nl/mobile-auth/v1/auth/token/refresh

Token lifetime: 7 days (604798 seconds)

Known endpoints (from gist):

  • /mobile-services/v1/receipts - All receipts
  • /mobile-services/v2/receipts/{id} - Specific receipt
  • /mobile-services/product/search/v2 - Product search

Note: Some mobile endpoints currently return 500 errors (infrastructure issues).

Why curl-cffi?

AH uses Cloudflare + Akamai bot detection. Normal requests → 403 Access Denied.

curl-cffi uses real Chrome TLS fingerprints:

from curl_cffi import requests
response = requests.get(url, impersonate="chrome120")  # ← Magic!

Checkjebon Multi-Store Data

Source: https://raw.githubusercontent.com/supermarkt/checkjebon/main/data/supermarkets.json

Stats:

  • File size: 10.3MB
  • Total products: 106,991
  • Daily updates
  • 24h local cache

Usage:

# Find cheapest
./checkjebon-search.py --compare "bier" --top 5

# Specific store
./checkjebon-search.py --query "campina" --store jumbo

# Show stats
./checkjebon-search.py --stats

Recipe Features (NEW!) šŸ³

Scan Fridge → Find Recipes → Shopping List

1. Scan your fridge:

./fridge-scan.sh
# Opens camera, captures fridge contents
# Output: /tmp/fridge-scan.jpg

2. Extract ingredients (via OpenClaw image tool):

# Ask assistant:
# "Analyze /tmp/fridge-scan.jpg and list all food items as comma-separated"
# → melk, eieren, tomaten, kaas, broccoli

3. Find recipes:

./ah-recipes.py ingredients --ingredients "melk,eieren,kaas,broccoli" --pretty

4. Get recipe details (by ID):

./ah-recipes.py details --recipe-id 1187649 --pretty

Or get recipe from URL directly:

./ah-recipes.py url --url "https://www.ah.nl/allerhande/recept/R-R1187649/zoete-tortillachips" --pretty

5. Complete workflow:

./smart-cook.sh
# Interactive: scan → analyze → find recipes → shopping list

Recipe ID Resolution

How to get recipe IDs:

  1. From search results: The search action returns titles only. To get full details, you need the recipe ID.
  2. From URL: Recipe URLs contain the ID in format R-R{ID}:
    • Example: https://www.ah.nl/allerhande/recept/R-R1187649/zoete-tortillachips
    • Extract: R-R1187649 → ID = 1187649
  3. Direct lookup: Use the url action to automatically extract ID and fetch details

Workflow:

# Step 1: Search for recipes (returns titles only)
./ah-recipes.py search --query "pasta carbonara" --pretty

# Step 2: If you have the recipe URL (e.g., from browser or website), extract ID
./ah-recipes.py url --url "https://www.ah.nl/allerhande/recept/R-R{ID}/{slug}" --pretty

# Note: Search results don't include recipe IDs (client-side rendered)
# To get full details, you need either:
#   - The direct recipe URL (contains R-R{ID})
#   - The recipe ID number

Recipe Search Examples

Search by text (returns IDs + titles):

./ah-recipes.py search --query "pasta carbonara" --size 10 --pretty
# Output: {"recipes": [{"id": 1200422, "title": "Klassieke spaghetti carbonara"}, ...], "total": 49, "hasMore": true}

Search with detailed info (cook time, ratings, images, servings):

./ah-recipes.py search --query "pasta carbonara" --size 5 --detailed --pretty
# Output: Full recipe summaries with time, ratings, images, servings

Search by ingredients:

./ah-recipes.py ingredients --ingredients "tomaat,ui,knoflook" --size 5 --pretty

Get recipe from URL:

./ah-recipes.py url --url "https://www.ah.nl/allerhande/recept/R-R1187649/zoete-tortillachips" --pretty
# Extracts recipe ID from URL (R-R1187649 → 1187649) and fetches full details

Examples

Cheapest melk across all stores:

./checkjebon-search.py --compare "melk" --top 5

AH bonussen vandaag:

./ah-api.py bonuses --filter WEB_BONUS_PAGE --pretty | \
  jq '.bonuses[] | select(.title | contains("Campina"))'

Search AH products:

./ah-api.py search --query "bier" --limit 20 --pretty

Troubleshooting

"Access Denied" errors:

  • Use curl-cffi (not standard requests)
  • Check User-Agent header
  • Refresh cookies (run ./setup-cookies.sh)

OAuth code expired:

  • Codes valid for only 30 seconds!
  • Use curl command immediately after generating code
  • Or use refresh_token to extend session

GraphQL errors:

  • Check date format (YYYY-MM-DD)
  • Verify filterSet value (case-sensitive)
  • Ensure cookies are fresh

Files

ah-bonuses/
ā”œā”€ā”€ SKILL.md              # This file
ā”œā”€ā”€ README.md             # Quick start
ā”œā”€ā”€ ah-api.py             # Main CLI tool (bonuses + search)
ā”œā”€ā”€ get-bonuses.py        # Legacy bonus tool
ā”œā”€ā”€ checkjebon-search.py  # Multi-store search
ā”œā”€ā”€ refresh-token.py      # OAuth token refresh
ā”œā”€ā”€ setup-cookies.sh      # Cookie extractor
└── ~/.ah_cookies.json    # Session cookies (gitignored)
└── ~/.ah_tokens.json     # OAuth tokens (gitignored)

Credits

  • AlbertPWN (userlandkernel) - Original mobile API research
  • TommasoAmici/ah-bonus-bot - Rust bot with product search endpoint
  • jabbink - Comprehensive API documentation gist
  • curl-cffi - Chrome fingerprinting library

Status

āœ… Bonussen API (GraphQL) - 100% working WITHOUT login! (200+ bonussen)
āœ… Product search (REST) - 100% working WITHOUT login! (20k+ producten)
āœ… Recipe search (GraphQL) - 100% working WITHOUT login!
āœ… Multi-store comparison (Checkjebon) - 100% working (107k products, 12 stores)
āœ… OAuth token flow - Working (7-day tokens, voor mobile API)
āš ļø Mobile API endpoints - Partial (some 500 errors)

Changelog

2026-02-02 - MAJOR UPDATE:

  • šŸŽ‰ Removed cookie requirement! All APIs now work WITHOUT login
  • āœ… Bonussen: 200+ items, anonymous access
  • āœ… Product search: 20k+ items, anonymous access
  • āœ… Recipes: Full search, anonymous access
  • šŸ”§ Uses curl-cffi with impersonate='chrome120' to bypass bot detection
  • šŸ—‘ļø Deprecated: setup-cookies.sh (no longer needed)
  • āš ļø OAuth still available for mobile API (receipts, personal data)

2026-02-01:

  • Added recipe search by ingredients
  • Added fridge scanner workflow
  • Multi-store comparison (Checkjebon.nl)

Last updated: 2026-02-02

README.md

Albert Heijn Bonuses Skill šŸ›’

Fetch your Albert Heijn bonuses programmatically! Bypasses bot detection using curl-cffi.

Quick Start

1. Install Dependencies

pip3 install curl-cffi --break-system-packages

2. Setup Cookies

./setup-cookies.sh

Follow the prompts to paste your browser cookies.

3. Fetch Bonuses!

# Get all bonuses
./get-bonuses.py --filter WEB_BONUS_PAGE --pretty

# Get personal bonuses only
./get-bonuses.py --filter APP_PERSONAL

# Save to file
./get-bonuses.py --filter WEB_BONUS_PAGE -o bonuses.json

Example Output

{
  "filter": "WEB_BONUS_PAGE",
  "count": 326,
  "fetched_at": "2026-02-01T20:57:00",
  "period": {
    "start": "2026-02-01",
    "end": "2026-02-08"
  },
  "bonuses": [
    {
      "id": "...",
      "title": "Innocent: gratis bezorging bij 12.50 euro",
      "subtitle": null,
      "promotionType": "INCENTIVE",
      "periodDescription": "vanaf maandag",
      "activationStatus": "NONE",
      "price": {
        "now": { "amount": 12.50 },
        "was": { "amount": 15.00 }
      },
      "product": {
        "title": "Innocent Smoothie",
        "category": "Dranken"
      }
    }
  ]
}

Usage from OpenClaw

# In your agent, just run:
exec ~/clawd/skills/ah-bonuses/get-bonuses.py --filter WEB_BONUS_PAGE

Then parse the JSON output!

Filters

  • WEB_BONUS_PAGE - All bonuses (most results)
  • APP_PERSONAL - Your personal offers
  • APP_BONUS_BOX - Bonus box offers
  • WEB_BONUS_BOX - Web bonus box
  • COUPON - Coupons
  • FREE_DELIVERY - Free delivery
  • SPOTLIGHT - Spotlight offers

Cookie Refresh

Cookies expire after ~1 hour. When you get errors:

./setup-cookies.sh

How It Works

  1. Uses curl-cffi with Chrome TLS fingerprinting to bypass bot detection
  2. Queries Albert Heijn GraphQL API (https://www.ah.nl/gql)
  3. Returns structured JSON with all bonus details

See SKILL.md for full documentation.

Troubleshooting

"Access Denied": → Cookies expired. Run ./setup-cookies.sh again.

Empty results: → Try different filter. WEB_BONUS_PAGE has the most bonuses.

Import error: → Install curl-cffi: pip3 install curl-cffi --break-system-packages

Credits

Built by Miel Monteur šŸ› ļø (Feb 2026)

Permissions & Security

Security level L1: Low-risk skills with minimal permissions. Review inputs and outputs before running in production.

Requirements

  • OpenClaw CLI installed and configured.
  • Language: Markdown
  • License: MIT
  • Topics:

FAQ

How do I install supermarkt-prijzen?

Run openclaw add @cgnl/supermarkt-prijzen in your terminal. This installs supermarkt-prijzen into your OpenClaw Skills catalog.

Does this skill run locally or in the cloud?

OpenClaw Skills execute locally by default. Review the SKILL.md and permissions before running any skill.

Where can I verify the source code?

The source repository is available at https://github.com/openclaw/skills/tree/main/skills/cgnl/supermarkt-prijzen. Review commits and README documentation before installing.