Gousto Meal Picker
Automates weekly Gousto recipe selection via their REST API. No browser needed for picking — only for initial auth and token refresh.
Setup
1. First-time auth (browser required)
Use agent-browser to log into Gousto and save session state:
agent-browser open "https://www.gousto.co.uk/my-gousto" --headed
# User logs in manually (CAPTCHA blocks automated login)
agent-browser state save <workspace>/gousto/gousto-auth.json
agent-browser close
2. Create config
Create <workspace>/gousto/config.json:
{
"userId": "<auth_user_id from /user/current>",
"numericUserId": "<numeric id>",
"deviceId": "<from gousto_session_id cookie>",
"subscriptionId": "<from subscription endpoint>",
"shippingAddressId": "<from order>",
"deliveryTariffId": "<from order>",
"plan": {
"mealsPerWeek": 4,
"portions": 2
},
"rules": {
"maxCookTimeMins": 45,
"maxMealsOver40Mins": 1,
"noNuts": true,
"noFish": true,
"maxPastaPerWeek": 1,
"maxRicePerWeek": 1,
"preferHealthy": true
}
}
No passwords or credentials are stored in config.json. Auth is handled entirely via browser cookies saved in gousto-auth.json (from the login step above). The config only contains Gousto account IDs and selection rules.
To discover IDs: log in via browser, then call GET /user/current and inspect a pending order via GET /order/v2/orders/<id>. See references/api.md for endpoint details.
3. Initialise selections tracker
Create <workspace>/gousto/selections.json:
{ "selections": {} }
Usage
Run the picker
node <skill-dir>/scripts/gousto-pick.mjs [--dry-run] [--week ORDER_ID]
--dry-run— show what would be selected without updating the order--week ORDER_ID— target a specific order instead of auto-detecting
Recommended cron schedule
Gousto menus open on Tuesdays at 12pm UK, 13 days before Monday delivery. Schedule the picker for Tuesdays at 1pm UK:
cron: "0 13 * * 2" (Europe/London)
Token refresh
Auth tokens expire ~10 hours after login. When the token expires, the agent should:
- Open Gousto in agent-browser (loads saved state → auto-refreshes)
- Save updated state:
agent-browser state save <workspace>/gousto/gousto-auth.json - Retry the script
Auth endpoints are WAF-protected — curl cannot hit /oauth/access-token or /login directly. Browser-based refresh is the only reliable method.
Selection Rules (all configurable)
All rules are set in config.json under "rules". Every filter can be toggled on/off.
Hard filters (set to true to exclude)
| Rule | Default | Description |
|---|---|---|
noNuts | true | Exclude recipes containing nuts (checks allergens + name) |
noFish | true | Exclude fish dishes |
fishAndChipsException | false | Allow fish & chips even when noFish is true |
noSeafood | false | Exclude all seafood (broader: crab, lobster, squid, etc.) |
noVegetarian | true | Exclude vegetarian meals |
noPlantBased | true | Exclude plant-based/vegan meals |
noDairy | false | Exclude dairy-containing meals |
noGluten | false | Exclude gluten-containing meals |
maxCookTimeMins | 45 | Exclude recipes over this cook time |
excludeAllergens | [] | Array of Gousto allergen slugs to exclude (e.g. ["sesame", "celery"]) |
excludeKeywords | [] | Exclude recipes whose name contains any of these strings |
Soft constraints (limits per week)
| Rule | Default | Description |
|---|---|---|
maxMealsOver40Mins | 1 | Max meals with 40+ min cook time |
maxPastaPerWeek | 1 | Max pasta dishes |
maxRicePerWeek | 1 | Max rice dishes |
maxSameProtein | 2 | Max meals with the same protein |
Scoring preferences
| Rule | Default | Description |
|---|---|---|
preferHealthy | true | Boost healthy/low-cal recipes, penalise high-cal |
preferQuicker | true | Boost faster cook times |
Example config
{
"rules": {
"noNuts": true,
"noFish": false,
"noVegetarian": false,
"maxCookTimeMins": 30,
"maxPastaPerWeek": 2,
"excludeKeywords": ["spicy", "chilli"],
"excludeAllergens": ["sesame"],
"preferHealthy": false
}
}
Security notes
- No passwords stored — auth uses browser cookies only (saved in
gousto-auth.json) - Treat
gousto-auth.jsonas sensitive — it contains OAuth tokens. Restrict file permissions (chmod 600) - Single API endpoint — the script only communicates with
production-api.gousto.co.uk - Use
--dry-runfirst — verify selections before enabling automated ordering - Required runtime — Node.js, curl, zsh shell, and agent-browser (for login/token refresh only)
File structure
gousto/
├── config.json — User config, API IDs, dietary rules
├── gousto-auth.json — Browser state (cookies with Bearer token)
├── selections.json — History of selections made