Automates weekly Gousto recipe selection via their REST API. No browser needed for picking — only for initial auth and token refresh.
Use agent-browser to log into Gousto and save session state:
bash
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
Create <workspace>/gousto/config.json:
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.
Create <workspace>/gousto/selections.json:
json
{ "selections": {} }
bash
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-detectingGousto menus open on Tuesdays at 12pm UK, 13 days before Monday delivery. Schedule the picker for Tuesdays at 1pm UK:
text
cron: "0 13 * * 2" (Europe/London)
Auth tokens expire ~10 hours after login. When the token expires, the agent should:
agent-browser state save <workspace>/gousto/gousto-auth.jsonAuth endpoints are WAF-protected — curl cannot hit /oauth/access-token or /login directly. Browser-based refresh is the only reliable method.
All rules are set in config.json under "rules". Every filter can be toggled on/off.
true to exclude)#RuleDefaultDescriptionnoNuts``trueExclude recipes containing nuts (checks allergens + name)noFish``trueExclude fish dishesfishAndChipsException``falseAllow fish & chips even when noFish is truenoSeafood``falseExclude all seafood (broader: crab, lobster, squid, etc.)noVegetarian``trueExclude vegetarian mealsnoPlantBased``trueExclude plant-based/vegan mealsnoDairy``falseExclude dairy-containing mealsnoGluten``falseExclude gluten-containing mealsmaxCookTimeMins``45Exclude recipes over this cook timeexcludeAllergens``[]Array of Gousto allergen slugs to exclude (e.g. ["sesame", "celery"])excludeKeywords``[]Exclude recipes whose name contains any of these strings
RuleDefaultDescriptionmaxMealsOver40Mins``1Max meals with 40+ min cook timemaxPastaPerWeek``1Max pasta dishesmaxRicePerWeek``1Max rice dishesmaxSameProtein``2Max meals with the same protein
RuleDefaultDescriptionpreferHealthy``trueBoost healthy/low-cal recipes, penalise high-calpreferQuicker``trueBoost faster cook times
json
{
"rules": {
"noNuts": true,
"noFish": false,
"noVegetarian": false,
"maxCookTimeMins": 30,
"maxPastaPerWeek": 2,
"excludeKeywords": ["spicy", "chilli"],
"excludeAllergens": ["sesame"],
"preferHealthy": false
}
}
gousto-auth.json)gousto-auth.json as sensitive — it contains OAuth tokens. Restrict file permissions ( chmod 600)production-api.gousto.co.uk--dry-run first — verify selections before enabling automated orderingtext
gousto/
├── config.json — User config, API IDs, dietary rules
├── gousto-auth.json — Browser state (cookies with Bearer token)
├── selections.json — History of selections made