Install
openclaw skills install @jdm0830/espn-fantasyLog into ESPN (Disney One-ID) and manage an ESPN Fantasy Football team via the ESPN Fantasy API. Use when the user asks to log in to, manage, set a lineup for, add/drop players on, or check their ESPN fantasy team, or when an ESPN session/cookie has gone stale and needs re-authentication. Runs a single real HEADED browser on a virtual display (TigerVNC), handles the Disney One-ID iframe login, email 2FA code handoff, and persists a reusable browser profile + the espn_s2 / SWID cookies the fantasy API needs.
openclaw skills install @jdm0830/espn-fantasyGet a durable, logged-in ESPN session, then drive the team through the ESPN Fantasy API instead of clicking around the site.
chrome-headless-shell ("Max challenge attempts exceeded"). If the box
has no usable display, start a virtual headed display with TigerVNC:
scripts/start-display.sh :1, then run the browser with DISPLAY=:1 HEADED=1.state/espn-profile/ and is reused every run — you log in once, not every time. Also save
espn_s2 + SWID to .secrets/espn-cookies.txt for API use.ESPN_PROFILE=state/espn-profile-fresh); a clean profile loads
the login form fine..secrets/ (600, root-only).pkill -f login-interactive matches the calling shell
and SIGTERMs your own command. Use kill <pid> (or pgrep -x node + /proc/<pid>/cmdline).cd skills/espn-fantasy/scripts
./start-display.sh :1 # starts Xvnc on :1, no-auth, localhost-only
DISPLAY=:1 XAUTHORITY=$HOME/.Xauthority HEADED=1 FULLCHROME=1 node login-interactive.mjs &
.secrets/espn-login.txt (ESPN_USER=, ESPN_PASS=).state/espn-profile/.state/espn-login.log; live screenshot state/espn-live.png..secrets/espn-cookies.txt and logs SUCCESS.The account has email 2FA. When the log shows 2FA_PROMPT active, ask the user for the code
from their email and drop it on disk:
printf '123456' > state/espn-2fa-code.txt
The running script picks it up within ~3s (it waits up to 45 min). Code = single-use, ~10 min TTL.
Load .secrets/espn-cookies.txt (espn_s2, SWID) and call the fantasy API. See
references/espn-fantasy-api.md.
| Var | Effect |
|---|---|
HEADED=1 | run the real headed browser (required) |
DISPLAY=:1 | the VNC virtual display |
FULLCHROME=1 | use full Chromium build (needed for headless; harmless headed) |
ESPN_PROFILE=<dir> | override profile dir (use for a fresh, un-poisoned profile) |
Never poll the ESPN API from the model (token burn + bot risk). Instead run scripts/monitor.mjs
on a systemd user timer. It diffs the league feed and appends only NEW events to
state/espn-alerts.jsonl; a quiet run produces nothing.
Watches: incoming/pending trade proposals, newly executed transactions (waivers, FA adds/drops, completed trades), and injury-status changes on the user's roster.
Install (units already on this box):
~/.config/systemd/user/espn-monitor.service # Type=oneshot -> node monitor.mjs
~/.config/systemd/user/espn-monitor.timer # OnUnitActiveSec=12min
systemctl --user enable --now espn-monitor.timer
Surface alerts cheaply from a heartbeat: if state/espn-alerts.jsonl is non-empty, relay it to
the user then truncate; if empty, stay silent.
scripts/start-display.sh — start the virtual headed display (Xvnc).scripts/lib.mjs — browser launcher: persistent profile, headed/full-Chromium modes,
stealth init.scripts/login-interactive.mjs — full flow: iframe fill, 2FA wait, rate-limit backoff,
cookie capture.scripts/tx.mjs — WRITE helper: setLineup, addDrop, quickLineup (uses the verified
bare-transaction format).scripts/monitor.mjs — no-LLM league watcher (diff -> alerts file).references/login-flow.md — exact selectors, failure modes, timings.references/strategy.md — team-management strategy (weekly rhythm, start/sit, waivers,
trades/trade-radar, monitoring cron design), open questions, current status, rollout phases.references/espn-fantasy-api.md — fantasy API endpoints for reading/managing a team.