Steam Idle Bot with Trading Card Support
Project description
Farm Steam playtime and trading-card drops on autopilot. Steam Idle Bot syncs your library, idles only the games that still have cards to drop, and remembers what's already finished — so every run scans less and starts faster. Live terminal dashboard, web UI, two interchangeable idling backends with automatic fallback.
Why it's different
Most idlers blindly run every game forever. Steam Idle Bot is accurate and self-pruning:
| 🎴 Drops only where it matters | Detects which games have trading cards and how many drops remain — idles just those, never wasting a slot on a drained game. |
| 🧠 Learns over time | Persistent no-drop caches record fully-farmed games; short-lived positive caches avoid re-scraping active games every refresh. |
| 🔐 Accurate by design | Verifies the Steam web session is genuinely logged in before trusting it; auto-recovers a valid session from a browser you're signed into. |
| 🖥️ Readable output | Live panel of game names, cards remaining and idle time; structured session report + optional JSON/Markdown checkpoints. |
| 🔁 Two backends, one interface | Built-in Python client (Steam Guard / 2FA) or a local steam-utility install — with transparent fallback if one fails. |
| 🔄 Rotates when cards drain | Inventory snapshots can prove a game dropped all known remaining cards before badge pages catch up, so refreshes can replace it mid-session. |
| ⚡ Modern & tested | uv-managed, fully typed, 560 tests across Python 3.12–3.14. |
Quick start
# 1. Install uv (if needed)
curl -LsSf https://astral.sh/uv/install.sh | sh
# 2. Clone & install
git clone https://github.com/bernardopg/steam-idler-python.git
cd steam-idler-python
uv sync
# 3. Configure (never commit the filled .env)
cp .env.example .env
# edit .env → USERNAME, PASSWORD, and ideally STEAM_API_KEY
# 4. Preview without contacting Steam
./run.sh --dry-run
# 5. Run it — terminal, or ./run-web.sh for the web UI
./run.sh
💡 A free Steam Web API key unlocks automatic library sync and badge-based filtering. Without it the bot still runs — it just can't filter as precisely.
How it works
The orchestrator wires a configuration layer to a swappable idling backend and three card services, then drives a refresh loop that tracks drops as they drain.
Game selection is a funnel — each stage narrows the set, capped at Steam's hard limit of 32:
Common commands
./run.sh # run normally (terminal)
./run.sh --dry-run # print config + chosen games, no Steam contact
./run.sh --no-trading-cards # skip trading-card filtering
./run.sh --max-games 10 # cap idled games
./run.sh --refresh-interval-seconds 300 # re-run selection every 5 min
./run.sh --checkpoint-minutes 5 --duration-minutes 25 # timed run + JSON/MD checkpoints
./run.sh --stop-app-ids "570,730" # stop steam-utility idles for those App IDs and exit
STEAM_IDLE_SKIP_SYNC=1 ./run.sh # skip the runner's preflight uv sync
STEAM_IDLE_RUNNER_VERBOSE=1 ./run.sh # show uv sync output while preparing the environment
./run.sh keeps the Python bot out of a shell pipeline so Ctrl+C reaches it directly, writes bot output to logs/runs/run_*.log, and prints a short startup/exit banner. By default it clears stale exported Steam Idle Bot environment overrides so .env wins; set STEAM_IDLE_PRESERVE_ENV=1 when you intentionally want exported variables to override .env.
Full flag and setting reference: USAGE guide.
Configuration
Settings come from environment variables / a .env file (copy .env.example). The two
required values are USERNAME and PASSWORD; everything else has sane defaults.
| Key | Default | Purpose |
|---|---|---|
STEAM_API_KEY |
— | Library sync + badge filtering (recommended) |
IDLING_BACKEND |
python |
python or steam_utility |
MAX_GAMES_TO_IDLE |
30 |
Cap (Steam hard limit: 32) |
REFRESH_INTERVAL_SECONDS |
600 |
How often the selection pipeline re-runs |
CHECKPOINT_MINUTES |
0 |
Write JSON/MD checkpoints every N min (0 = off) |
DURATION_MINUTES |
0 |
Stop after N min (0 = run until interrupted) |
POST_RUN_VERIFY_SECONDS |
0 |
Re-scrape card counts N s after stopping |
AUTO_BROWSER_COOKIES |
true |
Recover a community session from a logged-in browser |
🔐 Card-drop filtering needs an authenticated
web:communitysession. See the authentication & accuracy guide.
Documentation
| 🇺🇸 English | 🇧🇷 Português (BR) | |
|---|---|---|
| Full guide | README | README |
| Command sheet | USAGE | USAGE |
| Security | SECURITY | SECURITY |
| Roadmap & backlog | BACKLOG | BACKLOG |
Requirements
- Python 3.12+ — managed for you by
uv - A Steam account with games that have trading cards
- Steam Web API key (recommended) — library sync + badge data
- For drop filtering — an authenticated Steam web session
Contributing
Contributions welcome in both languages. Run uv run ruff check . && uv run mypy src && uv run pytest -q
before opening a PR. See the developer guides:
🇺🇸 English · 🇧🇷 Português.
The prioritized roadmap lives in BACKLOG.md.
License
MIT — see LICENSE. Not affiliated with Valve. Use responsibly and follow Steam's Terms of Service.
Project details
Release history Release notifications | RSS feed
Download files
Download the file for your platform. If you're not sure which to choose, learn more about installing packages.
Source Distribution
Built Distribution
Filter files by name, interpreter, ABI, and platform.
If you're not sure about the file name format, learn more about wheel file names.
Copy a direct link to the current filters
File details
Details for the file steam_idle_bot-1.0.0.tar.gz.
File metadata
- Download URL: steam_idle_bot-1.0.0.tar.gz
- Upload date:
- Size: 259.2 kB
- Tags: Source
- Uploaded using Trusted Publishing? Yes
- Uploaded via: twine/6.1.0 CPython/3.13.14
File hashes
| Algorithm | Hash digest | |
|---|---|---|
| SHA256 |
cbc95746dbfa4d7c54c55da9cb2d0761cf5c7ef9c75ca3d6fa4cd2b67b1b58bb
|
|
| MD5 |
720067c97441fb77205b63e0d7638588
|
|
| BLAKE2b-256 |
af7eba3de0effc6ae0562d8e4b845b0ebe98d0a0f5b379231b3b630b0569be1a
|
Provenance
The following attestation bundles were made for steam_idle_bot-1.0.0.tar.gz:
Publisher:
release.yml on bernardopg/steam-idler-python
-
Statement:
-
Statement type:
https://in-toto.io/Statement/v1 -
Predicate type:
https://docs.pypi.org/attestations/publish/v1 -
Subject name:
steam_idle_bot-1.0.0.tar.gz -
Subject digest:
cbc95746dbfa4d7c54c55da9cb2d0761cf5c7ef9c75ca3d6fa4cd2b67b1b58bb - Sigstore transparency entry: 2208111628
- Sigstore integration time:
-
Permalink:
bernardopg/steam-idler-python@dd3d3c9da9ead4e5995d032cc1c85eee3f4d59be -
Branch / Tag:
refs/tags/v1.0.0 - Owner: https://github.com/bernardopg
-
Access:
public
-
Token Issuer:
https://token.actions.githubusercontent.com -
Runner Environment:
github-hosted -
Publication workflow:
release.yml@dd3d3c9da9ead4e5995d032cc1c85eee3f4d59be -
Trigger Event:
push
-
Statement type:
File details
Details for the file steam_idle_bot-1.0.0-py3-none-any.whl.
File metadata
- Download URL: steam_idle_bot-1.0.0-py3-none-any.whl
- Upload date:
- Size: 71.0 kB
- Tags: Python 3
- Uploaded using Trusted Publishing? Yes
- Uploaded via: twine/6.1.0 CPython/3.13.14
File hashes
| Algorithm | Hash digest | |
|---|---|---|
| SHA256 |
fe12c0d3dda731aa0d67e4293214bc8bfe8c65b018de894d00138d7e1092e5b6
|
|
| MD5 |
3cbbb4cc92109a4009854ede9dbe9658
|
|
| BLAKE2b-256 |
1d330eb1a092e657b6a38eddb8777012d3027b326811c1a570d8605b045cebae
|
Provenance
The following attestation bundles were made for steam_idle_bot-1.0.0-py3-none-any.whl:
Publisher:
release.yml on bernardopg/steam-idler-python
-
Statement:
-
Statement type:
https://in-toto.io/Statement/v1 -
Predicate type:
https://docs.pypi.org/attestations/publish/v1 -
Subject name:
steam_idle_bot-1.0.0-py3-none-any.whl -
Subject digest:
fe12c0d3dda731aa0d67e4293214bc8bfe8c65b018de894d00138d7e1092e5b6 - Sigstore transparency entry: 2208111971
- Sigstore integration time:
-
Permalink:
bernardopg/steam-idler-python@dd3d3c9da9ead4e5995d032cc1c85eee3f4d59be -
Branch / Tag:
refs/tags/v1.0.0 - Owner: https://github.com/bernardopg
-
Access:
public
-
Token Issuer:
https://token.actions.githubusercontent.com -
Runner Environment:
github-hosted -
Publication workflow:
release.yml@dd3d3c9da9ead4e5995d032cc1c85eee3f4d59be -
Trigger Event:
push
-
Statement type: