This repo monitors Arc'teryx Outlet products and sends a Telegram alert when a target size goes from out of stock → in stock. By default, it also alerts when a product+size is first seen and is already in stock (e.g. first run or newly listed products). The primary entrypoint is watch_stock.py.
- Scrapes a category page (e.g. men's footwear) to collect product URLs (via Selenium).
- Fetches each product page and parses the embedded
__NEXT_DATA__JSON (viarequests). - Checks variant stock status for your target size(s).
- Sends Telegram alerts on restock events (and optionally repeats).
./setup.sh
cp stock_watch_config.example.json stock_watch_config.json
# Telegram (optional but recommended)
export TELEGRAM_BOT_TOKEN="123456789:replace-me"
export TELEGRAM_CHAT_ID="123456789" # or TELEGRAM_CHAT_IDS="id1,id2"
./run.shrun.sh behavior:
- If you pass
--config ..., it forwards args towatch_stock.py. - Else, if
stock_watch_config.jsonexists, it runswatch_stock.py --config stock_watch_config.json. - Else, it runs
watch_stock.pywith CLI defaults.
- Python 3.7+
- If you use
category_url: Google Chrome / Chromium installed (Selenium will manage the driver automatically on recent Selenium versions).
On a Linux server (Ubuntu example), you typically need Chrome/Chromium and common libraries. If Chrome fails to start, install the missing deps indicated in the error log.
Environment variables:
TELEGRAM_BOT_TOKENTELEGRAM_CHAT_ID(single) orTELEGRAM_CHAT_IDS(comma-separated)
The notifier is implemented in telegram_notifier.py.
Copy the example and edit it:
cp stock_watch_config.example.json stock_watch_config.jsondata_dir: where state is stored (defaultdata)state_file: persisted baseline + history (defaultdata/stock_watch_state.json)log_file: log path (defaultlogs/watch_stock.log)log_level:DEBUG|INFO|WARNING|ERRORshow_browser: settrueto run a visible browser (debugging category scraping)render_wait_seconds: seconds to wait after opening category pagescroll_times: how many times to scroll the category page (lazy-load)notify_on_first_run:trueby default (alert when a product+size is first seen in stock; setfalseto only alert on out-of-stock → in-stock transitions after baseline)max_products: global cap (0 = no limit)no_category_prefilter: iffalse, keywords are pre-filtered using category tile text to reduce product-page requestsrepeat.max_notifications_per_item: max alerts per product+size per “restock cycle” (min 1)repeat.repeat_interval_seconds: minimum seconds between repeated alerts (0 = no limit)error_notify.enabled: send a Telegram alert when scraping fails (network errors, blocking, parsing failures)error_notify.repeat_interval_seconds: throttle repeated error alerts across runs (0 = no limit)
You can define multiple independent watches. Each watch supports:
name: label for logs/alertscategory_url: category page URL to scrape (requires Selenium + Chrome)product_urls: optional explicit product URLs; if provided, category scraping is skippedkeywords: list of keywords to match (case-insensitive)sizes: list of size labels to monitor (e.g.["8","8.5"]or["M","L"])max_products: per-watch cap (0 = no limit)no_category_prefilter: overrideno_category_prefilterfor this watch
{
"version": 1,
"data_dir": "data",
"state_file": "data/stock_watch_state.json",
"log_file": "logs/watch_stock.log",
"log_level": "INFO",
"show_browser": false,
"render_wait_seconds": 10,
"scroll_times": 3,
"notify_on_first_run": true,
"repeat": {
"max_notifications_per_item": 3,
"repeat_interval_seconds": 1800
},
"error_notify": {
"enabled": true,
"repeat_interval_seconds": 3600
},
"watches": [
{
"name": "shoes-gtx",
"category_url": "https://outlet.arcteryx.com/ca/en/c/mens/footwear",
"keywords": ["waterproof", "gtx", "gore-tex"],
"sizes": ["8", "8.5"],
"max_products": 0,
"no_category_prefilter": false
}
]
}python3 watch_stock.py \
--category-url "https://outlet.arcteryx.com/ca/en/c/mens/footwear" \
--size 8 \
--keyword waterproof --keyword gtx --keyword gore-texUseful flags:
--dry-run: do everything except sending Telegram--no-notify-on-first-run: disable alerts for first-seen in-stock items--no-category-prefilter: fetch all product pages and match keywords there (more requests, more coverage)--show-browser: debug category scraping with a visible browser
data/stock_watch_state.json: baseline + per-product statelogs/watch_stock.log: logs
crontab -eRun every 30 minutes:
*/30 * * * * cd $HOME/arcteryx-monitor && ./run.sh >> logs/watch_stock.log 2>&1- Selenium/Chrome fails to start: install Chrome/Chromium and the missing system libraries; check
logs/watch_stock.logandlogs/chromedriver.log. - No products found on category page: increase
render_wait_seconds, increasescroll_times, or run with--show-browserto inspect the page. - Too many requests: keep a reasonable schedule (e.g. 30–60 minutes) and avoid aggressive scraping.
monitor_unified.pycan also run catalog-change monitoring, but the repo is optimized forwatch_stock.py.- Other scripts in the repo are legacy/deprecated and not maintained.